summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/contributions.txt2
-rw-r--r--indra/cmake/FMOD.cmake6
-rw-r--r--indra/llaudio/CMakeLists.txt5
-rw-r--r--indra/llmessage/llcachename.cpp27
-rw-r--r--indra/llmessage/llcachename.h6
-rw-r--r--indra/llui/llmenubutton.cpp100
-rw-r--r--indra/llui/llmenubutton.h19
-rw-r--r--indra/llui/lltoggleablemenu.cpp18
-rw-r--r--indra/llui/lltoggleablemenu.h5
-rw-r--r--indra/llui/llurlentry.cpp2
-rw-r--r--indra/newview/app_settings/settings.xml11
-rw-r--r--indra/newview/featuretable.txt6
-rw-r--r--indra/newview/featuretable_xp.txt6
-rw-r--r--indra/newview/installers/windows/installer_template.nsi2
-rw-r--r--indra/newview/llchathistory.cpp47
-rw-r--r--indra/newview/llimview.cpp31
-rw-r--r--indra/newview/llinspectavatar.cpp5
-rw-r--r--indra/newview/llinspectobject.cpp3
-rw-r--r--indra/newview/lllogchat.cpp157
-rw-r--r--indra/newview/lllogchat.h40
-rw-r--r--indra/newview/llnearbychat.cpp56
-rw-r--r--indra/newview/lloutfitslist.cpp9
-rw-r--r--indra/newview/llpanelgrouproles.cpp107
-rw-r--r--indra/newview/llpanelgrouproles.h6
-rw-r--r--indra/newview/llpanellandmarks.cpp7
-rw-r--r--indra/newview/llpanellandmarks.h5
-rw-r--r--indra/newview/llpanelmaininventory.cpp3
-rw-r--r--indra/newview/llpanelmaininventory.h3
-rw-r--r--indra/newview/llpaneloutfitedit.cpp11
-rw-r--r--indra/newview/llpaneloutfitedit.h4
-rw-r--r--indra/newview/llpanelpeople.cpp9
-rw-r--r--indra/newview/llpanelteleporthistory.cpp3
-rw-r--r--indra/newview/llpanelwearing.cpp10
-rw-r--r--indra/newview/llviewermenu.cpp5
-rw-r--r--indra/newview/skins/default/xui/da/strings.xml2
-rw-r--r--indra/newview/skins/default/xui/de/strings.xml2
-rw-r--r--indra/newview/skins/default/xui/en/menu_add_wearable_gear.xml4
-rw-r--r--indra/newview/skins/default/xui/en/menu_cof_gear.xml4
-rw-r--r--indra/newview/skins/default/xui/en/menu_gesture_gear.xml4
-rw-r--r--indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml4
-rw-r--r--indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml4
-rw-r--r--indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml4
-rw-r--r--indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml4
-rw-r--r--indra/newview/skins/default/xui/en/menu_outfit_gear.xml4
-rw-r--r--indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml5
-rw-r--r--indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml5
-rw-r--r--indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml5
-rw-r--r--indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml5
-rw-r--r--indra/newview/skins/default/xui/en/menu_places_gear_folder.xml4
-rw-r--r--indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml4
-rw-r--r--indra/newview/skins/default/xui/en/menu_teleport_history_gear.xml4
-rw-r--r--indra/newview/skins/default/xui/en/menu_wearing_gear.xml4
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml2
-rw-r--r--indra/newview/skins/default/xui/es/strings.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/strings.xml2
-rw-r--r--indra/newview/skins/default/xui/it/strings.xml2
-rw-r--r--indra/newview/skins/default/xui/ja/strings.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/notifications.xml16
-rw-r--r--indra/newview/skins/default/xui/nl/strings.xml2
-rw-r--r--indra/newview/skins/default/xui/pl/strings.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/strings.xml2
61 files changed, 603 insertions, 237 deletions
diff --git a/doc/contributions.txt b/doc/contributions.txt
index 16327d0917..96ee446a0c 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -72,6 +72,7 @@ Aleric Inglewood
VWR-13996
VWR-14426
SNOW-84
+ SNOW-477
SNOW-766
STORM-163
Ales Beaumont
@@ -174,6 +175,7 @@ Boroondas Gupte
VWR-233
VWR-20583
VWR-20891
+ VWR-23455
WEB-262
Bulli Schumann
CT-218
diff --git a/indra/cmake/FMOD.cmake b/indra/cmake/FMOD.cmake
index 96434e38fa..dcf44cd642 100644
--- a/indra/cmake/FMOD.cmake
+++ b/indra/cmake/FMOD.cmake
@@ -7,8 +7,10 @@ if (FMOD)
set(FMOD_FIND_REQUIRED ON)
include(FindFMOD)
else (STANDALONE)
- include(Prebuilt)
- use_prebuilt_binary(fmod)
+ if (INSTALL_PROPRIETARY)
+ include(Prebuilt)
+ use_prebuilt_binary(fmod)
+ endif (INSTALL_PROPRIETARY)
if (WINDOWS)
set(FMOD_LIBRARY fmod)
diff --git a/indra/llaudio/CMakeLists.txt b/indra/llaudio/CMakeLists.txt
index e869b9717c..21ec622819 100644
--- a/indra/llaudio/CMakeLists.txt
+++ b/indra/llaudio/CMakeLists.txt
@@ -14,7 +14,6 @@ include(LLVFS)
include_directories(
${LLAUDIO_INCLUDE_DIRS}
- ${FMOD_INCLUDE_DIR}
${LLCOMMON_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS}
${LLMESSAGE_INCLUDE_DIRS}
@@ -45,6 +44,10 @@ set(llaudio_HEADER_FILES
)
if (FMOD)
+ include_directories(
+ ${FMOD_INCLUDE_DIR}
+ )
+
list(APPEND llaudio_SOURCE_FILES
llaudioengine_fmod.cpp
lllistener_fmod.cpp
diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp
index 4a66a31c35..522b99bc02 100644
--- a/indra/llmessage/llcachename.cpp
+++ b/indra/llmessage/llcachename.cpp
@@ -38,6 +38,8 @@
#include "message.h"
#include "llmemtype.h"
+#include <boost/regex.hpp>
+
// llsd serialization constants
static const std::string AGENTS("agents");
static const std::string GROUPS("groups");
@@ -551,6 +553,31 @@ std::string LLCacheName::buildUsername(const std::string& full_name)
return full_name;
}
+//static
+std::string LLCacheName::buildLegacyName(const std::string& complete_name)
+{
+ boost::regex complete_name_regex("(.+)( \\()([A-Za-z]+)(.[A-Za-z]+)*(\\))");
+ boost::match_results<std::string::const_iterator> name_results;
+ if (!boost::regex_match(complete_name, name_results, complete_name_regex)) return complete_name;
+
+ std::string legacy_name = name_results[3];
+ // capitalize the first letter
+ std::string cap_letter = legacy_name.substr(0, 1);
+ LLStringUtil::toUpper(cap_letter);
+ legacy_name = cap_letter + legacy_name.substr(1);
+
+ if (name_results[4].matched)
+ {
+ std::string last_name = name_results[4];
+ std::string cap_letter = last_name.substr(1, 1);
+ LLStringUtil::toUpper(cap_letter);
+ last_name = cap_letter + last_name.substr(2);
+ legacy_name = legacy_name + " " + last_name;
+ }
+
+ return legacy_name;
+}
+
// This is a little bit kludgy. LLCacheNameCallback is a slot instead of a function pointer.
// The reason it is a slot is so that the legacy get() function below can bind an old callback
// and pass it as a slot. The reason it isn't a boost::function is so that trackable behavior
diff --git a/indra/llmessage/llcachename.h b/indra/llmessage/llcachename.h
index b469803060..b108e37157 100644
--- a/indra/llmessage/llcachename.h
+++ b/indra/llmessage/llcachename.h
@@ -90,6 +90,12 @@ public:
// "Random Linden" -> "random.linden"
static std::string buildUsername(const std::string& name);
+ // Converts a complete display name to a legacy name
+ // if possible, otherwise returns the input
+ // "Alias (random.linden)" -> "Random Linden"
+ // "Something random" -> "Something random"
+ static std::string buildLegacyName(const std::string& name);
+
// If available, this method copies the group name into the string
// provided. The caller must allocate at least
// DB_GROUP_NAME_BUF_SIZE characters. If not available, this
diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp
index c1b5efaa72..ac568a83e4 100644
--- a/indra/llui/llmenubutton.cpp
+++ b/indra/llui/llmenubutton.cpp
@@ -29,7 +29,7 @@
#include "llmenubutton.h"
// Linden library includes
-#include "llmenugl.h"
+#include "lltoggleablemenu.h"
#include "llstring.h"
#include "v4color.h"
@@ -44,22 +44,26 @@ LLMenuButton::Params::Params()
LLMenuButton::LLMenuButton(const LLMenuButton::Params& p)
: LLButton(p),
- mMenu(NULL),
- mMenuVisibleLastFrame(false),
+ mIsMenuShown(false),
mMenuPosition(MP_BOTTOM_LEFT)
{
std::string menu_filename = p.menu_filename;
if (!menu_filename.empty())
{
- mMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(menu_filename, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
- if (!mMenu)
+ LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(menu_filename, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
+ if (!menu)
{
llwarns << "Error loading menu_button menu" << llendl;
+ return;
}
- }
- updateMenuOrigin();
+ menu->setVisibilityChangeCallback(boost::bind(&LLMenuButton::onMenuVisibilityChange, this, _2));
+
+ mMenuHandle = menu->getHandle();
+
+ updateMenuOrigin();
+ }
}
boost::signals2::connection LLMenuButton::setMouseDownCallback( const mouse_signal_t::slot_type& cb )
@@ -69,34 +73,34 @@ boost::signals2::connection LLMenuButton::setMouseDownCallback( const mouse_sign
void LLMenuButton::hideMenu()
{
- if(!mMenu) return;
- mMenu->setVisible(FALSE);
+ if(mMenuHandle.isDead()) return;
+
+ LLToggleableMenu* menu = dynamic_cast<LLToggleableMenu*>(mMenuHandle.get());
+ if (menu)
+ {
+ menu->setVisible(FALSE);
+ }
}
-void LLMenuButton::setMenu(LLMenuGL* menu, EMenuPosition position /*MP_TOP_LEFT*/)
+LLToggleableMenu* LLMenuButton::getMenu()
{
- mMenu = menu;
- mMenuPosition = position;
+ return dynamic_cast<LLToggleableMenu*>(mMenuHandle.get());
}
-void LLMenuButton::draw()
+void LLMenuButton::setMenu(LLToggleableMenu* menu, EMenuPosition position /*MP_TOP_LEFT*/)
{
- //we save this off so next frame when we try to close it by
- //button click, and it hides menus before we get to it, we know
- mMenuVisibleLastFrame = mMenu && mMenu->getVisible();
-
- if (mMenuVisibleLastFrame)
- {
- setForcePressedState(true);
- }
+ if (!menu) return;
- LLButton::draw();
+ mMenuHandle = menu->getHandle();
+ mMenuPosition = position;
- setForcePressedState(false);
+ menu->setVisibilityChangeCallback(boost::bind(&LLMenuButton::onMenuVisibilityChange, this, _2));
}
BOOL LLMenuButton::handleKeyHere(KEY key, MASK mask )
{
+ if (mMenuHandle.isDead()) return FALSE;
+
if( KEY_RETURN == key && mask == MASK_NONE && !gKeyboard->getKeyRepeated(key))
{
// *HACK: We emit the mouse down signal to fire the callback bound to the
@@ -107,9 +111,10 @@ BOOL LLMenuButton::handleKeyHere(KEY key, MASK mask )
return TRUE;
}
- if (mMenu && mMenu->getVisible() && key == KEY_ESCAPE && mask == MASK_NONE)
+ LLToggleableMenu* menu = dynamic_cast<LLToggleableMenu*>(mMenuHandle.get());
+ if (menu && menu->getVisible() && key == KEY_ESCAPE && mask == MASK_NONE)
{
- mMenu->setVisible(FALSE);
+ menu->setVisible(FALSE);
return TRUE;
}
@@ -119,6 +124,7 @@ BOOL LLMenuButton::handleKeyHere(KEY key, MASK mask )
BOOL LLMenuButton::handleMouseDown(S32 x, S32 y, MASK mask)
{
LLButton::handleMouseDown(x, y, mask);
+
toggleMenu();
return TRUE;
@@ -126,28 +132,38 @@ BOOL LLMenuButton::handleMouseDown(S32 x, S32 y, MASK mask)
void LLMenuButton::toggleMenu()
{
- if(!mMenu) return;
+ if(mMenuHandle.isDead()) return;
+
+ LLToggleableMenu* menu = dynamic_cast<LLToggleableMenu*>(mMenuHandle.get());
+ if (!menu) return;
- if (mMenu->getVisible() || mMenuVisibleLastFrame)
+ // Store the button rectangle to toggle menu visibility if a mouse event
+ // occurred inside or outside the button rect.
+ menu->setButtonRect(this);
+
+ if (!menu->toggleVisibility() && mIsMenuShown)
{
- mMenu->setVisible(FALSE);
+ setForcePressedState(false);
+ mIsMenuShown = false;
}
else
{
- mMenu->buildDrawLabels();
- mMenu->arrangeAndClear();
- mMenu->updateParent(LLMenuGL::sMenuContainer);
+ menu->buildDrawLabels();
+ menu->arrangeAndClear();
+ menu->updateParent(LLMenuGL::sMenuContainer);
updateMenuOrigin();
- //mMenu->needsArrange(); //so it recalculates the visible elements
- LLMenuGL::showPopup(getParent(), mMenu, mX, mY);
+ LLMenuGL::showPopup(getParent(), menu, mX, mY);
+
+ setForcePressedState(true);
+ mIsMenuShown = true;
}
}
void LLMenuButton::updateMenuOrigin()
{
- if (!mMenu) return;
+ if (mMenuHandle.isDead()) return;
LLRect rect = getRect();
@@ -156,7 +172,7 @@ void LLMenuButton::updateMenuOrigin()
case MP_TOP_LEFT:
{
mX = rect.mLeft;
- mY = rect.mTop + mMenu->getRect().getHeight();
+ mY = rect.mTop + mMenuHandle.get()->getRect().getHeight();
break;
}
case MP_BOTTOM_LEFT:
@@ -167,3 +183,17 @@ void LLMenuButton::updateMenuOrigin()
}
}
}
+
+void LLMenuButton::onMenuVisibilityChange(const LLSD& param)
+{
+ bool new_visibility = param["visibility"].asBoolean();
+ bool is_closed_by_button_click = param["closed_by_button_click"].asBoolean();
+
+ // Reset the button "pressed" state only if the menu is shown by this particular
+ // menu button (not any other control) and is not being closed by a click on the button.
+ if (!new_visibility && !is_closed_by_button_click && mIsMenuShown)
+ {
+ setForcePressedState(false);
+ mIsMenuShown = false;
+ }
+}
diff --git a/indra/llui/llmenubutton.h b/indra/llui/llmenubutton.h
index 81c3592b16..9e91b9e99d 100644
--- a/indra/llui/llmenubutton.h
+++ b/indra/llui/llmenubutton.h
@@ -29,7 +29,7 @@
#include "llbutton.h"
-class LLMenuGL;
+class LLToggleableMenu;
class LLMenuButton
: public LLButton
@@ -52,14 +52,13 @@ public:
boost::signals2::connection setMouseDownCallback( const mouse_signal_t::slot_type& cb );
- /*virtual*/ void draw();
/*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask );
void hideMenu();
- LLMenuGL* getMenu() { return mMenu; }
- void setMenu(LLMenuGL* menu, EMenuPosition position = MP_TOP_LEFT);
+ LLToggleableMenu* getMenu();
+ void setMenu(LLToggleableMenu* menu, EMenuPosition position = MP_TOP_LEFT);
void setMenuPosition(EMenuPosition position) { mMenuPosition = position; }
@@ -70,12 +69,14 @@ protected:
void toggleMenu();
void updateMenuOrigin();
+ void onMenuVisibilityChange(const LLSD& param);
+
private:
- LLMenuGL* mMenu;
- bool mMenuVisibleLastFrame;
- EMenuPosition mMenuPosition;
- S32 mX;
- S32 mY;
+ LLHandle<LLView> mMenuHandle;
+ bool mIsMenuShown;
+ EMenuPosition mMenuPosition;
+ S32 mX;
+ S32 mY;
};
diff --git a/indra/llui/lltoggleablemenu.cpp b/indra/llui/lltoggleablemenu.cpp
index 0eb2dc1387..d29260750f 100644
--- a/indra/llui/lltoggleablemenu.cpp
+++ b/indra/llui/lltoggleablemenu.cpp
@@ -35,10 +35,22 @@ static LLDefaultChildRegistry::Register<LLToggleableMenu> r("toggleable_menu");
LLToggleableMenu::LLToggleableMenu(const LLToggleableMenu::Params& p)
: LLMenuGL(p),
mButtonRect(),
+ mVisibilityChangeSignal(NULL),
mClosedByButtonClick(false)
{
}
+LLToggleableMenu::~LLToggleableMenu()
+{
+ delete mVisibilityChangeSignal;
+}
+
+boost::signals2::connection LLToggleableMenu::setVisibilityChangeCallback(const commit_signal_t::slot_type& cb)
+{
+ if (!mVisibilityChangeSignal) mVisibilityChangeSignal = new commit_signal_t();
+ return mVisibilityChangeSignal->connect(cb);
+}
+
// virtual
void LLToggleableMenu::handleVisibilityChange (BOOL curVisibilityIn)
{
@@ -49,6 +61,12 @@ void LLToggleableMenu::handleVisibilityChange (BOOL curVisibilityIn)
{
mClosedByButtonClick = true;
}
+
+ if (mVisibilityChangeSignal)
+ {
+ (*mVisibilityChangeSignal)(this,
+ LLSD().with("visibility", curVisibilityIn).with("closed_by_button_click", mClosedByButtonClick));
+ }
}
void LLToggleableMenu::setButtonRect(const LLRect& rect, LLView* current_view)
diff --git a/indra/llui/lltoggleablemenu.h b/indra/llui/lltoggleablemenu.h
index f036cdfffb..2094bd776f 100644
--- a/indra/llui/lltoggleablemenu.h
+++ b/indra/llui/lltoggleablemenu.h
@@ -41,6 +41,10 @@ protected:
LLToggleableMenu(const Params&);
friend class LLUICtrlFactory;
public:
+ ~LLToggleableMenu();
+
+ boost::signals2::connection setVisibilityChangeCallback( const commit_signal_t::slot_type& cb );
+
virtual void handleVisibilityChange (BOOL curVisibilityIn);
const LLRect& getButtonRect() const { return mButtonRect; }
@@ -57,6 +61,7 @@ public:
protected:
bool mClosedByButtonClick;
LLRect mButtonRect;
+ commit_signal_t* mVisibilityChangeSignal;
};
#endif // LL_LLTOGGLEABLEMENU_H
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index f58c07754f..f49dfec82b 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -972,7 +972,7 @@ std::string LLUrlEntryWorldMap::getLocation(const std::string &url) const
//
LLUrlEntryNoLink::LLUrlEntryNoLink()
{
- mPattern = boost::regex("<nolink>[^<]*</nolink>",
+ mPattern = boost::regex("<nolink>.*</nolink>",
boost::regex::perl|boost::regex::icase);
}
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 086d73bc00..7172f0359a 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -12145,5 +12145,16 @@
<key>Value</key>
<real>300.0</real>
</map>
+ <key>GroupMembersSortOrder</key>
+ <map>
+ <key>Comment</key>
+ <string>The order by which group members will be sorted (name|donated|online)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string>name</string>
+ </map>
</map>
</llsd>
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index b09dd699ba..d69842d5f1 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -1,4 +1,4 @@
-version 23
+version 25
// NOTE: This is mostly identical to featuretable_mac.txt with a few differences
// Should be combined into one table
@@ -144,7 +144,7 @@ WLSkyDetail 1 48
RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
-RenderUseFBO 1 1
+RenderUseFBO 1 0
//
// Ultra graphics (REALLY PURTY!)
@@ -171,7 +171,7 @@ WLSkyDetail 1 128
RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
-RenderUseFBO 1 1
+RenderUseFBO 1 0
//
// Class Unknown Hardware (unknown)
diff --git a/indra/newview/featuretable_xp.txt b/indra/newview/featuretable_xp.txt
index 1e83bc73a5..dae7705971 100644
--- a/indra/newview/featuretable_xp.txt
+++ b/indra/newview/featuretable_xp.txt
@@ -1,4 +1,4 @@
-version 23
+version 25
// NOTE: This is mostly identical to featuretable_mac.txt with a few differences
// Should be combined into one table
@@ -144,7 +144,7 @@ WLSkyDetail 1 48
RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
-RenderUseFBO 1 1
+RenderUseFBO 1 0
//
// Ultra graphics (REALLY PURTY!)
@@ -171,7 +171,7 @@ WLSkyDetail 1 128
RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
-RenderUseFBO 1 1
+RenderUseFBO 1 0
//
// Class Unknown Hardware (unknown)
diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi
index d1cd335783..d5712f80cf 100644
--- a/indra/newview/installers/windows/installer_template.nsi
+++ b/indra/newview/installers/windows/installer_template.nsi
@@ -52,7 +52,7 @@ LangString LanguageCode ${LANG_JAPANESE} "ja"
LangString LanguageCode ${LANG_ITALIAN} "it"
LangString LanguageCode ${LANG_KOREAN} "ko"
LangString LanguageCode ${LANG_DUTCH} "nl"
-LangString LanguageCode ${LANG_POLISH} "da"
+LangString LanguageCode ${LANG_POLISH} "pl"
LangString LanguageCode ${LANG_PORTUGUESEBR} "pt"
LangString LanguageCode ${LANG_SIMPCHINESE} "zh"
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index 378c4358b3..cb5cf4a61d 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -54,6 +54,7 @@
#include "llviewertexteditor.h"
#include "llworld.h"
#include "lluiconstants.h"
+#include "llstring.h"
#include "llviewercontrol.h"
@@ -260,7 +261,7 @@ public:
if((chat.mFromID.isNull() && chat.mFromName.empty()) || chat.mFromName == SYSTEM_FROM && chat.mFromID.isNull())
{
mSourceType = CHAT_SOURCE_SYSTEM;
- }
+ }
mUserNameFont = style_params.font();
LLTextBox* user_name = getChild<LLTextBox>("user_name");
@@ -268,14 +269,14 @@ public:
user_name->setColor(style_params.color());
if (chat.mFromName.empty()
- || mSourceType == CHAT_SOURCE_SYSTEM
- || mAvatarID.isNull())
+ || mSourceType == CHAT_SOURCE_SYSTEM)
{
mFrom = LLTrans::getString("SECOND_LIFE");
user_name->setValue(mFrom);
updateMinUserNameWidth();
}
else if (mSourceType == CHAT_SOURCE_AGENT
+ && !mAvatarID.isNull()
&& chat.mChatStyle != CHAT_STYLE_HISTORY)
{
// ...from a normal user, lookup the name and fill in later.
@@ -288,7 +289,41 @@ public:
LLAvatarNameCache::get(mAvatarID,
boost::bind(&LLChatHistoryHeader::onAvatarNameCache, this, _1, _2));
}
- else {
+ else if (chat.mChatStyle == CHAT_STYLE_HISTORY ||
+ mSourceType == CHAT_SOURCE_AGENT)
+ {
+ //if it's an avatar name with a username add formatting
+ S32 username_start = chat.mFromName.rfind(" (");
+ S32 username_end = chat.mFromName.rfind(')');
+
+ if (username_start != std::string::npos &&
+ username_end == (chat.mFromName.length() - 1))
+ {
+ mFrom = chat.mFromName.substr(0, username_start);
+ user_name->setValue(mFrom);
+
+ if (gSavedSettings.getBOOL("NameTagShowUsernames"))
+ {
+ std::string username = chat.mFromName.substr(username_start + 2);
+ username = username.substr(0, username.length() - 1);
+ LLStyle::Params style_params_name;
+ LLColor4 userNameColor = LLUIColorTable::instance().getColor("EmphasisColor");
+ style_params_name.color(userNameColor);
+ style_params_name.font.name("SansSerifSmall");
+ style_params_name.font.style("NORMAL");
+ style_params_name.readonly_color(userNameColor);
+ user_name->appendText(" - " + username, FALSE, style_params_name);
+ }
+ }
+ else
+ {
+ mFrom = chat.mFromName;
+ user_name->setValue(mFrom);
+ updateMinUserNameWidth();
+ }
+ }
+ else
+ {
// ...from an object, just use name as given
mFrom = chat.mFromName;
user_name->setValue(mFrom);
@@ -367,7 +402,9 @@ public:
user_name->setValue( LLSD(av_name.mDisplayName ) );
user_name->setToolTip( av_name.mUsername );
- if (gSavedSettings.getBOOL("NameTagShowUsernames") && LLAvatarNameCache::useDisplayNames())
+ if (gSavedSettings.getBOOL("NameTagShowUsernames") &&
+ LLAvatarNameCache::useDisplayNames() &&
+ !av_name.mIsDisplayNameDefault)
{
LLStyle::Params style_params_name;
LLColor4 userNameColor = LLUIColorTable::instance().getColor("EmphasisColor");
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index fe8a46e908..914e7a3df0 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -430,8 +430,9 @@ void LLIMModel::LLIMSession::addMessagesFromHistory(const std::list<LLSD>& histo
}
else
{
- // Legacy chat logs only wrote the legacy name, not the agent_id
- gCacheName->getUUID(from, from_id);
+ // convert it to a legacy name if we have a complete name
+ std::string legacy_name = gCacheName->buildLegacyName(from);
+ gCacheName->getUUID(legacy_name, from_id);
}
std::string timestamp = msg[IM_TIME];
@@ -526,8 +527,16 @@ bool LLIMModel::LLIMSession::isOtherParticipantAvaline()
void LLIMModel::LLIMSession::onAvatarNameCache(const LLUUID& avatar_id, const LLAvatarName& av_name)
{
- // if username is empty, display names isn't enabled, use the display name
- mHistoryFileName = av_name.mUsername.empty() ? av_name.mDisplayName : av_name.mUsername;
+ if (av_name.mLegacyFirstName.empty())
+ {
+ // if mLegacyFirstName is empty it means display names is off and the
+ // data came from the gCacheName, mDisplayName will be the legacy name
+ mHistoryFileName = LLCacheName::cleanFullName(av_name.mDisplayName);
+ }
+ else
+ {
+ mHistoryFileName = LLCacheName::cleanFullName(av_name.getLegacyName());
+ }
}
void LLIMModel::LLIMSession::buildHistoryFileName()
@@ -737,8 +746,18 @@ bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from,
bool LLIMModel::logToFile(const std::string& file_name, const std::string& from, const LLUUID& from_id, const std::string& utf8_text)
{
if (gSavedPerAccountSettings.getBOOL("LogInstantMessages"))
- {
- LLLogChat::saveHistory(file_name, from, from_id, utf8_text);
+ {
+ std::string from_name = from;
+
+ LLAvatarName av_name;
+ if (!from_id.isNull() &&
+ LLAvatarNameCache::get(from_id, &av_name) &&
+ !av_name.mIsDisplayNameDefault)
+ {
+ from_name = av_name.getCompleteName();
+ }
+
+ LLLogChat::saveHistory(file_name, from_name, from_id, utf8_text);
return true;
}
else
diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp
index 29dcb2c4d3..91ede6d221 100644
--- a/indra/newview/llinspectavatar.cpp
+++ b/indra/newview/llinspectavatar.cpp
@@ -53,6 +53,7 @@
#include "llfloaterreg.h"
#include "llmenubutton.h"
#include "lltextbox.h"
+#include "lltoggleablemenu.h"
#include "lltooltip.h" // positionViewNearMouse()
#include "lltrans.h"
#include "lluictrl.h"
@@ -402,8 +403,8 @@ void LLInspectAvatar::processAvatarData(LLAvatarData* data)
// if neither the gear menu or self gear menu are open
void LLInspectAvatar::onMouseLeave(S32 x, S32 y, MASK mask)
{
- LLMenuGL* gear_menu = getChild<LLMenuButton>("gear_btn")->getMenu();
- LLMenuGL* gear_menu_self = getChild<LLMenuButton>("gear_self_btn")->getMenu();
+ LLToggleableMenu* gear_menu = getChild<LLMenuButton>("gear_btn")->getMenu();
+ LLToggleableMenu* gear_menu_self = getChild<LLMenuButton>("gear_self_btn")->getMenu();
if ( gear_menu && gear_menu->getVisible() &&
gear_menu_self && gear_menu_self->getVisible() )
{
diff --git a/indra/newview/llinspectobject.cpp b/indra/newview/llinspectobject.cpp
index 532ffca4be..ee076f68ea 100644
--- a/indra/newview/llinspectobject.cpp
+++ b/indra/newview/llinspectobject.cpp
@@ -47,6 +47,7 @@
#include "llsafehandle.h"
#include "llsidetray.h"
#include "lltextbox.h" // for description truncation
+#include "lltoggleablemenu.h"
#include "lltrans.h"
#include "llui.h" // positionViewNearMouse()
#include "lluictrl.h"
@@ -568,7 +569,7 @@ void LLInspectObject::updateSecureBrowsing()
// if the gear menu is not open
void LLInspectObject::onMouseLeave(S32 x, S32 y, MASK mask)
{
- LLMenuGL* gear_menu = getChild<LLMenuButton>("gear_btn")->getMenu();
+ LLToggleableMenu* gear_menu = getChild<LLMenuButton>("gear_btn")->getMenu();
if ( gear_menu && gear_menu->getVisible() )
{
return;
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index c8fd1e1d9a..8c70b1e973 100644
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -26,18 +26,13 @@
#include "llviewerprecompiledheaders.h"
-#include "lllogchat.h"
-
-// viewer includes
#include "llagent.h"
#include "llagentui.h"
+#include "lllogchat.h"
#include "lltrans.h"
#include "llviewercontrol.h"
-// library includes
-#include "llchat.h"
#include "llinstantmessage.h"
-#include "llsdserialize.h"
#include "llsingleton.h" // for LLSingleton
#include <boost/algorithm/string/trim.hpp>
@@ -65,7 +60,6 @@ const std::string IM_TIME("time");
const std::string IM_TEXT("message");
const std::string IM_FROM("from");
const std::string IM_FROM_ID("from_id");
-const std::string IM_SOURCE_TYPE("source_type");
const static std::string IM_SEPARATOR(": ");
const static std::string NEW_LINE("\n");
@@ -93,7 +87,7 @@ const static boost::regex TIMESTAMP_AND_STUFF("^(\\[\\d{4}/\\d{1,2}/\\d{1,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 boost::regex NAME_AND_TEXT("([^:]+[:]{1})?(\\s*)(.*)");
//is used to parse complex object names like "Xstreet SL Terminal v2.2.5 st"
const static std::string NAME_TEXT_DIVIDER(": ");
@@ -190,8 +184,7 @@ std::string LLLogChat::makeLogFileName(std::string filename)
{
filename = cleanFileName(filename);
filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS,filename);
- // new files are llsd notation format
- filename += ".llsd";
+ filename += ".txt";
return filename;
}
@@ -241,18 +234,6 @@ void LLLogChat::saveHistory(const std::string& filename,
const LLUUID& from_id,
const std::string& line)
{
- LLChat chat;
- chat.mText = line;
- chat.mFromName = from;
- chat.mFromID = from_id;
- // default to being from an agent
- chat.mSourceType = CHAT_SOURCE_AGENT;
- saveHistory(filename, chat);
-}
-
-//static
-void LLLogChat::saveHistory(const std::string& filename, const LLChat& chat)
-{
std::string tmp_filename = filename;
LLStringUtil::trim(tmp_filename);
if (tmp_filename.empty())
@@ -273,27 +254,89 @@ void LLLogChat::saveHistory(const std::string& filename, const LLChat& chat)
LLSD item;
if (gSavedPerAccountSettings.getBOOL("LogTimestamp"))
- item[IM_TIME] = LLLogChat::timestamp(gSavedPerAccountSettings.getBOOL("LogTimestampDate"));
+ item["time"] = LLLogChat::timestamp(gSavedPerAccountSettings.getBOOL("LogTimestampDate"));
- item[IM_FROM_ID] = chat.mFromID;
- item[IM_TEXT] = chat.mText;
- item[IM_SOURCE_TYPE] = chat.mSourceType;
+ item["from_id"] = from_id;
+ item["message"] = line;
//adding "Second Life:" for all system messages to make chat log history parsing more reliable
- if (chat.mFromName.empty() && chat.mFromID.isNull())
+ if (from.empty() && from_id.isNull())
{
- item[IM_FROM] = SYSTEM_FROM;
+ item["from"] = SYSTEM_FROM;
}
else
{
- item[IM_FROM] = chat.mFromName;
+ item["from"] = from;
}
- file << LLSDOStreamer<LLSDNotationFormatter>(item) << std::endl;
+ file << LLChatLogFormatter(item) << std::endl;
file.close();
}
+void LLLogChat::loadHistory(const std::string& filename, void (*callback)(ELogLineType, const LLSD&, void*), void* userdata)
+{
+ if(!filename.size())
+ {
+ llwarns << "Filename is Empty!" << llendl;
+ return ;
+ }
+
+ LLFILE* fptr = LLFile::fopen(makeLogFileName(filename), "r"); /*Flawfinder: ignore*/
+ if (!fptr)
+ {
+ callback(LOG_EMPTY, LLSD(), userdata);
+ return; //No previous conversation with this name.
+ }
+ else
+ {
+ 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)
+ {
+ LLSD item;
+ std::string line(buffer);
+ std::istringstream iss(line);
+
+ if (!LLChatLogParser::parse(line, item))
+ {
+ item["message"] = line;
+ callback(LOG_LINE, item, userdata);
+ }
+ else
+ {
+ callback(LOG_LLSD, item, userdata);
+ }
+ }
+ else
+ {
+ firstline = FALSE;
+ }
+ }
+ callback(LOG_END, LLSD(), userdata);
+
+ fclose(fptr);
+ }
+}
+
void append_to_last_message(std::list<LLSD>& messages, const std::string& line)
{
if (!messages.size()) return;
@@ -367,24 +410,52 @@ void LLLogChat::loadAllHistory(const std::string& file_name, std::list<LLSD>& me
fclose(fptr);
}
-// static
-bool LLChatLogParser::parse(const std::string& raw, LLSD& im)
+//*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 <actual_object's_name>"
+void LLChatLogFormatter::format(const LLSD& im, std::ostream& ostr) const
{
- if (!raw.length()) return false;
+ 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;
+ }
- im = LLSD::emptyMap();
+ //*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 <actual_object's_name>"
+ if (im[IM_FROM].isDefined())
+ {
+ std::string from = im[IM_FROM].asString();
+ boost::trim(from);
+ if (from.size())
+ {
+ ostr << from << IM_SEPARATOR;
+ }
+ }
- // In Viewer 2.1 we added UUID to chat/IM logging so we can look up
- // display names
- if (raw[0] == '{')
+ if (im[IM_TEXT].isDefined())
{
- // ...this is a viewer 2.1, new-style LLSD notation format log
- std::istringstream raw_stream(raw);
- LLPointer<LLSDParser> parser = new LLSDNotationParser();
- S32 count = parser->parse(raw_stream, im, raw.length());
- // expect several map items per parsed line
- return (count != LLSDParser::PARSE_FAILURE);
+ 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<std::string::const_iterator> matches;
diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h
index 8b1cc3484f..6958d56311 100644
--- a/indra/newview/lllogchat.h
+++ b/indra/newview/lllogchat.h
@@ -41,22 +41,49 @@ public:
};
static std::string timestamp(bool withdate = false);
static std::string makeLogFileName(std::string(filename));
-
- // Log a single line item to the appropriate chat file
- static void saveHistory(const std::string& filename, const LLChat& chat);
-
- // Prefer the above version - it saves more metadata about the item
static void saveHistory(const std::string& filename,
const std::string& from,
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& file_name, std::list<LLSD>& 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
@@ -74,7 +101,7 @@ public:
*
* @return false if failed to parse mandatory data - message text
*/
- static bool parse(const std::string& raw, LLSD& im);
+ static bool parse(std::string& raw, LLSD& im);
protected:
LLChatLogParser();
@@ -86,6 +113,5 @@ extern const std::string IM_TIME; //("time");
extern const std::string IM_TEXT; //("message");
extern const std::string IM_FROM; //("from");
extern const std::string IM_FROM_ID; //("from_id");
-extern const std::string IM_SOURCE_TYPE; //("source_type");
#endif
diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp
index f16cc4cef4..180695e40b 100644
--- a/indra/newview/llnearbychat.cpp
+++ b/indra/newview/llnearbychat.cpp
@@ -46,6 +46,8 @@
#include "llchathistory.h"
#include "llstylemap.h"
+#include "llavatarnamecache.h"
+
#include "lldraghandle.h"
#include "llbottomtray.h"
@@ -179,7 +181,21 @@ void LLNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args)
if (gSavedPerAccountSettings.getBOOL("LogNearbyChat"))
{
- LLLogChat::saveHistory("chat", chat);
+ std::string from_name = chat.mFromName;
+
+ if (chat.mSourceType == CHAT_SOURCE_AGENT)
+ {
+ // if the chat is coming from an agent, log the complete name
+ LLAvatarName av_name;
+ LLAvatarNameCache::get(chat.mFromID, &av_name);
+
+ if (!av_name.mIsDisplayNameDefault)
+ {
+ from_name = av_name.getCompleteName();
+ }
+ }
+
+ LLLogChat::saveHistory("chat", from_name, chat.mFromID, chat.mText);
}
}
@@ -248,11 +264,23 @@ void LLNearbyChat::processChatHistoryStyleUpdate(const LLSD& newvalue)
nearby_chat->updateChatHistoryStyle();
}
-bool isTwoWordsName(const std::string& name)
+bool isWordsName(const std::string& name)
{
- //checking for a single space
- S32 pos = name.find(' ', 0);
- return std::string::npos != pos && name.rfind(' ', name.length()) == pos && 0 != pos && name.length()-1 != pos;
+ // checking to see if it's display name plus username in parentheses
+ S32 open_paren = name.find(" (", 0);
+ S32 close_paren = name.find(')', 0);
+
+ if (open_paren != std::string::npos &&
+ close_paren == name.length()-1)
+ {
+ return true;
+ }
+ else
+ {
+ //checking for a single space
+ S32 pos = name.find(' ', 0);
+ return std::string::npos != pos && name.rfind(' ', name.length()) == pos && 0 != pos && name.length()-1 != pos;
+ }
}
void LLNearbyChat::loadHistory()
@@ -275,9 +303,10 @@ void LLNearbyChat::loadHistory()
from_id = msg[IM_FROM_ID].asUUID();
}
else
- {
- gCacheName->getUUID(from, from_id);
- }
+ {
+ std::string legacy_name = gCacheName->buildLegacyName(from);
+ gCacheName->getUUID(legacy_name, from_id);
+ }
LLChat chat;
chat.mFromName = from;
@@ -286,18 +315,15 @@ void LLNearbyChat::loadHistory()
chat.mTimeStr = msg[IM_TIME].asString();
chat.mChatStyle = CHAT_STYLE_HISTORY;
- if (msg.has(IM_SOURCE_TYPE))
- {
- S32 source_type = msg[IM_SOURCE_TYPE].asInteger();
- chat.mSourceType = (EChatSourceType)source_type;
- }
- else if (from_id.isNull() && SYSTEM_FROM == from)
+ chat.mSourceType = CHAT_SOURCE_AGENT;
+ if (from_id.isNull() && SYSTEM_FROM == from)
{
chat.mSourceType = CHAT_SOURCE_SYSTEM;
+
}
else if (from_id.isNull())
{
- chat.mSourceType = isTwoWordsName(from) ? CHAT_SOURCE_UNKNOWN : CHAT_SOURCE_OBJECT;
+ chat.mSourceType = isWordsName(from) ? CHAT_SOURCE_UNKNOWN : CHAT_SOURCE_OBJECT;
}
addMessage(chat, true, do_not_log);
diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp
index 33c968bf00..70295259b3 100644
--- a/indra/newview/lloutfitslist.cpp
+++ b/indra/newview/lloutfitslist.cpp
@@ -42,6 +42,7 @@
#include "llnotificationsutil.h"
#include "lloutfitobserver.h"
#include "llsidetray.h"
+#include "lltoggleablemenu.h"
#include "lltransutil.h"
#include "llviewermenu.h"
#include "llvoavatar.h"
@@ -122,7 +123,7 @@ public:
enable_registrar.add("Gear.OnEnable", boost::bind(&LLOutfitListGearMenu::onEnable, this, _2));
enable_registrar.add("Gear.OnVisible", boost::bind(&LLOutfitListGearMenu::onVisible, this, _2));
- mMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(
+ mMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(
"menu_outfit_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
llassert(mMenu);
}
@@ -137,7 +138,7 @@ public:
mMenu->arrangeAndClear(); // update menu height
}
- LLMenuGL* getMenu() { return mMenu; }
+ LLToggleableMenu* getMenu() { return mMenu; }
private:
const LLUUID& getSelectedOutfitID()
@@ -251,8 +252,8 @@ private:
return true;
}
- LLOutfitsList* mOutfitList;
- LLMenuGL* mMenu;
+ LLOutfitsList* mOutfitList;
+ LLToggleableMenu* mMenu;
};
//////////////////////////////////////////////////////////////////////////
diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp
index 35f898bfa6..0d1d96eae6 100644
--- a/indra/newview/llpanelgrouproles.cpp
+++ b/indra/newview/llpanelgrouproles.cpp
@@ -49,6 +49,7 @@
#include "llviewertexturelist.h"
#include "llviewerwindow.h"
#include "llfocusmgr.h"
+#include "llviewercontrol.h"
#include "roles_constants.h"
@@ -742,10 +743,12 @@ LLPanelGroupMembersSubTab::LLPanelGroupMembersSubTab()
mHasMatch(FALSE),
mNumOwnerAdditions(0)
{
+ mUdpateSessionID = LLUUID::null;
}
LLPanelGroupMembersSubTab::~LLPanelGroupMembersSubTab()
{
+ gSavedSettings.setString("GroupMembersSortOrder", mMembersList->getSortColumnName());
}
BOOL LLPanelGroupMembersSubTab::postBuildSubTab(LLView* root)
@@ -772,6 +775,17 @@ BOOL LLPanelGroupMembersSubTab::postBuildSubTab(LLView* root)
// Show the member's profile on double click.
mMembersList->setDoubleClickCallback(onMemberDoubleClick, this);
mMembersList->setContextMenu(LLScrollListCtrl::MENU_AVATAR);
+
+ LLSD row;
+ row["columns"][0]["column"] = "name";
+ row["columns"][1]["column"] = "donated";
+ row["columns"][2]["column"] = "online";
+ mMembersList->addElement(row);
+ std::string order_by = gSavedSettings.getString("GroupMembersSortOrder");
+ if(!order_by.empty())
+ {
+ mMembersList->sortByColumn(order_by, TRUE);
+ }
LLButton* button = parent->getChild<LLButton>("member_invite", recurse);
if ( button )
@@ -1529,6 +1543,10 @@ void LLPanelGroupMembersSubTab::update(LLGroupChange gc)
mMemberProgress = gdatap->mMembers.begin();
mPendingMemberUpdate = TRUE;
mHasMatch = FALSE;
+ // Generate unique ID for current updateMembers()- see onNameCache for details.
+ // Using unique UUID is perhaps an overkill but this way we are perfectly safe
+ // from coincidences.
+ mUdpateSessionID.generate();
}
else
{
@@ -1556,6 +1574,59 @@ void LLPanelGroupMembersSubTab::update(LLGroupChange gc)
}
}
+void LLPanelGroupMembersSubTab::addMemberToList(LLUUID id, LLGroupMemberData* data)
+{
+ LLUIString donated = getString("donation_area");
+ donated.setArg("[AREA]", llformat("%d", data->getContribution()));
+
+ LLSD row;
+ row["id"] = id;
+
+ row["columns"][0]["column"] = "name";
+ // value is filled in by name list control
+
+ row["columns"][1]["column"] = "donated";
+ row["columns"][1]["value"] = donated.getString();
+
+ row["columns"][2]["column"] = "online";
+ row["columns"][2]["value"] = data->getOnlineStatus();
+ row["columns"][2]["font"] = "SANSSERIF_SMALL";
+
+ mMembersList->addElement(row);
+
+ mHasMatch = TRUE;
+}
+
+void LLPanelGroupMembersSubTab::onNameCache(const LLUUID& update_id, const LLUUID& id)
+{
+ // Update ID is used to determine whether member whose id is passed
+ // into onNameCache() was passed after current or previous user-initiated update.
+ // This is needed to avoid probable duplication of members in list after changing filter
+ // or adding of members of another group if gets for their names were called on
+ // previous update. If this id is from get() called from older update,
+ // we do nothing.
+ if (mUdpateSessionID != update_id) return;
+
+ LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
+ if (!gdatap)
+ {
+ llwarns << "LLPanelGroupMembersSubTab::updateMembers() -- No group data!" << llendl;
+ return;
+ }
+
+ std::string fullname;
+ gCacheName->getFullName(id, fullname);
+ if (matchesSearchFilter(fullname))
+ {
+ addMemberToList(id, gdatap->mMembers[id]);
+ if(!mMembersList->getEnabled())
+ {
+ mMembersList->setEnabled(TRUE);
+ }
+ }
+
+}
+
void LLPanelGroupMembersSubTab::updateMembers()
{
mPendingMemberUpdate = FALSE;
@@ -1580,12 +1651,13 @@ void LLPanelGroupMembersSubTab::updateMembers()
//cleanup list only for first iretation
if(mMemberProgress == gdatap->mMembers.begin())
+ {
mMembersList->deleteAllItems();
+ }
LLGroupMgrGroupData::member_list_t::iterator end = gdatap->mMembers.end();
- LLUIString donated = getString("donation_area");
-
+
S32 i = 0;
for( ; mMemberProgress != end && i<UPDATE_MEMBERS_PER_FRAME;
++mMemberProgress, ++i)
@@ -1593,38 +1665,19 @@ void LLPanelGroupMembersSubTab::updateMembers()
if (!mMemberProgress->second)
continue;
// Do filtering on name if it is already in the cache.
- bool add_member = true;
-
std::string fullname;
if (gCacheName->getFullName(mMemberProgress->first, fullname))
{
- if ( !matchesSearchFilter(fullname) )
+ if (matchesSearchFilter(fullname))
{
- add_member = false;
+ addMemberToList(mMemberProgress->first, mMemberProgress->second);
}
}
-
- if (add_member)
+ else
{
- donated.setArg("[AREA]", llformat("%d", mMemberProgress->second->getContribution()));
-
- LLSD row;
- row["id"] = (*mMemberProgress).first;
-
- row["columns"][0]["column"] = "name";
- // value is filled in by name list control
-
- row["columns"][1]["column"] = "donated";
- row["columns"][1]["value"] = donated.getString();
-
- row["columns"][2]["column"] = "online";
- row["columns"][2]["value"] = mMemberProgress->second->getOnlineStatus();
- row["columns"][2]["font"] = "SANSSERIF_SMALL";
-
- LLScrollListItem* member = mMembersList->addElement(row);
-
- LLUUID id = member->getUUID();
- mHasMatch = TRUE;
+ // If name is not cached, onNameCache() should be called when it is cached and add this member to list.
+ gCacheName->get(mMemberProgress->first, FALSE, boost::bind(&LLPanelGroupMembersSubTab::onNameCache,
+ this, mUdpateSessionID, _1));
}
}
diff --git a/indra/newview/llpanelgrouproles.h b/indra/newview/llpanelgrouproles.h
index 6a773f1ebb..270259c16f 100644
--- a/indra/newview/llpanelgrouproles.h
+++ b/indra/newview/llpanelgrouproles.h
@@ -187,6 +187,9 @@ public:
virtual void setGroupID(const LLUUID& id);
+ void addMemberToList(LLUUID id, LLGroupMemberData* data);
+ void onNameCache(const LLUUID& update_id, const LLUUID& id);
+
protected:
typedef std::map<LLUUID, LLRoleMemberChangeType> role_change_data_map_t;
typedef std::map<LLUUID, role_change_data_map_t*> member_role_changes_map_t;
@@ -207,6 +210,9 @@ protected:
BOOL mPendingMemberUpdate;
BOOL mHasMatch;
+ // This id is generated after each user initiated member list update(opening Roles or changing filter)
+ LLUUID mUdpateSessionID;
+
member_role_changes_map_t mMemberRoleChangeData;
U32 mNumOwnerAdditions;
diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index e5695f420a..d25b8e0e02 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -51,6 +51,7 @@
#include "llplacesinventorybridge.h"
#include "llplacesinventorypanel.h"
#include "llsidetray.h"
+#include "lltoggleablemenu.h"
#include "llviewermenu.h"
#include "llviewerregion.h"
@@ -706,8 +707,8 @@ void LLLandmarksPanel::initListCommandsHandlers()
mCommitCallbackRegistrar.add("Places.LandmarksGear.Folding.Action", boost::bind(&LLLandmarksPanel::onFoldingAction, this, _2));
mEnableCallbackRegistrar.add("Places.LandmarksGear.Check", boost::bind(&LLLandmarksPanel::isActionChecked, this, _2));
mEnableCallbackRegistrar.add("Places.LandmarksGear.Enable", boost::bind(&LLLandmarksPanel::isActionEnabled, this, _2));
- mGearLandmarkMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_places_gear_landmark.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
- mGearFolderMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_places_gear_folder.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ mGearLandmarkMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_places_gear_landmark.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ mGearFolderMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_places_gear_folder.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
mMenuAdd = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_place_add_button.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
mListCommands->childSetAction(ADD_BUTTON_NAME, boost::bind(&LLLandmarksPanel::showActionMenu, this, mMenuAdd, ADD_BUTTON_NAME));
@@ -726,7 +727,7 @@ void LLLandmarksPanel::updateListCommands()
void LLLandmarksPanel::onActionsButtonClick()
{
- LLMenuGL* menu = mGearFolderMenu;
+ LLToggleableMenu* menu = mGearFolderMenu;
LLFolderViewItem* cur_item = NULL;
if(mCurrentSelectedList)
diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h
index 28c19d3e5f..8dcbca0440 100644
--- a/indra/newview/llpanellandmarks.h
+++ b/indra/newview/llpanellandmarks.h
@@ -41,6 +41,7 @@ class LLAccordionCtrlTab;
class LLFolderViewItem;
class LLMenuButton;
class LLMenuGL;
+class LLToggleableMenu;
class LLInventoryPanel;
class LLPlacesInventoryPanel;
@@ -157,8 +158,8 @@ private:
LLPlacesInventoryPanel* mMyInventoryPanel;
LLPlacesInventoryPanel* mLibraryInventoryPanel;
LLMenuButton* mGearButton;
- LLMenuGL* mGearLandmarkMenu;
- LLMenuGL* mGearFolderMenu;
+ LLToggleableMenu* mGearLandmarkMenu;
+ LLToggleableMenu* mGearFolderMenu;
LLMenuGL* mMenuAdd;
LLPlacesInventoryPanel* mCurrentSelectedList;
LLInventoryObserver* mInventoryObserver;
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index cc69dbd9d4..904e3dabcc 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -46,6 +46,7 @@
#include "llscrollcontainer.h"
#include "llsdserialize.h"
#include "llspinctrl.h"
+#include "lltoggleablemenu.h"
#include "lltooldraganddrop.h"
#include "llviewermenu.h"
#include "llviewertexturelist.h"
@@ -915,7 +916,7 @@ void LLPanelMainInventory::initListCommandsHandlers()
mCommitCallbackRegistrar.add("Inventory.GearDefault.Custom.Action", boost::bind(&LLPanelMainInventory::onCustomAction, this, _2));
mEnableCallbackRegistrar.add("Inventory.GearDefault.Enable", boost::bind(&LLPanelMainInventory::isActionEnabled, this, _2));
- mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
mGearMenuButton->setMenu(mMenuGearDefault);
mMenuAdd = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_add.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h
index f95a99157d..d136e2d32e 100644
--- a/indra/newview/llpanelmaininventory.h
+++ b/indra/newview/llpanelmaininventory.h
@@ -42,6 +42,7 @@ class LLTabContainer;
class LLFloaterInventoryFinder;
class LLMenuButton;
class LLMenuGL;
+class LLToggleableMenu;
class LLFloater;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -143,7 +144,7 @@ protected:
void setUploadCostIfNeeded();
private:
LLDragAndDropButton* mTrashButton;
- LLMenuGL* mMenuGearDefault;
+ LLToggleableMenu* mMenuGearDefault;
LLMenuGL* mMenuAdd;
LLMenuButton* mGearMenuButton;
diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp
index 5638374178..ce9b1c66d7 100644
--- a/indra/newview/llpaneloutfitedit.cpp
+++ b/indra/newview/llpaneloutfitedit.cpp
@@ -62,6 +62,7 @@
#include "llsaveoutfitcombobtn.h"
#include "llscrolllistctrl.h"
#include "lltextbox.h"
+#include "lltoggleablemenu.h"
#include "lltrans.h"
#include "lluictrlfactory.h"
#include "llsdutil.h"
@@ -152,13 +153,13 @@ std::string LLShopURLDispatcher::resolveURL(LLAssetType::EType asset_type, ESex
class LLPanelOutfitEditGearMenu
{
public:
- static LLMenuGL* create()
+ static LLToggleableMenu* create()
{
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
registrar.add("Wearable.Create", boost::bind(onCreate, _2));
- LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(
+ LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(
"menu_cof_gear.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
llassert(menu);
if (menu)
@@ -219,7 +220,7 @@ private:
class LLAddWearablesGearMenu : public LLInitClass<LLAddWearablesGearMenu>
{
public:
- static LLMenuGL* create(LLWearableItemsList* flat_list, LLInventoryPanel* inventory_panel)
+ static LLToggleableMenu* create(LLWearableItemsList* flat_list, LLInventoryPanel* inventory_panel)
{
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
@@ -234,7 +235,7 @@ public:
enable_registrar.add("AddWearable.Gear.Check", boost::bind(onCheck, flat_list_handle, inventory_panel_handle, _2));
enable_registrar.add("AddWearable.Gear.Visible", boost::bind(onVisible, inventory_panel_handle, _2));
- LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(
+ LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(
"menu_add_wearable_gear.xml",
LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
@@ -404,6 +405,7 @@ LLPanelOutfitEdit::LLPanelOutfitEdit()
mAddWearablesPanel(NULL),
mFolderViewFilterCmbBox(NULL),
mListViewFilterCmbBox(NULL),
+ mWearableListManager(NULL),
mPlusBtn(NULL),
mWearablesGearMenuBtn(NULL),
mGearMenuBtn(NULL)
@@ -431,6 +433,7 @@ LLPanelOutfitEdit::LLPanelOutfitEdit()
LLPanelOutfitEdit::~LLPanelOutfitEdit()
{
+ delete mWearableListManager;
delete mSavedFolderState;
delete mCOFDragAndDropObserver;
diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h
index 963db84503..fd366e9cbc 100644
--- a/indra/newview/llpaneloutfitedit.h
+++ b/indra/newview/llpaneloutfitedit.h
@@ -233,8 +233,8 @@ private:
std::vector<LLFilterItem*> mListViewItemTypes;
LLCOFWearables* mCOFWearables;
- LLMenuGL* mGearMenu;
- LLMenuGL* mAddWearablesGearMenu;
+ LLToggleableMenu* mGearMenu;
+ LLToggleableMenu* mAddWearablesGearMenu;
bool mInitialized;
std::auto_ptr<LLSaveOutfitComboBtn> mSaveComboBtn;
LLMenuButton* mWearablesGearMenuBtn;
diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp
index b79a2d3224..71c812efe2 100644
--- a/indra/newview/llpanelpeople.cpp
+++ b/indra/newview/llpanelpeople.cpp
@@ -35,6 +35,7 @@
#include "lleventtimer.h"
#include "llfiltereditor.h"
#include "lltabcontainer.h"
+#include "lltoggleablemenu.h"
#include "lluictrlfactory.h"
#include "llpanelpeople.h"
@@ -632,28 +633,28 @@ BOOL LLPanelPeople::postBuild()
LLMenuGL* plus_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_group_plus.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
mGroupPlusMenuHandle = plus_menu->getHandle();
- LLMenuGL* nearby_view_sort = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_people_nearby_view_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ LLToggleableMenu* nearby_view_sort = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_nearby_view_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
if(nearby_view_sort)
{
mNearbyViewSortMenuHandle = nearby_view_sort->getHandle();
mNearbyGearButton->setMenu(nearby_view_sort);
}
- LLMenuGL* friend_view_sort = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_people_friends_view_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ LLToggleableMenu* friend_view_sort = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_friends_view_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
if(friend_view_sort)
{
mFriendsViewSortMenuHandle = friend_view_sort->getHandle();
mFriendsGearButton->setMenu(friend_view_sort);
}
- LLMenuGL* group_view_sort = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_people_groups_view_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ LLToggleableMenu* group_view_sort = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_groups_view_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
if(group_view_sort)
{
mGroupsViewSortMenuHandle = group_view_sort->getHandle();
mGroupsGearButton->setMenu(group_view_sort);
}
- LLMenuGL* recent_view_sort = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_people_recent_view_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ LLToggleableMenu* recent_view_sort = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_recent_view_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
if(recent_view_sort)
{
mRecentViewSortMenuHandle = recent_view_sort->getHandle();
diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp
index 766f93e0a5..fff8ccb912 100644
--- a/indra/newview/llpanelteleporthistory.cpp
+++ b/indra/newview/llpanelteleporthistory.cpp
@@ -41,6 +41,7 @@
#include "llflatlistview.h"
#include "llnotificationsutil.h"
#include "lltextbox.h"
+#include "lltoggleablemenu.h"
#include "llviewermenu.h"
#include "lllandmarkactions.h"
#include "llclipboard.h"
@@ -450,7 +451,7 @@ BOOL LLTeleportHistoryPanel::postBuild()
mMenuGearButton = getChild<LLMenuButton>("gear_btn");
- LLMenuGL* gear_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_teleport_history_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());;
+ LLToggleableMenu* gear_menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_teleport_history_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());;
if(gear_menu)
{
mGearMenuHandle = gear_menu->getHandle();
diff --git a/indra/newview/llpanelwearing.cpp b/indra/newview/llpanelwearing.cpp
index 3b3d0cdce5..911a9e5dda 100644
--- a/indra/newview/llpanelwearing.cpp
+++ b/indra/newview/llpanelwearing.cpp
@@ -28,6 +28,8 @@
#include "llpanelwearing.h"
+#include "lltoggleablemenu.h"
+
#include "llappearancemgr.h"
#include "llinventoryfunctions.h"
#include "llinventorymodel.h"
@@ -59,12 +61,12 @@ public:
enable_registrar.add("Gear.OnEnable", boost::bind(&LLPanelWearing::isActionEnabled, mPanelWearing, _2));
- mMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(
+ mMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(
"menu_wearing_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
llassert(mMenu);
}
- LLMenuGL* getMenu() { return mMenu; }
+ LLToggleableMenu* getMenu() { return mMenu; }
private:
@@ -79,8 +81,8 @@ private:
}
}
- LLMenuGL* mMenu;
- LLPanelWearing* mPanelWearing;
+ LLToggleableMenu* mMenu;
+ LLPanelWearing* mPanelWearing;
};
//////////////////////////////////////////////////////////////////////////
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index ccf3df827d..68935d536b 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -4160,6 +4160,11 @@ class LLObjectEnableReturn : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
+ if (LLSelectMgr::getInstance()->getSelection()->isEmpty())
+ {
+ // Do not enable if nothing selected
+ return false;
+ }
#ifdef HACKED_GODLIKE_VIEWER
bool new_value = true;
#else
diff --git a/indra/newview/skins/default/xui/da/strings.xml b/indra/newview/skins/default/xui/da/strings.xml
index 9f4119e73b..afd933c7fa 100644
--- a/indra/newview/skins/default/xui/da/strings.xml
+++ b/indra/newview/skins/default/xui/da/strings.xml
@@ -774,7 +774,7 @@
<string name="xml_file">
XML Fil
</string>
- <string name="dot_raw_file">
+ <string name="raw_file">
RAW Fil
</string>
<string name="compressed_image_files">
diff --git a/indra/newview/skins/default/xui/de/strings.xml b/indra/newview/skins/default/xui/de/strings.xml
index ae2991df45..afcb68f537 100644
--- a/indra/newview/skins/default/xui/de/strings.xml
+++ b/indra/newview/skins/default/xui/de/strings.xml
@@ -798,7 +798,7 @@
<string name="xml_file">
XML-Datei
</string>
- <string name="dot_raw_file">
+ <string name="raw_file">
RAW-Datei
</string>
<string name="compressed_image_files">
diff --git a/indra/newview/skins/default/xui/en/menu_add_wearable_gear.xml b/indra/newview/skins/default/xui/en/menu_add_wearable_gear.xml
index 1925d3396f..5033ea9546 100644
--- a/indra/newview/skins/default/xui/en/menu_add_wearable_gear.xml
+++ b/indra/newview/skins/default/xui/en/menu_add_wearable_gear.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<menu
+<toggleable_menu
layout="topleft"
name="Add Wearable Gear Menu">
<menu_item_check
@@ -38,4 +38,4 @@
function="AddWearable.Gear.Visible"
parameter="by_type" />
</menu_item_check>
-</menu>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_cof_gear.xml b/indra/newview/skins/default/xui/en/menu_cof_gear.xml
index c2a11a64ec..a6e9a40e31 100644
--- a/indra/newview/skins/default/xui/en/menu_cof_gear.xml
+++ b/indra/newview/skins/default/xui/en/menu_cof_gear.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<menu
+<toggleable_menu
layout="topleft"
name="Gear COF">
<menu
@@ -10,4 +10,4 @@
label="New Body Parts"
layout="topleft"
name="COF.Geear.New_Body_Parts" />
-</menu>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_gesture_gear.xml b/indra/newview/skins/default/xui/en/menu_gesture_gear.xml
index 649f0edff7..b08d21e8f4 100644
--- a/indra/newview/skins/default/xui/en/menu_gesture_gear.xml
+++ b/indra/newview/skins/default/xui/en/menu_gesture_gear.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<menu
+<toggleable_menu
layout="topleft"
mouse_opaque="false"
name="menu_gesture_gear"
@@ -62,4 +62,4 @@
function="Gesture.EnableAction"
parameter="edit_gesture" />
</menu_item_call>
-</menu>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml b/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml
index 334decdf58..58d58a6ca9 100644
--- a/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml
+++ b/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<menu
+<toggleable_menu
create_jump_keys="true"
layout="topleft"
mouse_opaque="false"
@@ -124,4 +124,4 @@
<menu_item_call.on_click
function="InspectAvatar.Share"/>
</menu_item_call>
-</menu>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml b/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml
index 76f68c6d4b..f818ebe2d7 100644
--- a/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml
+++ b/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<menu
+<toggleable_menu
create_jump_keys="true"
layout="topleft"
mouse_opaque="false"
@@ -136,4 +136,4 @@
<menu_item_call.on_click
function="InspectObject.MoreInfo"/>
</menu_item_call>
-</menu>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml b/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml
index 30c2cde552..50ad3f834e 100644
--- a/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml
+++ b/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<menu
+<toggleable_menu
create_jump_keys="true"
layout="topleft"
mouse_opaque="false"
@@ -63,4 +63,4 @@
<menu_item_call.on_visible
function="IsGodCustomerService"/>
</menu_item_call>
-</menu>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml b/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml
index c394700081..679d5bc82e 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<menu
+<toggleable_menu
bottom="806"
layout="topleft"
left="0"
@@ -125,4 +125,4 @@
function="Inventory.GearDefault.Custom.Action"
parameter="empty_trash" />
</menu_item_call>
-</menu>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_outfit_gear.xml b/indra/newview/skins/default/xui/en/menu_outfit_gear.xml
index 732b8a788d..5fc25b8f0f 100644
--- a/indra/newview/skins/default/xui/en/menu_outfit_gear.xml
+++ b/indra/newview/skins/default/xui/en/menu_outfit_gear.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<menu
+<toggleable_menu
layout="topleft"
visible="false"
name="Gear Outfit">
@@ -212,4 +212,4 @@
function="Gear.OnVisible"
parameter="delete" />
</menu_item_call>
-</menu>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml
index 22796f7b68..29eeb93ac1 100644
--- a/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml
+++ b/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<menu name="menu_group_plus"
+<toggleable_menu
+ name="menu_group_plus"
left="0" bottom="0" visible="false"
mouse_opaque="false">
<menu_item_check
@@ -43,4 +44,4 @@
<menu_item_call name="show_blocked_list" label="Show Blocked Residents &amp; Objects">
<menu_item_call.on_click function="SideTray.ShowPanel" parameter="panel_block_list_sidetray" />
</menu_item_call>
-</menu>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml
index 2efb204ffb..c710fe3b9b 100644
--- a/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml
+++ b/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<menu name="menu_group_plus"
+<toggleable_menu
+ name="menu_group_plus"
left="0" bottom="0" visible="false"
mouse_opaque="false">
<menu_item_check
@@ -22,4 +23,4 @@
<menu_item_call.on_enable
function="People.Group.Minus.Enable"/>
</menu_item_call>
-</menu>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml
index 69b3831738..f9db64b524 100644
--- a/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml
+++ b/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<menu name="menu_group_plus"
+<toggleable_menu
+ name="menu_group_plus"
left="0" bottom="0" visible="false"
mouse_opaque="false">
<menu_item_check
@@ -45,4 +46,4 @@
<menu_item_call name="show_blocked_list" label="Show Blocked Residents &amp; Objects">
<menu_item_call.on_click function="SideTray.ShowPanel" userdata="panel_block_list_sidetray" />
</menu_item_call>
-</menu>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml
index 5c9555db92..0634e3bd3b 100644
--- a/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml
+++ b/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<menu name="menu_group_plus"
+<toggleable_menu
+ name="menu_group_plus"
left="0" bottom="0" visible="false"
mouse_opaque="false">
<menu_item_check
@@ -35,4 +36,4 @@
<menu_item_call name="show_blocked_list" label="Show Blocked Residents &amp; Objects">
<menu_item_call.on_click function="SideTray.ShowPanel" userdata="panel_block_list_sidetray" />
</menu_item_call>
-</menu>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml b/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml
index 77cc3910fd..6f46165883 100644
--- a/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml
+++ b/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<menu
+<toggleable_menu
bottom="806"
layout="topleft"
left="0"
@@ -145,4 +145,4 @@
function="Places.LandmarksGear.Folding.Action"
parameter="sort_by_date" />
</menu_item_check>
-</menu>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml b/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml
index 4b8bc8132f..121e7cc07a 100644
--- a/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml
+++ b/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<menu
+<toggleable_menu
bottom="806"
layout="topleft"
left="0"
@@ -174,4 +174,4 @@
function="Places.LandmarksGear.Enable"
parameter="create_pick" />
</menu_item_call>
-</menu>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_teleport_history_gear.xml b/indra/newview/skins/default/xui/en/menu_teleport_history_gear.xml
index 134b331514..bc7d4fe33b 100644
--- a/indra/newview/skins/default/xui/en/menu_teleport_history_gear.xml
+++ b/indra/newview/skins/default/xui/en/menu_teleport_history_gear.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<menu
+<toggleable_menu
name="Teleport History Gear Context Menu"
left="0"
bottom="0"
@@ -33,4 +33,4 @@
<menu_item_call.on_click
function="TeleportHistory.ClearTeleportHistory" />
</menu_item_call>
-</menu>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_wearing_gear.xml b/indra/newview/skins/default/xui/en/menu_wearing_gear.xml
index 84ab16c709..0ac2c14253 100644
--- a/indra/newview/skins/default/xui/en/menu_wearing_gear.xml
+++ b/indra/newview/skins/default/xui/en/menu_wearing_gear.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<menu
+<toggleable_menu
layout="topleft"
visible="false"
name="Gear Wearing">
@@ -20,4 +20,4 @@
function="Gear.OnEnable"
parameter="take_off" />
</menu_item_call>
-</menu>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index bee0e4fde6..403d976350 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -338,7 +338,7 @@
<string name="avi_movie_file">AVI Movie File</string>
<string name="xaf_animation_file">XAF Anim File</string>
<string name="xml_file">XML File</string>
- <string name="dot_raw_file">RAW File</string>
+ <string name="raw_file">RAW File</string>
<string name="compressed_image_files">Compressed Images</string>
<string name="load_files">Load Files</string>
<string name="choose_the_directory">Choose Directory</string>
diff --git a/indra/newview/skins/default/xui/es/strings.xml b/indra/newview/skins/default/xui/es/strings.xml
index ac12b700ee..5fa3d54de2 100644
--- a/indra/newview/skins/default/xui/es/strings.xml
+++ b/indra/newview/skins/default/xui/es/strings.xml
@@ -777,7 +777,7 @@
<string name="xml_file">
Archivo XML
</string>
- <string name="dot_raw_file">
+ <string name="raw_file">
Archivo RAW
</string>
<string name="compressed_image_files">
diff --git a/indra/newview/skins/default/xui/fr/strings.xml b/indra/newview/skins/default/xui/fr/strings.xml
index a7a766f6a6..af70048106 100644
--- a/indra/newview/skins/default/xui/fr/strings.xml
+++ b/indra/newview/skins/default/xui/fr/strings.xml
@@ -798,7 +798,7 @@
<string name="xml_file">
Fichier XML
</string>
- <string name="dot_raw_file">
+ <string name="raw_file">
Fichier RAW
</string>
<string name="compressed_image_files">
diff --git a/indra/newview/skins/default/xui/it/strings.xml b/indra/newview/skins/default/xui/it/strings.xml
index 4fc0d19199..9dbfc2b79c 100644
--- a/indra/newview/skins/default/xui/it/strings.xml
+++ b/indra/newview/skins/default/xui/it/strings.xml
@@ -783,7 +783,7 @@
<string name="xml_file">
File XML
</string>
- <string name="dot_raw_file">
+ <string name="raw_file">
File RAW
</string>
<string name="compressed_image_files">
diff --git a/indra/newview/skins/default/xui/ja/strings.xml b/indra/newview/skins/default/xui/ja/strings.xml
index 072ae6c630..92bbedaee5 100644
--- a/indra/newview/skins/default/xui/ja/strings.xml
+++ b/indra/newview/skins/default/xui/ja/strings.xml
@@ -798,7 +798,7 @@
<string name="xml_file">
XML ファイル
</string>
- <string name="dot_raw_file">
+ <string name="raw_file">
RAW ファイル
</string>
<string name="compressed_image_files">
diff --git a/indra/newview/skins/default/xui/nl/notifications.xml b/indra/newview/skins/default/xui/nl/notifications.xml
index a282c70364..b4b56a035f 100644
--- a/indra/newview/skins/default/xui/nl/notifications.xml
+++ b/indra/newview/skins/default/xui/nl/notifications.xml
@@ -2409,10 +2409,10 @@ Wilt u de [SECOND_LIFE] website bezoeken om dit in te stellen?
Onderwerp: [SUBJECT], Bericht: [MESSAGE]
</notification>
<notification name="FriendOnline">
- [FIRST] [LAST] is Online
+ [NAME] is Online
</notification>
<notification name="FriendOffline">
- [FIRST] [LAST] is Offline
+ [NAME] is Offline
</notification>
<notification name="AddSelfFriend">
U kunt uzelf niet als vriend toevoegen.
@@ -2574,7 +2574,7 @@ Indien u streaming media wilt zien op percelen die dit ondersteunen, dient u naa
De objecten die uw eigendom zijn op het geselecteerde perceel zijn geretourneerd naar uw inventaris.
</notification>
<notification name="OtherObjectsReturned">
- De objecten op het geselecteerde perceel dat het eigendom is van [FIRST] [LAST], zijn geretourneerd naar zijn of haar inventaris.
+ De objecten op het geselecteerde perceel dat het eigendom is van [NAME], zijn geretourneerd naar zijn of haar inventaris.
</notification>
<notification name="OtherObjectsReturned2">
De objecten op het geselecteerde perceel dat het eigendom is van inwoner &apos;[NAME]&apos;, zijn geretourneerd naar hun eigenaar.
@@ -2701,7 +2701,7 @@ Probeer het alstublieft opnieuw over enkele ogenblikken.
Geen geldig perceel kon gevonden worden.
</notification>
<notification name="ObjectGiveItem">
- Een object genaamd [OBJECTFROMNAME], eigendom van [FIRST] [LAST], heeft u een [OBJECTTYPE] genaamd [OBJECTNAME] gegeven.
+ Een object genaamd &lt;nolink&gt;[OBJECTFROMNAME]&lt;/nolink&gt;, eigendom van [NAME_SLURL], heeft u een [OBJECTTYPE] genaamd [ITEM_SLURL] gegeven.
<form name="form">
<button name="Keep" text="Behouden"/>
<button name="Discard" text="Afwijzen"/>
@@ -2840,7 +2840,7 @@ Dit verzoek inwilligen?
</form>
</notification>
<notification name="ScriptDialog">
- [FIRST] [LAST]&apos;s &apos;[TITLE]&apos;
+ [NAME]&apos;s &apos;&lt;nolink&gt;[TITLE]&lt;/nolink&gt;&apos;
[MESSAGE]
<form name="form">
<button name="Ignore" text="Negeren"/>
@@ -2941,13 +2941,13 @@ Klik Accepteren om deel te nemen aan dit gesprek of Afwijzen om de uitnodiging a
</form>
</notification>
<notification name="AutoUnmuteByIM">
- Er is een instant message naar [FIRST] [LAST] gestuurd, waardoor deze automatisch van de negeerlijst is gehaald.
+ Er is een instant message naar [NAME] gestuurd, waardoor deze automatisch van de negeerlijst is gehaald.
</notification>
<notification name="AutoUnmuteByMoney">
- Er is geld gegeven aan [FIRST] [LAST], waardoor deze automatisch van de negeerlijst is gehaald.
+ Er is geld gegeven aan [NAME], waardoor deze automatisch van de negeerlijst is gehaald.
</notification>
<notification name="AutoUnmuteByInventory">
- Er is inventaris aangeboden aan [FIRST] [LAST], waardoor deze automatisch van de negeerlijst is gehaald.
+ Er is inventaris aangeboden aan [NAME], waardoor deze automatisch van de negeerlijst is gehaald.
</notification>
<notification name="VoiceInviteGroup">
[NAME] doet nu mee met een Voice chat gesprek binnen de groep [GROUP].
diff --git a/indra/newview/skins/default/xui/nl/strings.xml b/indra/newview/skins/default/xui/nl/strings.xml
index 1ee26c3f24..844945913f 100644
--- a/indra/newview/skins/default/xui/nl/strings.xml
+++ b/indra/newview/skins/default/xui/nl/strings.xml
@@ -665,7 +665,7 @@
<string name="xml_file">
XML bestand
</string>
- <string name="dot_raw_file">
+ <string name="raw_file">
RAW bestand
</string>
<string name="compressed_image_files">
diff --git a/indra/newview/skins/default/xui/pl/strings.xml b/indra/newview/skins/default/xui/pl/strings.xml
index c9fe22f3c8..e355bdbb96 100644
--- a/indra/newview/skins/default/xui/pl/strings.xml
+++ b/indra/newview/skins/default/xui/pl/strings.xml
@@ -774,7 +774,7 @@
<string name="xml_file">
Plik XML
</string>
- <string name="dot_raw_file">
+ <string name="raw_file">
Plik RAW
</string>
<string name="compressed_image_files">
diff --git a/indra/newview/skins/default/xui/pt/strings.xml b/indra/newview/skins/default/xui/pt/strings.xml
index 2247b0a76b..800ad479fc 100644
--- a/indra/newview/skins/default/xui/pt/strings.xml
+++ b/indra/newview/skins/default/xui/pt/strings.xml
@@ -777,7 +777,7 @@
<string name="xml_file">
Arquivo XML
</string>
- <string name="dot_raw_file">
+ <string name="raw_file">
Arquivo RAW
</string>
<string name="compressed_image_files">