summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llui/llmenugl.cpp4
-rw-r--r--indra/llui/llmenugl.h4
-rw-r--r--indra/newview/CMakeLists.txt2
-rw-r--r--indra/newview/llavataractions.cpp4
-rw-r--r--indra/newview/llcallingcard.cpp42
-rw-r--r--indra/newview/llcallingcard.h14
-rw-r--r--indra/newview/llfavoritesbar.cpp121
-rw-r--r--indra/newview/llfloaterreporter.cpp1
-rw-r--r--indra/newview/llfolderviewitem.cpp2
-rw-r--r--indra/newview/llfriendcard.cpp425
-rw-r--r--indra/newview/llfriendcard.h143
-rw-r--r--indra/newview/llinventorybridge.cpp54
-rw-r--r--indra/newview/llinventorybridge.h31
-rw-r--r--indra/newview/llmenucommands.cpp1
-rw-r--r--indra/newview/llpanellandmarks.cpp1
-rw-r--r--indra/newview/llpanellandmarks.h5
-rw-r--r--indra/newview/llpanelpeople.cpp41
-rw-r--r--indra/newview/llpanelpeople.h4
-rw-r--r--indra/newview/llpanelplaces.cpp2
-rw-r--r--indra/newview/llpreview.cpp1
-rw-r--r--indra/newview/llpreviewanim.cpp1
-rw-r--r--indra/newview/llpreviewsound.cpp1
-rw-r--r--indra/newview/llpreviewtexture.cpp3
-rw-r--r--indra/newview/llsidetray.cpp13
-rw-r--r--indra/newview/llstartup.cpp10
-rw-r--r--indra/newview/llstatusbar.cpp5
-rw-r--r--indra/newview/llstatusbar.h2
-rw-r--r--indra/newview/lltooldraganddrop.cpp1
-rw-r--r--indra/newview/llviewerinventory.cpp6
-rw-r--r--indra/newview/llviewerinventory.h2
-rw-r--r--indra/newview/llviewertexteditor.cpp1
-rw-r--r--indra/newview/llviewerwindow.cpp1
-rw-r--r--indra/newview/llvoavatar.cpp36
-rw-r--r--indra/newview/llvoavatarself.cpp1
-rw-r--r--indra/newview/skins/default/xui/en/panel_people.xml12
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml4
36 files changed, 844 insertions, 157 deletions
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index 4edae46f32..d6dfe6c198 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -1642,6 +1642,7 @@ LLMenuGL::LLMenuGL(const LLMenuGL::Params& p)
mHorizontalLayout( p.horizontal_layout ),
mScrollable(mHorizontalLayout ? FALSE : p.scrollable), // Scrolling is supported only for vertical layout
mMaxScrollableItems(p.max_scrollable_items),
+ mPreferredWidth(p.preferred_width),
mKeepFixedSize( p.keep_fixed_size ),
mLabel (p.label),
mLastMouseX(0),
@@ -2025,6 +2026,9 @@ void LLMenuGL::arrange( void )
}
}
+ if (mPreferredWidth < U32_MAX)
+ width = llmin(mPreferredWidth, max_width);
+
if (mScrollable)
{
S32 max_items_height = max_height - spillover_item_height * 2;
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index 44459a6c0e..0bf6301f93 100644
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -383,6 +383,7 @@ public:
keep_fixed_size,
scrollable;
Optional<U32> max_scrollable_items;
+ Optional<U32> preferred_width;
Optional<LLUIColor> bg_color;
Optional<S32> shortcut_pad;
@@ -396,7 +397,9 @@ public:
bg_color("bg_color", LLUIColorTable::instance().getColor( "MenuDefaultBgColor" )),
scrollable("scrollable", false),
max_scrollable_items("max_scrollable_items", U32_MAX),
+ preferred_width("preferred_width", U32_MAX),
shortcut_pad("shortcut_pad")
+
{
addSynonym(bg_visible, "opaque");
addSynonym(bg_color, "color");
@@ -544,6 +547,7 @@ protected:
S32 mMouseVelX;
S32 mMouseVelY;
U32 mMaxScrollableItems;
+ U32 mPreferredWidth;
BOOL mHorizontalLayout;
BOOL mScrollable;
BOOL mKeepFixedSize;
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 43d5f70b2f..9878a71d89 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -213,6 +213,7 @@ set(viewer_SOURCE_FILES
llfolderview.cpp
llfolderviewitem.cpp
llfollowcam.cpp
+ llfriendcard.cpp
llgesturemgr.cpp
llgivemoney.cpp
llglsandbox.cpp
@@ -668,6 +669,7 @@ set(viewer_HEADER_FILES
llfoldervieweventlistener.h
llfolderviewitem.h
llfollowcam.h
+ llfriendcard.h
llgesturemgr.h
llgivemoney.h
llgroupactions.h
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index 4e289efd1b..5f71b6e3f6 100644
--- a/indra/newview/llavataractions.cpp
+++ b/indra/newview/llavataractions.cpp
@@ -42,7 +42,7 @@
#include "llagent.h"
#include "llappviewer.h" // for gLastVersionChannel
#include "llcallingcard.h" // for LLAvatarTracker
-#include "llinventorymodel.h"
+#include "llinventorymodel.h" // for gInventory.findCategoryUUIDForType
#include "llimview.h" // for gIMMgr
#include "llsidetray.h"
#include "llviewermessage.h" // for handle_lure
@@ -229,8 +229,6 @@ bool LLAvatarActions::handleRemove(const LLSD& notification, const LLSD& respons
}
LLAvatarTracker::instance().terminateBuddy(id);
LLAvatarTracker::instance().notifyObservers();
- gInventory.addChangedMask(LLInventoryObserver::LABEL | LLInventoryObserver::CALLING_CARD, LLUUID::null);
- gInventory.notifyObservers();
break;
case 1: // NO
diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp
index 355a90209a..7326e39af3 100644
--- a/indra/newview/llcallingcard.cpp
+++ b/indra/newview/llcallingcard.cpp
@@ -95,29 +95,8 @@ const F32 OFFLINE_SECONDS = FIND_FREQUENCY + 8.0f;
// static
LLAvatarTracker LLAvatarTracker::sInstance;
-/*
-class LLAvatarTrackerInventoryObserver : public LLInventoryObserver
-{
-public:
- LLAvatarTrackerInventoryObserver(LLAvatarTracker* at) :
- mAT(at) {}
- virtual ~LLAvatarTrackerInventoryObserver() {}
- virtual void changed(U32 mask);
-protected:
- LLAvatarTracker* mAT;
-};
-*/
-/*
-void LLAvatarTrackerInventoryObserver::changed(U32 mask)
-{
- // if there's a calling card change, just do it.
- if((mask & LLInventoryObserver::CALLING_CARD) != 0)
- {
- mAT->inventoryChanged();
- }
-}
-*/
+
///----------------------------------------------------------------------------
/// Class LLAvatarTracker
@@ -329,7 +308,8 @@ void LLAvatarTracker::terminateBuddy(const LLUUID& id)
msg->nextBlock("ExBlock");
msg->addUUID("OtherID", id);
gAgent.sendReliableMessage();
- mModifyMask |= LLFriendObserver::REMOVE;
+
+ addChangedMask(LLFriendObserver::REMOVE, id);
delete buddy;
}
@@ -503,6 +483,18 @@ void LLAvatarTracker::notifyObservers()
(*it)->changed(mModifyMask);
}
mModifyMask = LLFriendObserver::NONE;
+ mChangedBuddyIDs.clear();
+}
+
+// store flag for change
+// and id of object change applies to
+void LLAvatarTracker::addChangedMask(U32 mask, const LLUUID& referent)
+{
+ mModifyMask |= mask;
+ if (referent.notNull())
+ {
+ mChangedBuddyIDs.insert(referent);
+ }
}
void LLAvatarTracker::applyFunctor(LLRelationshipFunctor& f)
@@ -706,7 +698,7 @@ void LLAvatarTracker::formFriendship(const LLUUID& id)
//visible online to each other.
buddy_info = new LLRelationship(LLRelationship::GRANT_ONLINE_STATUS,LLRelationship::GRANT_ONLINE_STATUS, false);
at.mBuddyInfo[id] = buddy_info;
- at.mModifyMask |= LLFriendObserver::ADD;
+ at.addChangedMask(LLFriendObserver::ADD, id);
at.notifyObservers();
}
}
@@ -722,7 +714,7 @@ void LLAvatarTracker::processTerminateFriendship(LLMessageSystem* msg, void**)
LLRelationship* buddy = get_ptr_in_map(at.mBuddyInfo, id);
if(!buddy) return;
at.mBuddyInfo.erase(id);
- at.mModifyMask |= LLFriendObserver::REMOVE;
+ at.addChangedMask(LLFriendObserver::REMOVE, id);
delete buddy;
at.notifyObservers();
}
diff --git a/indra/newview/llcallingcard.h b/indra/newview/llcallingcard.h
index 85a1ab6e1e..113f16de70 100644
--- a/indra/newview/llcallingcard.h
+++ b/indra/newview/llcallingcard.h
@@ -147,6 +147,17 @@ public:
void removeObserver(LLFriendObserver* observer);
void notifyObservers();
+ /**
+ * Stores flag for change and id of object change applies to
+ *
+ * This allows outsiders to tell the AvatarTracker if something has
+ * been changed 'under the hood',
+ * and next notification will have exact avatar IDs have been changed.
+ */
+ void addChangedMask(U32 mask, const LLUUID& referent);
+
+ const std::set<LLUUID>& getChangedIDs() { return mChangedBuddyIDs; }
+
// Apply the functor to every buddy. Do not actually modify the
// buddy list in the functor or bad things will happen.
void applyFunctor(LLRelationshipFunctor& f);
@@ -179,6 +190,9 @@ protected:
buddy_map_t mBuddyInfo;
+ typedef std::set<LLUUID> changed_buddy_t;
+ changed_buddy_t mChangedBuddyIDs;
+
typedef std::vector<LLFriendObserver*> observer_list_t;
observer_list_t mObservers;
diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
index 70ee5d395e..7ad60232c7 100644
--- a/indra/newview/llfavoritesbar.cpp
+++ b/indra/newview/llfavoritesbar.cpp
@@ -61,6 +61,55 @@ static LLDefaultChildRegistry::Register<LLFavoritesBarCtrl> r("favorites_bar");
const S32 DROP_DOWN_MENU_WIDTH = 250;
/**
+ * Helper for LLFavoriteLandmarkButton and LLFavoriteLandmarkMenuItem.
+ * Performing requests for SLURL for given Landmark ID
+ */
+class LLSLURLGetter
+{
+public:
+ LLSLURLGetter()
+ : mLandmarkID(LLUUID::null)
+ , mSLURL("(Loading...)")
+ , mLoaded(false) {}
+
+ void setLandmarkID(const LLUUID& id) { mLandmarkID = id; }
+
+ const std::string& getSLURL()
+ {
+ if(!mLoaded)
+ requestSLURL();
+
+ return mSLURL;
+ }
+private:
+ /**
+ * Requests landmark data from server.
+ */
+ void requestSLURL()
+ {
+ if (mLandmarkID.isNull())
+ return;
+
+ LLVector3d g_pos;
+ if(LLLandmarkActions::getLandmarkGlobalPos(mLandmarkID, g_pos))
+ {
+ LLLandmarkActions::getSLURLfromPosGlobal(g_pos,
+ boost::bind(&LLSLURLGetter::landmarkNameCallback, this, _1), false);
+ }
+ }
+
+ void landmarkNameCallback(const std::string& name)
+ {
+ mSLURL = name;
+ mLoaded = true;
+ }
+
+ LLUUID mLandmarkID;
+ std::string mSLURL;
+ bool mLoaded;
+};
+
+/**
* This class is needed to override LLButton default handleToolTip function and
* show SLURL as button tooltip.
* *NOTE: dzaporozhan: This is a workaround. We could set tooltips for buttons
@@ -71,9 +120,6 @@ class LLFavoriteLandmarkButton : public LLButton
{
public:
- /**
- * Requests landmark data from server and shows landmark SLURL as tooltip.
- */
BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect)
{
if(LLUI::sShowXUINames)
@@ -81,48 +127,53 @@ public:
return LLButton::handleToolTip(x, y, msg, sticky_rect);
}
- if(!mLoaded)
- {
- LLVector3d g_pos;
- if(LLLandmarkActions::getLandmarkGlobalPos(mLandmarkID, g_pos))
- {
- LLLandmarkActions::getSLURLfromPosGlobal(g_pos,
- boost::bind(&LLFavoriteLandmarkButton::landmarkNameCallback, this, _1), false);
- }
- }
-
- msg = mSLURL;
+ msg = mUrlGetter.getSLURL();
return TRUE;
}
-
- void landmarkNameCallback(const std::string& name)
- {
- mSLURL = name;
- mLoaded = true;
- }
- void setLandmarkID(const LLUUID& id){ mLandmarkID = id; }
+ void setLandmarkID(const LLUUID& id){ mUrlGetter.setLandmarkID(id); }
protected:
+ LLFavoriteLandmarkButton(const LLButton::Params& p) : LLButton(p) {}
+ friend class LLUICtrlFactory;
- LLFavoriteLandmarkButton(const LLButton::Params& p)
- : LLButton(p)
- , mLandmarkID(LLUUID::null)
- , mSLURL("(Loading...)")
- , mLoaded(false)
+private:
+ LLSLURLGetter mUrlGetter;
+};
+
+/**
+ * This class is needed to override LLMenuItemCallGL default handleToolTip function and
+ * show SLURL as button tooltip.
+ * *NOTE: dzaporozhan: This is a workaround. We could set tooltips for buttons
+ * in showDropDownMenu function but landmark data is not available when Favorites Bar is
+ * created. Thats why we are requesting landmark data after
+ */
+class LLFavoriteLandmarkMenuItem : public LLMenuItemCallGL
+{
+public:
+ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect)
{
- static std::string loading_tooltip = LLTrans::getString("favorite_landmark_loading_tooltip");
- mSLURL = loading_tooltip;
+ if(LLUI::sShowXUINames)
+ {
+ return LLMenuItemCallGL::handleToolTip(x, y, msg, sticky_rect);
+ }
+
+ msg = mUrlGetter.getSLURL();
+ return TRUE;
}
+
+ void setLandmarkID(const LLUUID& id){ mUrlGetter.setLandmarkID(id); }
+
+protected:
+ LLFavoriteLandmarkMenuItem(const LLMenuItemCallGL::Params& p) : LLMenuItemCallGL(p) {}
friend class LLUICtrlFactory;
private:
- LLUUID mLandmarkID;
- std::string mSLURL;
- bool mLoaded;
+ LLSLURLGetter mUrlGetter;
};
+
// updateButtons's helper
struct LLFavoritesSort
{
@@ -483,6 +534,7 @@ void LLFavoritesBarCtrl::showDropDownMenu()
menu_p.visible(false);
menu_p.scrollable(true);
menu_p.max_scrollable_items = 10;
+ menu_p.preferred_width = DROP_DOWN_MENU_WIDTH;
LLToggleableMenu* menu = LLUICtrlFactory::create<LLToggleableMenu>(menu_p);
@@ -554,8 +606,10 @@ void LLFavoritesBarCtrl::showDropDownMenu()
item_params.label(item_name);
item_params.on_click.function(boost::bind(&LLFavoritesBarCtrl::onButtonClick, this, item->getUUID()));
- LLMenuItemCallGL *menu_item = LLUICtrlFactory::create<LLMenuItemCallGL>(item_params);
+ LLFavoriteLandmarkMenuItem *menu_item = LLUICtrlFactory::create<LLFavoriteLandmarkMenuItem>(item_params);
menu_item->setRightMouseDownCallback(boost::bind(&LLFavoritesBarCtrl::onButtonRightClick, this,item->getUUID(),_1,_2,_3,_4));
+ menu_item->setLandmarkID(item->getUUID());
+
// Check whether item name wider than menu
if (menu_item->getNominalWidth() > max_width)
{
@@ -583,7 +637,8 @@ void LLFavoritesBarCtrl::showDropDownMenu()
menu->setButtonRect(mChevronRect, this);
- LLMenuGL::showPopup(this, menu, getRect().getWidth() - widest_item, 0);
+ LLMenuGL::showPopup(this, menu, getRect().getWidth() - max_width, 0);
+
}
}
diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp
index 818381b561..4d154c4cd3 100644
--- a/indra/newview/llfloaterreporter.cpp
+++ b/indra/newview/llfloaterreporter.cpp
@@ -54,7 +54,6 @@
#include "llagent.h"
#include "llbutton.h"
#include "llcheckboxctrl.h"
-#include "llfloaterinventory.h"
#include "llfloaterreg.h"
#include "lllineeditor.h"
#include "lltexturectrl.h"
diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp
index 8961508bcc..f1e499e14b 100644
--- a/indra/newview/llfolderviewitem.cpp
+++ b/indra/newview/llfolderviewitem.cpp
@@ -231,6 +231,8 @@ void LLFolderViewItem::refreshFromListener()
// *TODO: to be removed when database supports multi language. This is a
// temporary attempt to display the inventory folder in the user locale.
+ // mantipov: *NOTE: be sure this code is synchronized with LLFriendCardsManager::findChildFolderUUID
+ // it uses the same way to find localized string
if (LLAssetType::lookupIsProtectedCategoryType(preferred_type))
{
LLTrans::findString(mLabel, "InvFolder " + mLabel);
diff --git a/indra/newview/llfriendcard.cpp b/indra/newview/llfriendcard.cpp
new file mode 100644
index 0000000000..bef5f094e3
--- /dev/null
+++ b/indra/newview/llfriendcard.cpp
@@ -0,0 +1,425 @@
+/**
+ * @file llfriendcard.cpp
+ * @brief Implementation of classes to process Friends Cards
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-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 "llinventory.h"
+#include "lltrans.h"
+
+#include "llfriendcard.h"
+
+#include "llcallingcard.h" // for LLAvatarTracker
+#include "llviewerinventory.h"
+#include "llinventorymodel.h"
+
+// Constants;
+
+static const std::string INVENTORY_STRING_FRIENDS_SUBFOLDER = "Friends";
+static const std::string INVENTORY_STRING_FRIENDS_ALL_SUBFOLDER = "All";
+
+// helper functions
+
+/*
+mantipov *NOTE: unable to use
+LLTrans::getString("InvFolder Friends"); or
+LLTrans::getString("InvFolder FriendsAll");
+in next two functions to set localized folders' names because of there is a hack in the
+LLFolderViewItem::refreshFromListener() method for protected asset types.
+So, localized names will be got from the strings with "InvFolder LABEL_NAME" in the strings.xml
+*/
+inline const std::string& get_friend_folder_name()
+{
+ return INVENTORY_STRING_FRIENDS_SUBFOLDER;
+}
+
+inline const std::string& get_friend_all_subfolder_name()
+{
+ return INVENTORY_STRING_FRIENDS_ALL_SUBFOLDER;
+}
+
+void move_from_to_arrays(LLInventoryModel::cat_array_t& from, LLInventoryModel::cat_array_t& to)
+{
+ while (from.count() > 0)
+ {
+ to.put(from.get(0));
+ from.remove(0);
+ }
+}
+
+const LLUUID& get_folder_uuid(const LLUUID& parentFolderUUID, LLInventoryCollectFunctor& matchFunctor)
+{
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+
+ gInventory.collectDescendentsIf(parentFolderUUID, cats, items,
+ LLInventoryModel::EXCLUDE_TRASH, matchFunctor);
+
+ if (cats.count() == 1)
+ {
+ return cats.get(0)->getUUID();
+ }
+
+ return LLUUID::null;
+}
+
+// LLFriendCardsManager Constructor / Destructor
+LLFriendCardsManager::LLFriendCardsManager()
+{
+ LLAvatarTracker::instance().addObserver(this);
+}
+
+LLFriendCardsManager::~LLFriendCardsManager()
+{
+ LLAvatarTracker::instance().removeObserver(this);
+}
+
+void LLFriendCardsManager::putAvatarData(const LLUUID& avatarID)
+{
+ llinfos << "Store avatar data, avatarID: " << avatarID << llendl;
+ std::pair< avatar_uuid_set_t::iterator, bool > pr;
+ pr = mBuddyIDSet.insert(avatarID);
+ if (pr.second == false)
+ {
+ llwarns << "Trying to add avatar UUID for the stored avatar: "
+ << avatarID
+ << llendl;
+ }
+}
+
+const LLUUID LLFriendCardsManager::extractAvatarID(const LLUUID& avatarID)
+{
+ LLUUID rv;
+ avatar_uuid_set_t::iterator it = mBuddyIDSet.find(avatarID);
+ if (mBuddyIDSet.end() == it)
+ {
+ llwarns << "Call method for non-existent avatar name in the map: " << avatarID << llendl;
+ }
+ else
+ {
+ rv = (*it);
+ mBuddyIDSet.erase(it);
+ }
+ return rv;
+}
+
+// be sure LLInventoryModel::buildParentChildMap() has been called before it.
+// and this method must be called before any actions with friend list
+void LLFriendCardsManager::ensureFriendFoldersExist()
+{
+ LLUUID callingCardsFolderID = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD);
+
+ LLUUID friendFolderUUID = findFriendFolderUUIDImpl();
+
+ if (friendFolderUUID.isNull())
+ {
+ friendFolderUUID = gInventory.createNewCategory(callingCardsFolderID,
+ LLAssetType::AT_CALLINGCARD, get_friend_folder_name());
+ }
+
+ LLUUID friendAllSubfolderUUID = findFriendAllSubfolderUUIDImpl();
+
+ if (friendAllSubfolderUUID.isNull())
+ {
+ friendAllSubfolderUUID = gInventory.createNewCategory(friendFolderUUID,
+ LLAssetType::AT_CALLINGCARD, get_friend_all_subfolder_name());
+ }
+}
+
+
+bool LLFriendCardsManager::isItemInAnyFriendsList(const LLViewerInventoryItem* item)
+{
+ if (item->getType() != LLAssetType::AT_CALLINGCARD)
+ return false;
+
+ LLInventoryModel::item_array_t items;
+ findMatchedFriendCards(item->getCreatorUUID(), items);
+
+ return items.count() > 0;
+}
+
+bool LLFriendCardsManager::isCategoryInFriendFolder(const LLViewerInventoryCategory* cat) const
+{
+ if (NULL == cat)
+ return false;
+ return TRUE == gInventory.isObjectDescendentOf(cat->getUUID(), findFriendFolderUUIDImpl());
+}
+
+void LLFriendCardsManager::syncFriendsFolder()
+{
+ //lets create "Friends" and "Friends/All" in the Inventory "Calling Cards" if they are absent
+ LLFriendCardsManager::instance().ensureFriendFoldersExist();
+
+ LLAvatarTracker::buddy_map_t all_buddies;
+ LLAvatarTracker::instance().copyBuddyList(all_buddies);
+
+ // 1. Remove Friend Cards for non-friends
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+
+ gInventory.collectDescendents(findFriendAllSubfolderUUIDImpl(), cats, items, LLInventoryModel::EXCLUDE_TRASH);
+
+ LLInventoryModel::item_array_t::const_iterator it;
+ for (it = items.begin(); it != items.end(); ++it)
+ {
+ lldebugs << "Check if buddy is in list: " << (*it)->getName() << " " << (*it)->getCreatorUUID() << llendl;
+ if (NULL == get_ptr_in_map(all_buddies, (*it)->getCreatorUUID()))
+ {
+ lldebugs << "NONEXISTS, so remove it" << llendl;
+ removeFriendCardFromInventory((*it)->getCreatorUUID());
+ }
+ }
+
+ // 2. Add missing Friend Cards for friends
+ LLAvatarTracker::buddy_map_t::const_iterator buddy_it = all_buddies.begin();
+ llinfos << "try to build friends, count: " << all_buddies.size() << llendl;
+ for(; buddy_it != all_buddies.end(); ++buddy_it)
+ {
+ const LLUUID& buddy_id = (*buddy_it).first;
+ addFriendCardToInventory(buddy_id);
+ }
+}
+
+void LLFriendCardsManager::collectFriendsLists(folderid_buddies_map_t& folderBuddiesMap) const
+{
+ folderBuddiesMap.clear();
+
+ LLInventoryModel::cat_array_t* listFolders;
+ LLInventoryModel::item_array_t* items;
+
+ // get folders in the Friend folder. Items should be NULL due to Cards should be in lists.
+ gInventory.getDirectDescendentsOf(findFriendFolderUUIDImpl(), listFolders, items);
+
+ if (NULL == listFolders)
+ return;
+
+ LLInventoryModel::cat_array_t::const_iterator itCats; // to iterate Friend Lists (categories)
+ LLInventoryModel::item_array_t::const_iterator itBuddy; // to iterate Buddies in each List
+ LLInventoryModel::cat_array_t* fakeCatsArg;
+ for (itCats = listFolders->begin(); itCats != listFolders->end(); ++itCats)
+ {
+ if (items)
+ items->clear();
+
+ // *HACK: Only Friends/All content will be shown for now
+ // *TODO: Remove this hack, implement sorting if it will be needded by spec.
+ if ((*itCats)->getUUID() != findFriendAllSubfolderUUIDImpl())
+ continue;
+
+ gInventory.getDirectDescendentsOf((*itCats)->getUUID(), fakeCatsArg, items);
+
+ if (NULL == items)
+ continue;
+
+ std::vector<LLUUID> buddyUUIDs;
+ for (itBuddy = items->begin(); itBuddy != items->end(); ++itBuddy)
+ {
+ buddyUUIDs.push_back((*itBuddy)->getCreatorUUID());
+ }
+
+ folderBuddiesMap.insert(make_pair((*itCats)->getUUID(), buddyUUIDs));
+ }
+}
+
+
+/************************************************************************/
+/* Private Methods */
+/************************************************************************/
+const LLUUID& LLFriendCardsManager::findFriendFolderUUIDImpl() const
+{
+ LLUUID callingCardsFolderID = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD);
+
+ std::string friendFolderName = get_friend_folder_name();
+
+ return findChildFolderUUID(callingCardsFolderID, friendFolderName);
+}
+
+const LLUUID& LLFriendCardsManager::findFriendAllSubfolderUUIDImpl() const
+{
+ LLUUID friendFolderUUID = findFriendFolderUUIDImpl();
+
+ std::string friendAllSubfolderName = get_friend_all_subfolder_name();
+
+ return findChildFolderUUID(friendFolderUUID, friendAllSubfolderName);
+}
+
+const LLUUID& LLFriendCardsManager::findChildFolderUUID(const LLUUID& parentFolderUUID, const std::string& folderLabel) const
+{
+ // mantipov *HACK: get localaized name in the same way like in the LLFolderViewItem::refreshFromListener() method.
+ // be sure these both methods are synchronized.
+ // see also get_friend_folder_name() and get_friend_all_subfolder_name() functions
+ std::string localizedName = LLTrans::getString("InvFolder " + folderLabel);
+
+ LLNameCategoryCollector matchFolderFunctor(localizedName);
+
+ return get_folder_uuid(parentFolderUUID, matchFolderFunctor);
+}
+const LLUUID& LLFriendCardsManager::findFriendCardInventoryUUIDImpl(const LLUUID& avatarID)
+{
+ LLUUID friendAllSubfolderUUID = findFriendAllSubfolderUUIDImpl();
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+ LLInventoryModel::item_array_t::const_iterator it;
+
+ // it is not necessary to check friendAllSubfolderUUID against NULL. It will be processed by collectDescendents
+ gInventory.collectDescendents(friendAllSubfolderUUID, cats, items, LLInventoryModel::EXCLUDE_TRASH);
+ for (it = items.begin(); it != items.end(); ++it)
+ {
+ if ((*it)->getCreatorUUID() == avatarID)
+ return (*it)->getUUID();
+ }
+
+ return LLUUID::null;
+}
+
+void LLFriendCardsManager::findMatchedFriendCards(const LLUUID& avatarID, LLInventoryModel::item_array_t& items) const
+{
+ LLInventoryModel::cat_array_t cats;
+ LLUUID friendFolderUUID = findFriendFolderUUIDImpl();
+
+ LLParticularBuddyCollector matchFunctor(avatarID);
+
+ LLViewerInventoryCategory* friendFolder = gInventory.getCategory(friendFolderUUID);
+
+ LLInventoryModel::cat_array_t subFolders;
+ subFolders.push_back(friendFolder);
+
+ while (subFolders.count() > 0)
+ {
+ LLViewerInventoryCategory* cat = subFolders.get(0);
+ subFolders.remove(0);
+
+ gInventory.collectDescendentsIf(cat->getUUID(), cats, items,
+ LLInventoryModel::EXCLUDE_TRASH, matchFunctor);
+
+ move_from_to_arrays(cats, subFolders);
+ }
+}
+
+class CreateFriendCardCallback : public LLInventoryCallback
+{
+public:
+ void fire(const LLUUID& inv_item_id)
+ {
+ LLViewerInventoryItem* item = gInventory.getItem(inv_item_id);
+
+ if (item)
+ LLFriendCardsManager::instance().extractAvatarID(item->getCreatorUUID());
+ }
+};
+
+bool LLFriendCardsManager::addFriendCardToInventory(const LLUUID& avatarID)
+{
+ LLInventoryModel* invModel = &gInventory;
+
+ bool shouldBeAdded = true;
+ std::string name;
+ gCacheName->getFullName(avatarID, name);
+
+ lldebugs << "Processing buddy name: " << name
+ << ", id: " << avatarID
+ << llendl;
+
+ if (shouldBeAdded && findFriendCardInventoryUUIDImpl(avatarID).notNull())
+ {
+ shouldBeAdded = false;
+ lldebugs << "is found in Inventory: " << name << llendl;
+ }
+
+ if (shouldBeAdded && isAvatarDataStored(avatarID))
+ {
+ shouldBeAdded = false;
+ lldebugs << "is found in sentRequests: " << name << llendl;
+ }
+
+ LLUUID friendListFolderID = findFriendAllSubfolderUUIDImpl();
+ if (shouldBeAdded && !invModel->isCategoryComplete(friendListFolderID))
+ {
+ shouldBeAdded = false;
+ }
+ if (shouldBeAdded)
+ {
+ putAvatarData(avatarID);
+ lldebugs << "Sent create_inventory_item for " << avatarID << ", " << name << llendl;
+
+ // TODO: mantipov: Is CreateFriendCardCallback really needed? Probably not
+ LLPointer<LLInventoryCallback> cb = new CreateFriendCardCallback();
+
+ create_inventory_callingcard(avatarID, friendListFolderID, cb);
+ }
+
+ return shouldBeAdded;
+}
+
+void LLFriendCardsManager::removeFriendCardFromInventory(const LLUUID& avatarID)
+{
+ LLInventoryModel::item_array_t items;
+ findMatchedFriendCards(avatarID, items);
+
+ LLInventoryModel::item_array_t::const_iterator it;
+ for (it = items.begin(); it != items.end(); ++ it)
+ {
+ gInventory.removeItem((*it)->getUUID());
+ }
+}
+
+void LLFriendCardsManager::onFriendListUpdate(U32 changed_mask)
+{
+ LLAvatarTracker& at = LLAvatarTracker::instance();
+
+ switch(changed_mask) {
+ case LLFriendObserver::ADD:
+ {
+ const std::set<LLUUID>& changed_items = at.getChangedIDs();
+ std::set<LLUUID>::const_iterator id_it = changed_items.begin();
+ std::set<LLUUID>::const_iterator id_end = changed_items.end();
+ for (;id_it != id_end; ++id_it)
+ {
+ LLFriendCardsManager::instance().addFriendCardToInventory(*id_it);
+ }
+ }
+ break;
+ case LLFriendObserver::REMOVE:
+ {
+ const std::set<LLUUID>& changed_items = at.getChangedIDs();
+ std::set<LLUUID>::const_iterator id_it = changed_items.begin();
+ std::set<LLUUID>::const_iterator id_end = changed_items.end();
+ for (;id_it != id_end; ++id_it)
+ {
+ LLFriendCardsManager::instance().removeFriendCardFromInventory(*id_it);
+ }
+ }
+
+ default:;
+ }
+}
+
+// EOF
diff --git a/indra/newview/llfriendcard.h b/indra/newview/llfriendcard.h
new file mode 100644
index 0000000000..18a6d0ab69
--- /dev/null
+++ b/indra/newview/llfriendcard.h
@@ -0,0 +1,143 @@
+/**
+ * @file llfriendcard.h
+ * @brief Definition of classes to process Friends Cards
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-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_LLFRIENDCARD_H
+#define LL_LLFRIENDCARD_H
+
+
+#include "llcallingcard.h"
+#include "llinventorymodel.h" // for LLInventoryModel::item_array_t
+
+class LLViewerInventoryItem;
+
+class LLFriendCardsManager
+ : public LLSingleton<LLFriendCardsManager>
+ , public LLFriendObserver
+{
+ LOG_CLASS(LLFriendCardsManager);
+
+ friend class LLSingleton<LLFriendCardsManager>;
+ friend class CreateFriendCardCallback;
+
+public:
+ typedef std::map<LLUUID, std::vector<LLUUID> > folderid_buddies_map_t;
+
+ // LLFriendObserver implementation
+ void changed(U32 mask)
+ {
+ onFriendListUpdate(mask);
+ }
+
+ /**
+ * Ensures that all necessary folders are created in Inventory.
+ *
+ * For now it processes Calling Card, Calling Card/Friends & Calling Card/Friends/All folders
+ */
+ void ensureFriendFoldersExist();
+
+
+ /**
+ * Determines if specified Inventory Calling Card exists in any of lists
+ * in the Calling Card/Friends/ folder (Default, or Custom)
+ */
+ bool isItemInAnyFriendsList(const LLViewerInventoryItem* item);
+
+ /**
+ * Checks is the specified category is in the Calling Card/Friends folder
+ */
+ bool isCategoryInFriendFolder(const LLViewerInventoryCategory* cat) const;
+
+ /**
+ * Synchronizes content of the Calling Card/Friends/All Global Inventory folder with Agent's Friend List
+ */
+ void syncFriendsFolder();
+
+ /*!
+ * \brief
+ * Collects folders' IDs with the buddies' IDs in the Inventory Calling Card/Friends folder.
+ *
+ * \param folderBuddiesMap
+ * map into collected data will be put. It will be cleared before adding new data.
+ *
+ * Each item in the out map is a pair where first is an LLViewerInventoryCategory UUID,
+ * second is a vector with UUID of Avatars from this folder.
+ *
+ */
+ void collectFriendsLists(folderid_buddies_map_t& folderBuddiesMap) const;
+
+private:
+ LLFriendCardsManager();
+ ~LLFriendCardsManager();
+
+
+ /**
+ * Stores buddy id to avoid sent create_inventory_callingcard several time for the same Avatar
+ */
+ void putAvatarData(const LLUUID& avatarID);
+
+ /**
+ * Extracts buddy id of Created Friend Card
+ */
+ const LLUUID extractAvatarID(const LLUUID& avatarID);
+
+ bool isAvatarDataStored(const LLUUID& avatarID) const
+ {
+ return (mBuddyIDSet.end() != mBuddyIDSet.find(avatarID));
+ }
+
+ const LLUUID& findChildFolderUUID(const LLUUID& parentFolderUUID, const std::string& folderLabel) const;
+ const LLUUID& findFriendFolderUUIDImpl() const;
+ const LLUUID& findFriendAllSubfolderUUIDImpl() const;
+ const LLUUID& findFriendCardInventoryUUIDImpl(const LLUUID& avatarID);
+ void findMatchedFriendCards(const LLUUID& avatarID, LLInventoryModel::item_array_t& items) const;
+
+ /**
+ * Adds avatar specified by its UUID into the Calling Card/Friends/All Global Inventory folder
+ */
+ bool addFriendCardToInventory(const LLUUID& avatarID);
+
+ /**
+ * Removes an avatar specified by its UUID from the Calling Card/Friends/All Global Inventory folder
+ * and from the all Custom Folders
+ */
+ void removeFriendCardFromInventory(const LLUUID& avatarID);
+
+ void onFriendListUpdate(U32 changed_mask);
+
+
+private:
+ typedef std::set<LLUUID> avatar_uuid_set_t;
+
+ avatar_uuid_set_t mBuddyIDSet;
+};
+
+#endif // LL_LLFRIENDCARD_H
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index efa97de692..789e628b67 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -58,6 +58,7 @@
#include "llfloaterworldmap.h"
#include "llfocusmgr.h"
#include "llfolderview.h"
+#include "llfriendcard.h"
#include "llavataractions.h"
#include "llgesturemgr.h"
#include "lliconctrl.h"
@@ -162,10 +163,26 @@ std::string ICON_NAME[ICON_NAME_COUNT] =
BOOL gAddToOutfit = FALSE;
+
+// +=================================================+
+// | LLInventoryPanelObserver |
+// +=================================================+
+void LLInventoryPanelObserver::changed(U32 mask)
+{
+ mIP->modelChanged(mask);
+}
+
+
// +=================================================+
// | 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();
@@ -2302,7 +2319,11 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
}
else if(isAgentInventory()) // do not allow creating in library
{
- mItems.push_back(std::string("New Folder"));
+ LLViewerInventoryCategory *cat = getCategory();
+
+ // 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"));
@@ -2310,7 +2331,6 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
mItems.push_back(std::string("New Body Parts"));
mItems.push_back(std::string("Change Type"));
- LLViewerInventoryCategory *cat = getCategory();
if (cat && LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType()))
{
mDisabledItems.push_back(std::string("Change Type"));
@@ -2879,6 +2899,16 @@ void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
// | 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);
@@ -3216,6 +3246,18 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,
return rv;
}
+BOOL LLCallingCardBridge::removeItem()
+{
+ if (LLFriendCardsManager::instance().isItemInAnyFriendsList(getItem()))
+ {
+ LLAvatarActions::removeFriendDialog(getItem()->getCreatorUUID());
+ return FALSE;
+ }
+ else
+ {
+ return LLItemBridge::removeItem();
+ }
+}
// +=================================================+
// | LLNotecardBridge |
// +=================================================+
@@ -3450,6 +3492,14 @@ void LLAnimationBridge::openItem()
// 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;
+}
+
BOOL LLObjectBridge::isItemRemovable()
{
LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 3af54c52ea..25859b7f73 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -38,9 +38,10 @@
#include "llviewercontrol.h"
#include "llcallingcard.h"
#include "llinventorymodel.h"
-#include "llfloaterinventory.h"
#include "llfoldervieweventlistener.h"
+class LLInventoryPanel;
+
enum EInventoryIcon
{
TEXTURE_ICON_NAME,
@@ -114,7 +115,7 @@ class LLInventoryPanelObserver : public LLInventoryObserver
public:
LLInventoryPanelObserver(LLInventoryPanel* ip) : mIP(ip) {}
virtual ~LLInventoryPanelObserver() {}
- virtual void changed(U32 mask) { mIP->modelChanged(mask); }
+ virtual void changed(U32 mask);
protected:
LLInventoryPanel* mIP;
};
@@ -191,11 +192,7 @@ public:
virtual void clearDisplayName() {}
protected:
- LLInvFVBridge(LLInventoryPanel* inventory, const LLUUID& uuid) :
- mUUID(uuid), mInvType(LLInventoryType::IT_NONE)
- {
- mInventoryPanel = inventory->getHandle();
- }
+ LLInvFVBridge(LLInventoryPanel* inventory, const LLUUID& uuid);
LLInventoryObject* getInventoryObject() const;
LLInventoryModel* getInventoryModel() const;
@@ -395,15 +392,7 @@ public:
virtual void openItem();
protected:
- LLLandmarkBridge(LLInventoryPanel* inventory, const LLUUID& uuid, U32 flags = 0x00) :
- LLItemBridge(inventory, uuid)
- {
- mVisited = FALSE;
- if (flags & LLInventoryItem::II_FLAGS_LANDMARK_VISITED)
- {
- mVisited = TRUE;
- }
- }
+ LLLandmarkBridge(LLInventoryPanel* inventory, const LLUUID& uuid, U32 flags = 0x00);
protected:
BOOL mVisited;
@@ -438,6 +427,7 @@ public:
EDragAndDropType cargo_type,
void* cargo_data);
void refreshFolderViewItem();
+ BOOL removeItem();
protected:
LLCallingCardBridge( LLInventoryPanel* inventory, const LLUUID& uuid );
@@ -515,13 +505,7 @@ public:
LLInventoryObject* getObject() const;
protected:
- 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;
- }
+ LLObjectBridge(LLInventoryPanel* inventory, const LLUUID& uuid, LLInventoryType::EType type, U32 flags);
protected:
static LLUUID sContextMenuItemID; // Only valid while the context menu is open.
@@ -788,6 +772,7 @@ void wear_inventory_item_on_avatar(LLInventoryItem* item);
void wear_outfit_by_name(const std::string& name);
void wear_inventory_category(LLInventoryCategory* category, bool copy, bool append);
+class LLViewerJointAttachment;
void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment);
// Move items from an in-world object's "Contents" folder to a specified
diff --git a/indra/newview/llmenucommands.cpp b/indra/newview/llmenucommands.cpp
index efa15e05da..1666ec1336 100644
--- a/indra/newview/llmenucommands.cpp
+++ b/indra/newview/llmenucommands.cpp
@@ -50,7 +50,6 @@
#include "llfloaterdirectory.h"
#include "llfloaterworldmap.h"
#include "llgivemoney.h"
-#include "llfloaterinventory.h"
#include "lllineeditor.h"
#include "llnotify.h"
#include "llstatusbar.h"
diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index 7bf7ceb6d2..1d79ea4a21 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -38,6 +38,7 @@
#include "lllandmark.h"
#include "llfloaterworldmap.h"
+#include "llfloaterinventory.h"
#include "llfoldervieweventlistener.h"
#include "lllandmarklist.h"
#include "llsidetray.h"
diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h
index 0b11270fb5..14cbbd6123 100644
--- a/indra/newview/llpanellandmarks.h
+++ b/indra/newview/llpanellandmarks.h
@@ -33,10 +33,13 @@
#ifndef LL_LLPANELLANDMARKS_H
#define LL_LLPANELLANDMARKS_H
-#include "llfloaterinventory.h"
#include "llinventorymodel.h"
#include "llpanelplacestab.h"
+class LLFolderViewItem;
+class LLInventoryPanel;
+class LLSaveFolderState;
+
class LLLandmarksPanel : public LLPanelPlacesTab
{
public:
diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp
index 844e5122f4..697182c8fc 100644
--- a/indra/newview/llpanelpeople.cpp
+++ b/indra/newview/llpanelpeople.cpp
@@ -47,6 +47,7 @@
#include "llcallingcard.h" // for LLAvatarTracker
#include "llfloateravatarpicker.h"
//#include "llfloaterminiinspector.h"
+#include "llfriendcard.h"
#include "llavataractions.h"
#include "llgroupactions.h"
#include "llgrouplist.h"
@@ -302,7 +303,7 @@ LLPanelPeople::LLPanelPeople()
mFilterEditor(NULL),
mTabContainer(NULL),
mOnlineFriendList(NULL),
- mOfflineFriendList(NULL),
+ mAllFriendList(NULL),
mNearbyList(NULL),
mRecentList(NULL)
{
@@ -337,7 +338,7 @@ BOOL LLPanelPeople::postBuild()
mTabContainer->setCommitCallback(boost::bind(&LLPanelPeople::onTabSelected, this, _2));
mOnlineFriendList = getChild<LLPanel>(FRIENDS_TAB_NAME)->getChild<LLAvatarList>("avatars_online");
- mOfflineFriendList = getChild<LLPanel>(FRIENDS_TAB_NAME)->getChild<LLAvatarList>("avatars_offline");
+ mAllFriendList = getChild<LLPanel>(FRIENDS_TAB_NAME)->getChild<LLAvatarList>("avatars_all");
mNearbyList = getChild<LLPanel>(NEARBY_TAB_NAME)->getChild<LLAvatarList>("avatar_list");
@@ -354,11 +355,11 @@ BOOL LLPanelPeople::postBuild()
friends_panel->childSetAction("del_btn", boost::bind(&LLPanelPeople::onDeleteFriendButtonClicked, this));
mOnlineFriendList->setDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, mOnlineFriendList));
- mOfflineFriendList->setDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, mOfflineFriendList));
+ mAllFriendList->setDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, mAllFriendList));
mNearbyList->setDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, mNearbyList));
mRecentList->setDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, mRecentList));
mOnlineFriendList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mOnlineFriendList));
- mOfflineFriendList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mOfflineFriendList));
+ mAllFriendList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mAllFriendList));
mNearbyList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mNearbyList));
mRecentList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mRecentList));
@@ -427,17 +428,25 @@ bool LLPanelPeople::updateFriendList(U32 changed_mask)
// *TODO: it's suboptimal to rebuild the whole lists on online status change.
- // save them to the online and offline friends vectors
+ // save them to the online and all friends vectors
mOnlineFriendVec.clear();
- mOfflineFriendVec.clear();
+ mAllFriendVec.clear();
+
+ LLFriendCardsManager::folderid_buddies_map_t listMap;
+
+ // *NOTE: For now collectFriendsLists returns data only for Friends/All folder. EXT-694.
+ LLFriendCardsManager::instance().collectFriendsLists(listMap);
+ if (listMap.size() > 0)
+ {
+ mAllFriendVec = listMap.begin()->second;
+ }
+
LLAvatarTracker::buddy_map_t::const_iterator buddy_it = all_buddies.begin();
for (; buddy_it != all_buddies.end(); ++buddy_it)
{
LLUUID buddy_id = buddy_it->first;
if (av_tracker.isBuddyOnline(buddy_id))
mOnlineFriendVec.push_back(buddy_id);
- else
- mOfflineFriendVec.push_back(buddy_id);
}
return filterFriendList();
@@ -477,19 +486,19 @@ bool LLPanelPeople::updateGroupList()
bool LLPanelPeople::filterFriendList()
{
- if (!mOnlineFriendList || !mOfflineFriendList)
+ if (!mOnlineFriendList || !mAllFriendList)
return true; // there's no point in further updates
// We must always update Friends list to clear the latest removed friend.
bool have_names =
mOnlineFriendList->update(mOnlineFriendVec, mFilterSubString) &
- mOfflineFriendList->update(mOfflineFriendVec, mFilterSubString);
+ mAllFriendList->update(mAllFriendVec, mFilterSubString);
if (mOnlineFriendVec.size() == 0)
mOnlineFriendList->setCommentText(getString("no_friends_online"));
- if (mOfflineFriendVec.size() == 0)
- mOfflineFriendList->setCommentText(getString("no_friends_offline"));
+ if (mAllFriendVec.size() == 0)
+ mAllFriendList->setCommentText(getString("no_friends"));
return have_names;
}
@@ -615,7 +624,7 @@ LLUUID LLPanelPeople::getCurrentItemID() const
if ((cur_online_friend = mOnlineFriendList->getCurrentID()).notNull())
return cur_online_friend;
- return mOfflineFriendList->getCurrentID();
+ return mAllFriendList->getCurrentID();
}
if (cur_tab == NEARBY_TAB_NAME)
@@ -720,12 +729,12 @@ void LLPanelPeople::onAvatarListDoubleClicked(LLAvatarList* list)
void LLPanelPeople::onAvatarListCommitted(LLAvatarList* list)
{
- // Make sure only one of the friends lists (online/offline) has selection.
+ // Make sure only one of the friends lists (online/all) has selection.
if (getActiveTabName() == FRIENDS_TAB_NAME)
{
if (list == mOnlineFriendList)
- mOfflineFriendList->deselectAllItems(TRUE);
- else if (list == mOfflineFriendList)
+ mAllFriendList->deselectAllItems(TRUE);
+ else if (list == mAllFriendList)
mOnlineFriendList->deselectAllItems(TRUE);
else
llassert(0 && "commit on unknown friends list");
diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h
index d0f78f4247..3358a70bac 100644
--- a/indra/newview/llpanelpeople.h
+++ b/indra/newview/llpanelpeople.h
@@ -116,7 +116,7 @@ private:
LLFilterEditor* mFilterEditor;
LLTabContainer* mTabContainer;
LLAvatarList* mOnlineFriendList;
- LLAvatarList* mOfflineFriendList;
+ LLAvatarList* mAllFriendList;
LLAvatarList* mNearbyList;
LLAvatarList* mRecentList;
LLGroupList* mGroupList;
@@ -142,7 +142,7 @@ private:
typedef std::vector<LLUUID> uuid_vector_t;
uuid_vector_t mNearbyVec;
uuid_vector_t mOnlineFriendVec;
- uuid_vector_t mOfflineFriendVec;
+ uuid_vector_t mAllFriendVec;
uuid_vector_t mRecentVec;
};
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index ad1dd74cc6..7cb9e61e72 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -32,6 +32,7 @@
#include "llviewerprecompiledheaders.h"
#include "llassettype.h"
+#include "llwindow.h"
#include "lllandmark.h"
@@ -51,6 +52,7 @@
#include "llpanelteleporthistory.h"
#include "llsidetray.h"
#include "lltoggleablemenu.h"
+#include "llviewerinventory.h"
#include "llviewermenu.h"
#include "llviewerparcelmgr.h"
#include "llviewerregion.h"
diff --git a/indra/newview/llpreview.cpp b/indra/newview/llpreview.cpp
index 7faabbb28b..ab253e012d 100644
--- a/indra/newview/llpreview.cpp
+++ b/indra/newview/llpreview.cpp
@@ -51,7 +51,6 @@
#include "llagent.h"
#include "llvoavatarself.h"
#include "llselectmgr.h"
-#include "llfloaterinventory.h"
#include "llviewerinventory.h"
#include "llviewerwindow.h"
#include "lltrans.h"
diff --git a/indra/newview/llpreviewanim.cpp b/indra/newview/llpreviewanim.cpp
index 6fe23e8aeb..3bda30e0c6 100644
--- a/indra/newview/llpreviewanim.cpp
+++ b/indra/newview/llpreviewanim.cpp
@@ -36,7 +36,6 @@
#include "llbutton.h"
#include "llresmgr.h"
#include "llinventory.h"
-#include "llfloaterinventory.h"
#include "llvoavatarself.h"
#include "llagent.h" // gAgent
#include "llkeyframemotion.h"
diff --git a/indra/newview/llpreviewsound.cpp b/indra/newview/llpreviewsound.cpp
index 0f2b94ebd4..7659c50ed3 100644
--- a/indra/newview/llpreviewsound.cpp
+++ b/indra/newview/llpreviewsound.cpp
@@ -36,7 +36,6 @@
#include "llagent.h" // gAgent
#include "llbutton.h"
#include "llinventory.h"
-#include "llfloaterinventory.h"
#include "lllineeditor.h"
#include "llpreviewsound.h"
#include "llresmgr.h"
diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp
index 9122e49a06..9d7338c111 100644
--- a/indra/newview/llpreviewtexture.cpp
+++ b/indra/newview/llpreviewtexture.cpp
@@ -32,6 +32,8 @@
#include "llviewerprecompiledheaders.h"
+#include "llwindow.h"
+
#include "llpreviewtexture.h"
#include "llagent.h"
@@ -39,7 +41,6 @@
#include "llfilepicker.h"
#include "llfloaterreg.h"
#include "llimagetga.h"
-#include "llfloaterinventory.h"
#include "llinventory.h"
#include "llresmgr.h"
#include "lltrans.h"
diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp
index 3ac9076e85..afa8e5f072 100644
--- a/indra/newview/llsidetray.cpp
+++ b/indra/newview/llsidetray.cpp
@@ -642,20 +642,18 @@ LLPanel* LLSideTray::showPanel (const std::string& panel_name, const LLSD& para
return NULL;
}
+// *TODO: Eliminate magic constants.
static const S32 fake_offset = 132;
static const S32 fake_top_offset = 18;
void LLSideTray::resetPanelRect ()
{
- LLNavigationBar* nav_bar = LLNavigationBar::getInstance();
- LLRect nav_rect = nav_bar->getRect();
const LLRect& parent_rect = gViewerWindow->getRootView()->getRect();
static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray>());
- S32 panel_width = sidetray_params.default_button_width+sidetray_params.default_button_margin;
- if(!mCollapsed)
- panel_width+=mMaxBarWidth;
+ S32 panel_width = sidetray_params.default_button_width;
+ panel_width += mCollapsed ? sidetray_params.default_button_margin : mMaxBarWidth;
S32 panel_height = parent_rect.getHeight()-fake_top_offset;
@@ -671,9 +669,8 @@ void LLSideTray::setPanelRect ()
const LLRect& parent_rect = gViewerWindow->getRootView()->getRect();
- S32 panel_width = sidetray_params.default_button_width+sidetray_params.default_button_margin;
- if(!mCollapsed)
- panel_width+=mMaxBarWidth;
+ S32 panel_width = sidetray_params.default_button_width;
+ panel_width += mCollapsed ? sidetray_params.default_button_margin : mMaxBarWidth;
S32 panel_height = parent_rect.getHeight()-fake_top_offset - nav_rect.getHeight();
S32 panel_top = parent_rect.mTop-fake_top_offset - nav_rect.getHeight();
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 920ec0c65d..6c0481feaa 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -77,6 +77,7 @@
#include "llviewercontrol.h"
#include "llvfs.h"
#include "llxorcipher.h" // saved password, MAC address
+#include "llwindow.h"
#include "imageids.h"
#include "message.h"
#include "v3math.h"
@@ -111,7 +112,7 @@
#include "llimagebmp.h"
#include "llinventorybridge.h"
#include "llinventorymodel.h"
-#include "llfloaterinventory.h"
+#include "llfriendcard.h"
#include "llkeyboard.h"
#include "llloginhandler.h" // gLoginHandler, SLURL support
#include "llpanellogin.h"
@@ -2142,10 +2143,15 @@ bool idle_startup()
}
+ // This method MUST be called before gInventory.findCategoryUUIDForType because of
+ // gInventory.mIsAgentInvUsable is set to true in the gInventory.buildParentChildMap.
+ gInventory.buildParentChildMap();
+
//all categories loaded. lets create "My Favorites" category
gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE,true);
- gInventory.buildParentChildMap();
+ // lets create "Friends" and "Friends/All" in the Inventory "Calling Cards" and fill it with buddies
+ LLFriendCardsManager::instance().syncFriendsFolder();
llinfos << "Setting Inventory changed mask and notifying observers" << llendl;
gInventory.addChangedMask(LLInventoryObserver::ALL, LLUUID::null);
diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp
index 9cabcf4680..c724fb5315 100644
--- a/indra/newview/llstatusbar.cpp
+++ b/indra/newview/llstatusbar.cpp
@@ -46,7 +46,6 @@
#include "llfloaterregioninfo.h"
#include "llfloaterscriptdebug.h"
#include "llhudicon.h"
-#include "llfloaterinventory.h"
#include "llnavigationbar.h"
#include "llkeyboard.h"
#include "lllineeditor.h"
@@ -224,7 +223,7 @@ void LLStatusBar::draw()
LLPanel::draw();
}
-BOOL LLStatusBar::handleRightMouseUp(S32 x, S32 y, MASK mask)
+BOOL LLStatusBar::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
if (mHideNavbarContextMenu)
{
@@ -603,7 +602,7 @@ void LLStatusBar::onHideNavbarContextMenuItemClicked(const LLSD& userdata)
void LLStatusBar::onMainMenuRightClicked(LLUICtrl* ctrl, S32 x, S32 y, MASK mask)
{
- handleRightMouseUp(x, y, mask);
+ handleRightMouseDown(x, y, mask);
}
// static
diff --git a/indra/newview/llstatusbar.h b/indra/newview/llstatusbar.h
index 0cb3551768..b77db2c525 100644
--- a/indra/newview/llstatusbar.h
+++ b/indra/newview/llstatusbar.h
@@ -58,7 +58,7 @@ public:
/*virtual*/ void draw();
- /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL postBuild();
// MANIPULATORS
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index b5dd34df15..c58457d599 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -51,7 +51,6 @@
#include "llhudmanager.h"
#include "llinventorybridge.h"
#include "llinventorymodel.h"
-#include "llfloaterinventory.h"
#include "llmutelist.h"
#include "llnotify.h"
#include "llpreviewnotecard.h"
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 4645b9bf59..95ab40f9bf 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -799,14 +799,14 @@ void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id,
gAgent.sendReliableMessage();
}
-void create_inventory_callingcard(const LLUUID& avatar_id)
+void create_inventory_callingcard(const LLUUID& avatar_id, const LLUUID& parent /*= LLUUID::null*/, LLPointer<LLInventoryCallback> cb/*=NULL*/)
{
std::string item_desc = avatar_id.asString();
std::string item_name;
gCacheName->getFullName(avatar_id, item_name);
create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
- LLUUID::null, LLTransactionID::tnull, item_name, item_desc, LLAssetType::AT_CALLINGCARD,
- LLInventoryType::IT_CALLINGCARD, NOT_WEARABLE, PERM_MOVE | PERM_TRANSFER, NULL);
+ parent, LLTransactionID::tnull, item_name, item_desc, LLAssetType::AT_CALLINGCARD,
+ LLInventoryType::IT_CALLINGCARD, NOT_WEARABLE, PERM_MOVE | PERM_TRANSFER, cb);
}
void copy_inventory_item(
diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h
index 8920fb053b..0bfb37f7e8 100644
--- a/indra/newview/llviewerinventory.h
+++ b/indra/newview/llviewerinventory.h
@@ -286,7 +286,7 @@ void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id,
U32 next_owner_perm,
LLPointer<LLInventoryCallback> cb);
-void create_inventory_callingcard(const LLUUID& avatar_id);
+void create_inventory_callingcard(const LLUUID& avatar_id, const LLUUID& parent = LLUUID::null, LLPointer<LLInventoryCallback> cb=NULL);
/**
* @brief Securely create a new inventory item by copying from another.
diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp
index 7bbe2c89b4..de01e79803 100644
--- a/indra/newview/llviewertexteditor.cpp
+++ b/indra/newview/llviewertexteditor.cpp
@@ -39,7 +39,6 @@
#include "llinventory.h"
#include "llinventorybridge.h"
#include "llinventorymodel.h"
-#include "llfloaterinventory.h"
#include "llviewertexteditor.h"
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 9bdf9d2aac..461f7fc1c7 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -116,7 +116,6 @@
#include "llhudview.h"
#include "llimagebmp.h"
#include "llimagej2c.h"
-#include "llfloaterinventory.h"
#include "llkeyboard.h"
#include "lllineeditor.h"
#include "llmenugl.h"
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 98d8b27e09..018cce4b49 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -52,7 +52,6 @@
#include "llheadrotmotion.h"
#include "llhudeffecttrail.h"
#include "llhudmanager.h"
-#include "llfloaterinventory.h"
#include "llkeyframefallmotion.h"
#include "llkeyframestandmotion.h"
#include "llkeyframewalkmotion.h"
@@ -5510,6 +5509,24 @@ void LLVOAvatar::sitDown(BOOL bSitting)
//-----------------------------------------------------------------------------
void LLVOAvatar::sitOnObject(LLViewerObject *sit_object)
{
+ if (isSelf())
+ {
+ // Might be first sit
+ LLFirstUse::useSit();
+
+ gAgent.setFlying(FALSE);
+ gAgent.setThirdPersonHeadOffset(LLVector3::zero);
+ //interpolate to new camera position
+ gAgent.startCameraAnimation();
+ // make sure we are not trying to autopilot
+ gAgent.stopAutoPilot();
+ gAgent.setupSitCamera();
+ if (gAgent.getForceMouselook())
+ {
+ gAgent.changeCameraToMouselook();
+ }
+ }
+
if (mDrawable.isNull())
{
return;
@@ -5531,23 +5548,6 @@ void LLVOAvatar::sitOnObject(LLViewerObject *sit_object)
stopMotion(ANIM_AGENT_BODY_NOISE);
- if (isSelf())
- {
- // Might be first sit
- LLFirstUse::useSit();
-
- gAgent.setFlying(FALSE);
- gAgent.setThirdPersonHeadOffset(LLVector3::zero);
- //interpolate to new camera position
- gAgent.startCameraAnimation();
- // make sure we are not trying to autopilot
- gAgent.stopAutoPilot();
- gAgent.setupSitCamera();
- if (gAgent.getForceMouselook())
- {
- gAgent.changeCameraToMouselook();
- }
- }
}
//-----------------------------------------------------------------------------
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 9777e1ec21..a7b5b60842 100644
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -54,7 +54,6 @@
#include "llheadrotmotion.h"
#include "llhudeffecttrail.h"
#include "llhudmanager.h"
-#include "llfloaterinventory.h"
#include "llkeyframefallmotion.h"
#include "llkeyframestandmotion.h"
#include "llkeyframewalkmotion.h"
diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml
index fce31a2c68..22823ea98b 100644
--- a/indra/newview/skins/default/xui/en/panel_people.xml
+++ b/indra/newview/skins/default/xui/en/panel_people.xml
@@ -19,8 +19,8 @@
name="no_friends_online"
value="No friends online" />
<string
- name="no_friends_offline"
- value="No friends offline" />
+ name="no_friends"
+ value="No friends" />
<string
name="no_groups"
value="No groups" />
@@ -153,14 +153,14 @@
can_resize="false"
layout="topleft"
min_height="100"
- name="tab_offline"
- title="Offline">
+ name="tab_all"
+ title="All">
<panel
follows="all"
height="260"
layout="topleft"
left="0"
- name="tab_offline_panel"
+ name="tab_all_panel"
top="100"
width="285">
<avatar_list
@@ -169,7 +169,7 @@
height="255"
layout="topleft"
left="0"
- name="avatars_offline"
+ name="avatars_all"
top="0"
width="285" />
</panel>
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 4560a7138c..27b34d16a8 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -413,6 +413,10 @@ this texture in your inventory
<string name="InvFolder Current Outfit">Current Outfit</string>
<string name="InvFolder My Outfits">My Outfits</string>
+ <!-- are used for Friends and Friends/All folders in Inventory "Calling cards" folder. See EXT-694-->
+ <string name="InvFolder Friends">Friends</string>
+ <string name="InvFolder All">All</string>
+
<!-- inventory FVBridge -->
<string name="Buy">Buy</string>
<string name="BuyforL$">Buy for L$</string>