diff options
Diffstat (limited to 'indra/newview')
50 files changed, 457 insertions, 185 deletions
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index dfab0453a0..23b6edc321 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -12189,5 +12189,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/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/llinventoryicon.cpp b/indra/newview/llinventoryicon.cpp index 7216d61e7f..3f4f33e88d 100644 --- a/indra/newview/llinventoryicon.cpp +++ b/indra/newview/llinventoryicon.cpp @@ -50,7 +50,7 @@ public: LLIconDictionary::LLIconDictionary() { addEntry(LLInventoryIcon::ICONNAME_TEXTURE, new IconEntry("Inv_Texture")); - addEntry(LLInventoryIcon::ICONNAME_SOUND, new IconEntry("Inv_Texture")); + addEntry(LLInventoryIcon::ICONNAME_SOUND, new IconEntry("Inv_Sound")); addEntry(LLInventoryIcon::ICONNAME_CALLINGCARD_ONLINE, new IconEntry("Inv_CallingCard")); addEntry(LLInventoryIcon::ICONNAME_CALLINGCARD_OFFLINE, new IconEntry("Inv_CallingCard")); addEntry(LLInventoryIcon::ICONNAME_LANDMARK, new IconEntry("Inv_Landmark")); @@ -83,7 +83,7 @@ LLIconDictionary::LLIconDictionary() addEntry(LLInventoryIcon::ICONNAME_GESTURE, new IconEntry("Inv_Gesture")); addEntry(LLInventoryIcon::ICONNAME_LINKITEM, new IconEntry("Inv_LinkItem")); - addEntry(LLInventoryIcon::ICONNAME_LINKFOLDER, new IconEntry("Inv_LinkItem")); + addEntry(LLInventoryIcon::ICONNAME_LINKFOLDER, new IconEntry("Inv_LinkFolder")); addEntry(LLInventoryIcon::ICONNAME_INVALID, new IconEntry("Inv_Invalid")); 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 3eaa8d53a4..ff9abb6b72 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -4170,6 +4170,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 & 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 & 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 & 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 '[NAME]', 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 <nolink>[OBJECTFROMNAME]</nolink>, 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]'s '[TITLE]' + [NAME]'s '<nolink>[TITLE]</nolink>' [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"> |