diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 409ffa4f1..22625a260 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -66,12 +66,12 @@ set(llui_SOURCE_FILES lltextbox.cpp lltexteditor.cpp lltextparser.cpp + lltrans.cpp llui.cpp lluictrl.cpp lluictrlfactory.cpp lluiimage.cpp lluistring.cpp - lluitrans.cpp llundo.cpp llviewborder.cpp llview.cpp @@ -108,6 +108,7 @@ set(llui_HEADER_FILES llnotificationptr.h llnotifications.h llnotificationsutil.h + llnotificationtemplate.h llpanel.h llprogressbar.h llradiogroup.h @@ -128,6 +129,7 @@ set(llui_HEADER_FILES lltextbox.h lltexteditor.h lltextparser.h + lltrans.h lluiconstants.h lluictrlfactory.h lluictrl.h @@ -135,7 +137,6 @@ set(llui_HEADER_FILES llui.h lluiimage.h lluistring.h - lluitrans.h lluixmltags.h llundo.h llviewborder.h diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 15868333c..de6d988b2 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -59,8 +59,7 @@ #include "llresmgr.h" #include "llui.h" -#include "lluitrans.h" - +#include "lltrans.h" #include "llstl.h" #include "v2math.h" @@ -271,24 +270,24 @@ void LLMenuItemGL::appendAcceleratorString( std::string& st ) const { if ( mAcceleratorMask & MASK_MAC_CONTROL ) { - st.append( LLUITrans::getString("accel-mac-control") ); + st.append( LLTrans::getString("accel-mac-control") ); } else { - st.append( LLUITrans::getString("accel-mac-command") ); // Symbol would be "\xE2\x8C\x98" + st.append( LLTrans::getString("accel-mac-command") ); // Symbol would be "\xE2\x8C\x98" } } if( mAcceleratorMask & MASK_ALT ) - st.append( LLUITrans::getString("accel-mac-option") ); // Symbol would be "\xE2\x8C\xA5" + st.append( LLTrans::getString("accel-mac-option") ); // Symbol would be "\xE2\x8C\xA5" if( mAcceleratorMask & MASK_SHIFT ) - st.append( LLUITrans::getString("accel-mac-shift") ); // Symbol would be "\xE2\x8C\xA7" + st.append( LLTrans::getString("accel-mac-shift") ); // Symbol would be "\xE2\x8C\xA7" #else if( mAcceleratorMask & MASK_CONTROL ) - st.append( LLUITrans::getString("accel-win-control") ); + st.append( LLTrans::getString("accel-win-control") ); if( mAcceleratorMask & MASK_ALT ) - st.append( LLUITrans::getString("accel-win-alt") ); + st.append( LLTrans::getString("accel-win-alt") ); if( mAcceleratorMask & MASK_SHIFT ) - st.append( LLUITrans::getString("accel-win-shift") ); + st.append( LLTrans::getString("accel-win-shift") ); #endif std::string keystr = LLKeyboard::stringFromKey( mAcceleratorKey ); diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index fa4a27564..dc0cf9c87 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -31,9 +31,13 @@ */ #include "linden_common.h" + +#include "llnotifications.h" +#include "llnotificationtemplate.h" #include "lluictrlfactory.h" #include "lldir.h" #include "llsdserialize.h" +#include "lltrans.h" #include "llnotifications.h" @@ -164,12 +168,7 @@ bool filterIgnoredNotifications(LLNotificationPtr notification) { LLNotificationFormPtr form = notification->getForm(); // Check to see if the user wants to ignore this alert - if (form->getIgnoreType() != LLNotificationForm::IGNORE_NO) - { - return LLUI::sConfigGroup->getWarning(notification->getName()); - } - - return true; + return !notification->getForm()->getIgnored(); } bool handleIgnoredNotification(const LLSD& payload) @@ -219,7 +218,8 @@ LLNotificationForm::LLNotificationForm() LLNotificationForm::LLNotificationForm(const std::string& name, const LLXMLNodePtr xml_node) : mFormData(LLSD::emptyArray()), - mIgnore(IGNORE_NO) + mIgnore(IGNORE_NO), + mInvertSetting(false) { if (!xml_node->hasName("form")) { @@ -248,7 +248,7 @@ LLNotificationForm::LLNotificationForm(const std::string& name, const LLXMLNodeP LLUI::sIgnoresGroup->declareLLSD(std::string("Default") + name, "", std::string("Default response for notification " + name)); } child->getAttributeString("text", mIgnoreMsg); - LLUI::sIgnoresGroup->addWarning(name); + mIgnoreSetting = LLUI::sIgnoresGroup->addWarning(name); } else { @@ -344,13 +344,13 @@ void LLNotificationForm::formatElements(const LLSD& substitutions) if ((*it).has("text")) { std::string text = (*it)["text"].asString(); - text = LLNotification::format(text, substitutions); + LLStringUtil::format(text, substitutions); (*it)["text"] = text; } if ((*it)["type"].asString() == "text" && (*it).has("value")) { std::string value = (*it)["value"].asString(); - value = LLNotification::format(value, substitutions); + LLStringUtil::format(value, substitutions); (*it)["value"] = value; } } @@ -367,6 +367,33 @@ std::string LLNotificationForm::getDefaultOption() return ""; } +LLControlVariablePtr LLNotificationForm::getIgnoreSetting() +{ + return mIgnoreSetting; +} + +bool LLNotificationForm::getIgnored() +{ + bool show = true; + if (mIgnore != LLNotificationForm::IGNORE_NO + && mIgnoreSetting) + { + show = mIgnoreSetting->getValue().asBoolean(); + if (mInvertSetting) show = !show; + } + + return !show; +} + +void LLNotificationForm::setIgnored(bool ignored) +{ + if (mIgnoreSetting) + { + if (mInvertSetting) ignored = !ignored; + mIgnoreSetting->setValue(!ignored); + } +} + LLNotificationTemplate::LLNotificationTemplate() : mExpireSeconds(0), mExpireOption(-1), @@ -417,6 +444,7 @@ LLNotification::LLNotification(const LLSD& sd) : LLSD LLNotification::asLLSD() { LLSD output; + output["id"] = mId; output["name"] = mTemplatep->mName; output["form"] = getForm()->asLLSD(); output["substitutions"] = mSubstitutions; @@ -545,7 +573,7 @@ void LLNotification::respond(const LLSD& response) if (mForm->getIgnoreType() != LLNotificationForm::IGNORE_NO) { - LLUI::sIgnoresGroup->setWarning(getName(), !mIgnored); + mForm->setIgnored(mIgnored); if (mIgnored && mForm->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE) { LLUI::sIgnoresGroup->setLLSD("Default" + getName(), response); @@ -555,6 +583,36 @@ void LLNotification::respond(const LLSD& response) update(); } +const std::string& LLNotification::getName() const +{ + return mTemplatep->mName; +} + +const std::string& LLNotification::getIcon() const +{ + return mTemplatep->mIcon; +} + + +bool LLNotification::isPersistent() const +{ + return mTemplatep->mPersist; +} +std::string LLNotification::getType() const +{ + return (mTemplatep ? mTemplatep->mType : ""); +} + +S32 LLNotification::getURLOption() const +{ + return (mTemplatep ? mTemplatep->mURLOption : -1); +} +bool LLNotification::hasUniquenessConstraints() const +{ + return (mTemplatep ? mTemplatep->mUnique : false); +} + + void LLNotification::setIgnored(bool ignore) { mIgnored = ignore; @@ -569,21 +627,6 @@ void LLNotification::setResponseFunctor(std::string const &responseFunctorName) mTemporaryResponder = false; } -bool LLNotification::payloadContainsAll(const std::vector& required_fields) const -{ - for(std::vector::const_iterator required_fields_it = required_fields.begin(); - required_fields_it != required_fields.end(); - required_fields_it++) - { - std::string required_field_name = *required_fields_it; - if( ! getPayload().has(required_field_name)) - { - return false; // a required field was not found - } - } - return true; // all required fields were found -} - bool LLNotification::isEquivalentTo(LLNotificationPtr that) const { if (this->mTemplatep->mName != that->mTemplatep->mName) @@ -592,11 +635,28 @@ bool LLNotification::isEquivalentTo(LLNotificationPtr that) const } if (this->mTemplatep->mUnique) { + const LLSD& these_substitutions = this->getSubstitutions(); + const LLSD& those_substitutions = that->getSubstitutions(); + const LLSD& this_payload = this->getPayload(); + const LLSD& that_payload = that->getPayload(); + // highlander bit sez there can only be one of these - return - this->payloadContainsAll(that->mTemplatep->mUniqueContext) && - that->payloadContainsAll(this->mTemplatep->mUniqueContext); + for (std::vector::const_iterator it = mTemplatep->mUniqueContext.begin(), end_it = mTemplatep->mUniqueContext.end(); + it != end_it; + ++it) + { + // if templates differ in either substitution strings or payload with the given field name + // then they are considered inequivalent + // use of get() avoids converting the LLSD value to a map as the [] operator would + if (these_substitutions.get(*it).asString() != those_substitutions.get(*it).asString() + || this_payload.get(*it).asString() != that_payload.get(*it).asString()) + { + return false; + } + } + return true; } + return false; } @@ -605,23 +665,15 @@ void LLNotification::init(const std::string& template_name, const LLSD& form_ele mTemplatep = LLNotifications::instance().getTemplate(template_name); if (!mTemplatep) return; - // add default substitutions - // TODO: change this to read from the translatable strings file! - if (gHippoGridManager->getConnectedGrid()->isSecondLife()) { - mSubstitutions["[SECOND_LIFE]"] = "Second Life"; + const LLStringUtil::format_map_t& default_args = LLTrans::getDefaultArgs(); + for (LLStringUtil::format_map_t::const_iterator iter = default_args.begin(); + iter != default_args.end(); ++iter) + { + mSubstitutions[iter->first] = iter->second; } - else { - mSubstitutions["[SECOND_LIFE]"] = gHippoGridManager->getConnectedGrid()->getGridName(); - } - mSubstitutions["[VIEWER_NAME]"] = LLNotifications::instance().getGlobalString("VIEWER_NAME"); - mSubstitutions["[VIEWER_SITE]"] = LLNotifications::instance().getGlobalString("VIEWER_SITE"); - - mSubstitutions["[GRID_NAME]"] = gHippoGridManager->getConnectedGrid()->getGridName(); - mSubstitutions["[GRID_SITE]"] = gHippoGridManager->getConnectedGrid()->getWebSite(); - mSubstitutions["[CURRENCY]"] = gHippoGridManager->getConnectedGrid()->getCurrencySymbol(); - mSubstitutions["_URL"] = getURL(); mSubstitutions["_NAME"] = template_name; + // TODO: something like this so that a missing alert is sensible: //mSubstitutions["_ARGS"] = get_all_arguments_as_text(mSubstitutions); @@ -631,6 +683,8 @@ void LLNotification::init(const std::string& template_name, const LLSD& form_ele // apply substitution to form labels mForm->formatElements(mSubstitutions); + mIgnored = mForm->getIgnored(); + LLDate rightnow = LLDate::now(); if (mTemplatep->mExpireSeconds) { @@ -653,63 +707,6 @@ std::string LLNotification::summarize() const return s; } -//static -std::string LLNotification::format(const std::string& s, const LLSD& substitutions) -{ - if (!substitutions.isMap()) - { - return s; - } - - std::ostringstream output; - // match strings like [NAME] - const boost::regex key("\\[([0-9_A-Z]+)]"); - - std::string::const_iterator start = s.begin(); - std::string::const_iterator end = s.end(); - boost::smatch match; - - while (boost::regex_search(start, end, match, key, boost::match_default)) - { - bool found_replacement = false; - std::string replacement; - - // see if we have a replacement for the bracketed string (without the brackets) - // test first using has() because if we just look up with operator[] we get back an - // empty string even if the value is missing. We want to distinguish between - // missing replacements and deliberately empty replacement strings. - if (substitutions.has(std::string(match[1].first, match[1].second))) - { - replacement = substitutions[std::string(match[1].first, match[1].second)].asString(); - found_replacement = true; - } - // if not, see if there's one WITH brackets - else if (substitutions.has(std::string(match[0].first, match[0].second))) - { - replacement = substitutions[std::string(match[0].first, match[0].second)].asString(); - found_replacement = true; - } - - if (found_replacement) - { - // found a replacement - // "hello world" is output - output << std::string(start, match[0].first) << replacement; - } - else - { - // we had no replacement, so leave the string we searched for so that it gets noticed by QA - // "hello [NAME_NOT_FOUND]" is output - output << std::string(start, match[0].second); - } - - // update search position - start = match[0].second; - } - // send the remainder of the string (with no further matches for bracketed names) - output << std::string(start, end); - return output.str(); -} std::string LLNotification::getMessage() const { @@ -718,15 +715,30 @@ std::string LLNotification::getMessage() const // cache it in the notification if (!mTemplatep) return std::string(); - return format(mTemplatep->mMessage, mSubstitutions); + + std::string message = mTemplatep->mMessage; + LLStringUtil::format(message, mSubstitutions); + return message; } std::string LLNotification::getLabel() const { - return (mTemplatep ? format(mTemplatep->mLabel, mSubstitutions) : ""); + if(!mTemplatep) + return std::string(); + + std::string label = mTemplatep->mLabel; + LLStringUtil::format(label, mSubstitutions); + return label; } - +std::string LLNotification::getURL() const +{ + if (!mTemplatep) + return std::string(); + std::string url = mTemplatep->mURL; + LLStringUtil::format(url, mSubstitutions); + return (mTemplatep ? url : ""); +} // ========================================================= // LLNotificationChannel implementation diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 999f664a0..c513b82f9 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -217,6 +217,9 @@ public: // appends form elements from another form serialized as LLSD void append(const LLSD& sub_form); std::string getDefaultOption(); + LLPointer getIgnoreSetting(); + bool getIgnored(); + void setIgnored(bool ignored); EIgnoreType getIgnoreType() { return mIgnore; } std::string getIgnoreMessage() { return mIgnoreMsg; } @@ -224,80 +227,15 @@ public: private: LLSD mFormData; EIgnoreType mIgnore; - std::string mIgnoreMsg; + std::string mIgnoreMsg; + LLPointer mIgnoreSetting; + bool mInvertSetting; }; typedef boost::shared_ptr LLNotificationFormPtr; -// This is the class of object read from the XML file (notifications.xml, -// from the appropriate local language directory). -struct LLNotificationTemplate -{ - LLNotificationTemplate(); - // the name of the notification -- the key used to identify it - // Ideally, the key should follow variable naming rules - // (no spaces or punctuation). - std::string mName; - // The type of the notification - // used to control which queue it's stored in - std::string mType; - // The text used to display the notification. Replaceable parameters - // are enclosed in square brackets like this []. - std::string mMessage; - // The label for the notification; used for - // certain classes of notification (those with a window and a window title). - // Also used when a notification pops up underneath the current one. - // Replaceable parameters can be used in the label. - std::string mLabel; - // The name of the icon image. This should include an extension. - std::string mIcon; - // This is the Highlander bit -- "There Can Be Only One" - // An outstanding notification with this bit set - // is updated by an incoming notification with the same name, - // rather than creating a new entry in the queue. - // (used for things like progress indications, or repeating warnings - // like "the grid is going down in N minutes") - bool mUnique; - // if we want to be unique only if a certain part of the payload is constant - // specify the field names for the payload. The notification will only be - // combined if all of the fields named in the context are identical in the - // new and the old notification; otherwise, the notification will be - // duplicated. This is to support suppressing duplicate offers from the same - // sender but still differentiating different offers. Example: Invitation to - // conference chat. - std::vector mUniqueContext; - // If this notification expires automatically, this value will be - // nonzero, and indicates the number of seconds for which the notification - // will be valid (a teleport offer, for example, might be valid for - // 300 seconds). - U32 mExpireSeconds; - // if the offer expires, one of the options is chosen automatically - // based on its "value" parameter. This controls which one. - // If expireSeconds is specified, expireOption should also be specified. - U32 mExpireOption; - // if the notification contains a url, it's stored here (and replaced - // into the message where [_URL] is found) - std::string mURL; - // if there's a URL in the message, this controls which option visits - // that URL. Obsolete this and eliminate the buttons for affected - // messages when we allow clickable URLs in the UI - U32 mURLOption; - // does this notification persist across sessions? if so, it will be - // serialized to disk on first receipt and read on startup - bool mPersist; - // This is the name of the default functor, if present, to be - // used for the notification's callback. It is optional, and used only if - // the notification is constructed without an identified functor. - std::string mDefaultFunctor; - // The form data associated with a given notification (buttons, text boxes, etc) - LLNotificationFormPtr mForm; - // default priority for notifications of this type - ENotificationPriority mPriority; - // UUID of the audio file to be played when this notification arrives - // this is loaded as a name, but looked up to get the UUID upon template load. - // If null, it wasn't specified. - LLUUID mSoundEffect; -}; + +struct LLNotificationTemplate; // we want to keep a map of these by name, and it's best to manage them // with smart pointers @@ -401,21 +339,15 @@ private: // this is just for making it easy to look things up in a set organized by UUID -- DON'T USE IT // for anything real! - LLNotification(LLUUID uuid) : mId(uuid) {} + LLNotification(LLUUID uuid) : mId(uuid), mCancelled(false), mRespondedTo(false), mIgnored(false), mPriority(NOTIFICATION_PRIORITY_UNSPECIFIED), mTemporaryResponder(false) {} void cancel(); - bool payloadContainsAll(const std::vector& required_fields) const; - public: // constructor from a saved notification LLNotification(const LLSD& sd); - // This is a string formatter for substituting into the message directly - // from LLSD without going through the hopefully-to-be-obsoleted LLString - static std::string format(const std::string& text, const LLSD& substitutions); - void setResponseFunctor(std::string const &responseFunctorName); typedef enum e_response_template_type @@ -474,11 +406,12 @@ public: return mIgnored; } - const std::string& getName() const - { - return mTemplatep->mName; - } - + const std::string& getName() const; + + const std::string& getIcon() const; + + bool isPersistent() const; + const LLUUID& id() const { return mId; @@ -499,23 +432,11 @@ public: return mTimestamp; } - std::string getType() const - { - return (mTemplatep ? mTemplatep->mType : ""); - } - + std::string getType() const; std::string getMessage() const; std::string getLabel() const; - - std::string getURL() const - { - return (mTemplatep ? mTemplatep->mURL : ""); - } - - S32 getURLOption() const - { - return (mTemplatep ? mTemplatep->mURLOption : -1); - } + std::string getURL() const; + S32 getURLOption() const; const LLNotificationFormPtr getForm(); @@ -581,7 +502,7 @@ public: std::string summarize() const; - bool hasUniquenessConstraints() const { return (mTemplatep ? mTemplatep->mUnique : false);} + bool hasUniquenessConstraints() const; virtual ~LLNotification() {} }; @@ -650,7 +571,7 @@ namespace LLNotificationComparators struct orderBy { typedef boost::function field_t; - orderBy(field_t field, EDirection = ORDER_INCREASING) : mField(field) {} + orderBy(field_t field, EDirection direction = ORDER_INCREASING) : mField(field), mDirection(direction) {} bool operator()(LLNotificationPtr lhs, LLNotificationPtr rhs) { if (mDirection == ORDER_DECREASING) diff --git a/indra/llui/llnotificationtemplate.h b/indra/llui/llnotificationtemplate.h new file mode 100644 index 000000000..0c434be38 --- /dev/null +++ b/indra/llui/llnotificationtemplate.h @@ -0,0 +1,108 @@ +/** +* @file llnotificationtemplate.h +* @brief Description of notification contents +* @author Q (with assistance from Richard and Coco) +* +* $LicenseInfo:firstyear=2008&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2010, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#ifndef LL_LLNOTIFICATION_TEMPLATE_H +#define LL_LLNOTIFICATION_TEMPLATE_H + +#include "llnotifications.h" + + +typedef boost::shared_ptr LLNotificationFormPtr; + +// This is the class of object read from the XML file (notifications.xml, +// from the appropriate local language directory). +struct LLNotificationTemplate +{ + LLNotificationTemplate(); + // the name of the notification -- the key used to identify it + // Ideally, the key should follow variable naming rules + // (no spaces or punctuation). + std::string mName; + // The type of the notification + // used to control which queue it's stored in + std::string mType; + // The text used to display the notification. Replaceable parameters + // are enclosed in square brackets like this []. + std::string mMessage; + // The label for the notification; used for + // certain classes of notification (those with a window and a window title). + // Also used when a notification pops up underneath the current one. + // Replaceable parameters can be used in the label. + std::string mLabel; + // The name of the icon image. This should include an extension. + std::string mIcon; + // This is the Highlander bit -- "There Can Be Only One" + // An outstanding notification with this bit set + // is updated by an incoming notification with the same name, + // rather than creating a new entry in the queue. + // (used for things like progress indications, or repeating warnings + // like "the grid is going down in N minutes") + bool mUnique; + // if we want to be unique only if a certain part of the payload is constant + // specify the field names for the payload. The notification will only be + // combined if all of the fields named in the context are identical in the + // new and the old notification; otherwise, the notification will be + // duplicated. This is to support suppressing duplicate offers from the same + // sender but still differentiating different offers. Example: Invitation to + // conference chat. + std::vector mUniqueContext; + // If this notification expires automatically, this value will be + // nonzero, and indicates the number of seconds for which the notification + // will be valid (a teleport offer, for example, might be valid for + // 300 seconds). + U32 mExpireSeconds; + // if the offer expires, one of the options is chosen automatically + // based on its "value" parameter. This controls which one. + // If expireSeconds is specified, expireOption should also be specified. + U32 mExpireOption; + // if the notification contains a url, it's stored here (and replaced + // into the message where [_URL] is found) + std::string mURL; + // if there's a URL in the message, this controls which option visits + // that URL. Obsolete this and eliminate the buttons for affected + // messages when we allow clickable URLs in the UI + U32 mURLOption; + // does this notification persist across sessions? if so, it will be + // serialized to disk on first receipt and read on startup + bool mPersist; + // This is the name of the default functor, if present, to be + // used for the notification's callback. It is optional, and used only if + // the notification is constructed without an identified functor. + std::string mDefaultFunctor; + // The form data associated with a given notification (buttons, text boxes, etc) + LLNotificationFormPtr mForm; + // default priority for notifications of this type + ENotificationPriority mPriority; + // UUID of the audio file to be played when this notification arrives + // this is loaded as a name, but looked up to get the UUID upon template load. + // If null, it wasn't specified. + LLUUID mSoundEffect; +}; + + +#endif //LL_LLNOTIFICATION_TEMPLATE_H + diff --git a/indra/newview/lltrans.cpp b/indra/llui/lltrans.cpp similarity index 78% rename from indra/newview/lltrans.cpp rename to indra/llui/lltrans.cpp index 187782d5e..8fb40e5d6 100644 --- a/indra/newview/lltrans.cpp +++ b/indra/llui/lltrans.cpp @@ -31,7 +31,7 @@ */ -#include "llviewerprecompiledheaders.h" +#include "linden_common.h" #include "lltrans.h" #include "llxmlnode.h" #include "lluictrlfactory.h" @@ -41,9 +41,10 @@ #include LLTrans::template_map_t LLTrans::sStringTemplates; +LLStringUtil::format_map_t LLTrans::sDefaultArgs; //static -bool LLTrans::parseStrings(const std::string& xml_filename) +bool LLTrans::parseStrings(const std::string& xml_filename, const std::set& default_args) { LLXMLNodePtr root; BOOL success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root); @@ -54,6 +55,7 @@ bool LLTrans::parseStrings(const std::string& xml_filename) return false; } + sDefaultArgs.clear(); for (LLXMLNode* string = root->getFirstChild(); string != NULL; string = string->getNextSibling()) { @@ -72,19 +74,30 @@ bool LLTrans::parseStrings(const std::string& xml_filename) LLTransTemplate xml_template(string_name, string->getTextContents()); sStringTemplates[xml_template.mName] = xml_template; + + std::set::const_iterator iter = default_args.find(xml_template.mName); + if (iter != default_args.end()) + { + std::string name = *iter; + if (name[0] != '[') + name = llformat("[%s]",name.c_str()); + sDefaultArgs[name] = xml_template.mText; + } } return true; } //static -std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args) +std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::format_map_t& msg_args) { template_map_t::iterator iter = sStringTemplates.find(xml_desc); if (iter != sStringTemplates.end()) { std::string text = iter->second.mText; + LLStringUtil::format_map_t args = sDefaultArgs; + args.insert(msg_args.begin(), msg_args.end()); LLStringUtil::format(text, args); return text; @@ -96,7 +109,11 @@ std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil:: LL_WARNS_ONCE("configuration") << "Missing String in strings.xml: [" << xml_desc << "]" << LL_ENDL; LLNotificationsUtil::add("MissingString", args); - return xml_desc; + return "MissingString("+xml_desc+")"; } } +void LLTrans::setDefaultArg(const std::string& name, const std::string& value) +{ + sDefaultArgs[name] = value; +} diff --git a/indra/newview/lltrans.h b/indra/llui/lltrans.h similarity index 80% rename from indra/newview/lltrans.h rename to indra/llui/lltrans.h index d735fa630..56ed08f3b 100644 --- a/indra/newview/lltrans.h +++ b/indra/llui/lltrans.h @@ -1,6 +1,6 @@ /** - * @file lltrans.h - * @brief LLTrans definition + * @file lluitrans.h + * @brief LLUITrans definition * * $LicenseInfo:firstyear=2000&license=viewergpl$ * @@ -61,9 +61,10 @@ public: /** * @brief Parses the xml file that holds the strings. Used once on startup * @param xml_filename Filename to parse + * @param default_args Set of strings (expected to be in the file) to use as default replacement args, e.g. "SECOND_LIFE" * @returns true if the file was parsed successfully, true if something went wrong */ - static bool parseStrings(const std::string& xml_filename); + static bool parseStrings(const std::string& xml_filename, const std::set& default_args); /** * @brief Returns a translated string @@ -84,10 +85,24 @@ public: return getString(xml_desc, empty); } + // get the default args + static const LLStringUtil::format_map_t& getDefaultArgs() + { + return sDefaultArgs; + } + + static void setDefaultArg(const std::string& name, const std::string& value); + + // insert default args into an arg list + static void getArgs(LLStringUtil::format_map_t& args) + { + args.insert(sDefaultArgs.begin(), sDefaultArgs.end()); + } private: typedef std::map template_map_t; static template_map_t sStringTemplates; + static LLStringUtil::format_map_t sDefaultArgs; }; #endif diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 7fd3015e5..de34a0c8a 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -962,7 +962,9 @@ void gl_rect_2d_checkerboard(const LLRect& parent_screen_rect, const LLRect& rec F32 offs_y = (parent_screen_rect.mBottom + rect.mBottom) / image_height; LLRectf uv_rect(offs_x,offs_y+scale_y,offs_x+scale_x,offs_y); - gl_draw_scaled_image(rect.mLeft,rect.mBottom,rect.getWidth(),rect.getHeight(),checkboard_image->getImage(), UI_VERTEX_COLOR, uv_rect); + LLColor4 color=UI_VERTEX_COLOR; + color.mV[VALPHA] = alpha; + gl_draw_scaled_image(rect.mLeft,rect.mBottom,rect.getWidth(),rect.getHeight(),checkboard_image->getImage(), color, uv_rect); gGL.flush(); } diff --git a/indra/llui/lluitrans.cpp b/indra/llui/lluitrans.cpp deleted file mode 100644 index a60ff370d..000000000 --- a/indra/llui/lluitrans.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/** - * @file lluitrans.cpp - * @brief LLUITrans implementation - * - * $LicenseInfo:firstyear=2000&license=viewergpl$ - * - * Copyright (c) 2000-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - - -#include "linden_common.h" -#include "lluitrans.h" -#include "llxmlnode.h" -#include "lluictrlfactory.h" -#include "llalertdialog.h" -#include "llnotificationsutil.h" - -#include - -LLUITrans::template_map_t LLUITrans::sStringTemplates; - -//static -bool LLUITrans::parseStrings(const std::string& xml_filename) -{ - LLXMLNodePtr root; - BOOL success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root); - - if (!success || root.isNull() || !root->hasName( "strings" )) - { - llerrs << "Problem reading strings: " << xml_filename << llendl; - return false; - } - - for (LLXMLNode* string = root->getFirstChild(); - string != NULL; string = string->getNextSibling()) - { - if (!string->hasName("string")) - { - continue; - } - - std::string string_name; - - if (! string->getAttributeString("name", string_name)) - { - llwarns << "Unable to parse string with no name" << llendl; - continue; - } - - LLUITransTemplate xml_template(string_name, string->getTextContents()); - sStringTemplates[xml_template.mName] = xml_template; - } - - return true; -} - -//static -std::string LLUITrans::getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args) -{ - template_map_t::iterator iter = sStringTemplates.find(xml_desc); - - if (iter != sStringTemplates.end()) - { - std::string text = iter->second.mText; - LLStringUtil::format(text, args); - - return text; - } - else - { - LLSD args; - args["STRING_NAME"] = xml_desc; - LL_WARNS_ONCE("configuration") << "Missing String in strings.xml: [" << xml_desc << "]" << LL_ENDL; - LLNotificationsUtil::add("MissingString", args); - - return xml_desc; - } -} - diff --git a/indra/llui/lluitrans.h b/indra/llui/lluitrans.h deleted file mode 100644 index 32fb46828..000000000 --- a/indra/llui/lluitrans.h +++ /dev/null @@ -1,87 +0,0 @@ -/** - * @file lluitrans.h - * @brief LLUITrans definition - * - * $LicenseInfo:firstyear=2000&license=viewergpl$ - * - * Copyright (c) 2000-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_UI_TRANS_H -#define LL_UI_TRANS_H - -#include - -/** - * @brief String template loaded from strings.xml - */ -class LLUITransTemplate -{ -public: - LLUITransTemplate(const std::string& name = LLStringUtil::null, const std::string& text = LLStringUtil::null) : mName(name), mText(text) {} - - std::string mName; - std::string mText; -}; - -class LLUITrans -{ -public: - LLUITrans(); - - /** - * @brief Parses the xml file that holds the strings. Used once on startup - * @param xml_filename Filename to parse - * @returns true if the file was parsed successfully, true if something went wrong - */ - static bool parseStrings(const std::string& xml_filename); - - /** - * @brief Returns a translated string - * @param xml_desc String's description - * @param args A list of substrings to replace in the string - * @returns Translated string - */ - static std::string getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args); - - /** - * @brief Returns a translated string - * @param xml_desc String's description - * @returns Translated string - */ - static std::string getString(const std::string &xml_desc) - { - LLStringUtil::format_map_t empty; - return getString(xml_desc, empty); - } - - -private: - typedef std::map template_map_t; - static template_map_t sStringTemplates; -}; - -#endif diff --git a/indra/llwindow/llwindowcallbacks.cpp b/indra/llwindow/llwindowcallbacks.cpp index 09689d087..c2705bbf7 100644 --- a/indra/llwindow/llwindowcallbacks.cpp +++ b/indra/llwindow/llwindowcallbacks.cpp @@ -187,3 +187,14 @@ void LLWindowCallbacks::handleResumeWatchdog(LLWindow *window) } +std::string LLWindowCallbacks::translateString(const char* tag) +{ + return std::string(); +} + +//virtual +std::string LLWindowCallbacks::translateString(const char* tag, + const std::map& args) +{ + return std::string(); +} diff --git a/indra/llwindow/llwindowcallbacks.h b/indra/llwindow/llwindowcallbacks.h index 5ba442ed4..6d353c479 100644 --- a/indra/llwindow/llwindowcallbacks.h +++ b/indra/llwindow/llwindowcallbacks.h @@ -84,6 +84,10 @@ public: virtual void handlePauseWatchdog(LLWindow *window); virtual void handleResumeWatchdog(LLWindow *window); + // Look up a localized string, usually for an error message + virtual std::string translateString(const char* tag); + virtual std::string translateString(const char* tag, + const std::map& args); }; diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 86eb5ece9..5263d68c1 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -496,7 +496,8 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, if (!RegisterClass(&wc)) { - OSMessageBox("RegisterClass failed", "Error", OSMB_OK); + OSMessageBox(mCallbacks->translateString("MBRegClassFailed"), + mCallbacks->translateString("MBError"), OSMB_OK); return; } sIsClassRegistered = TRUE; @@ -608,8 +609,11 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, mFullscreenBits = -1; mFullscreenRefresh = -1; - std::string error = llformat("Unable to run fullscreen at %d x %d.\nRunning in window.", width, height); - OSMessageBox(error, "Error", OSMB_OK); + std::map args; + args["[WIDTH]"] = llformat("%d", width); + args["[HEIGHT]"] = llformat ("%d", height); + OSMessageBox(mCallbacks->translateString("MBFullScreenErr", args), + mCallbacks->translateString("MBError"), OSMB_OK); } } @@ -752,7 +756,9 @@ void LLWindowWin32::close() // This causes WM_DESTROY to be sent *immediately* if (!DestroyWindow(mWindowHandle)) { - OSMessageBox("DestroyWindow(mWindowHandle) failed", "Shutdown Error", OSMB_OK); + OSMessageBox(mCallbacks->translateString("MBDestroyWinFailed"), + mCallbacks->translateString("MBShutdownErr"), + OSMB_OK); } mWindowHandle = NULL; @@ -1059,14 +1065,16 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO if (!(mhDC = GetDC(mWindowHandle))) { close(); - OSMessageBox("Can't make GL device context", "Error", OSMB_OK); + OSMessageBox(mCallbacks->translateString("MBDevContextErr"), + mCallbacks->translateString("MBError"), OSMB_OK); return FALSE; } if (!(pixel_format = ChoosePixelFormat(mhDC, &pfd))) { close(); - OSMessageBox("Can't find suitable pixel format", "Error", OSMB_OK); + OSMessageBox(mCallbacks->translateString("MBPixelFmtErr"), + mCallbacks->translateString("MBError"), OSMB_OK); return FALSE; } @@ -1075,57 +1083,48 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO &pfd)) { close(); - OSMessageBox("Can't get pixel format description", "Error", OSMB_OK); + OSMessageBox(mCallbacks->translateString("MBPixelFmtDescErr"), + mCallbacks->translateString("MBError"), OSMB_OK); return FALSE; } if (pfd.cColorBits < 32) { close(); - OSMessageBox( - "Second Life requires True Color (32-bit) to run in a window.\n" - "Please go to Control Panels -> Display -> Settings and\n" - "set the screen to 32-bit color.\n" - "Alternately, if you choose to run fullscreen, Second Life\n" - "will automatically adjust the screen each time it runs.", - "Error", - OSMB_OK); + OSMessageBox(mCallbacks->translateString("MBTrueColorWindow"), + mCallbacks->translateString("MBError"), OSMB_OK); return FALSE; } if (pfd.cAlphaBits < 8) { close(); - OSMessageBox( - "Second Life is unable to run because it can't get an 8 bit alpha\n" - "channel. Usually this is due to video card driver issues.\n" - "Please make sure you have the latest video card drivers installed.\n" - "Also be sure your monitor is set to True Color (32-bit) in\n" - "Control Panels -> Display -> Settings.\n" - "If you continue to receive this message, contact customer service.", - "Error", - OSMB_OK); + OSMessageBox(mCallbacks->translateString("MBAlpha"), + mCallbacks->translateString("MBError"), OSMB_OK); return FALSE; } if (!SetPixelFormat(mhDC, pixel_format, &pfd)) { close(); - OSMessageBox("Can't set pixel format", "Error", OSMB_OK); + OSMessageBox(mCallbacks->translateString("MBPixelFmtSetErr"), + mCallbacks->translateString("MBError"), OSMB_OK); return FALSE; } if (!(mhRC = wglCreateContext(mhDC))) { close(); - OSMessageBox("Can't create GL rendering context", "Error", OSMB_OK); + OSMessageBox(mCallbacks->translateString("MBGLContextErr"), + mCallbacks->translateString("MBError"), OSMB_OK); return FALSE; } if (!wglMakeCurrent(mhDC, mhRC)) { close(); - OSMessageBox("Can't activate GL rendering context", "Error", OSMB_OK); + OSMessageBox(mCallbacks->translateString("MBGLContextActErr"), + mCallbacks->translateString("MBError"), OSMB_OK); return FALSE; } @@ -1322,14 +1321,15 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO if (!(mhDC = GetDC(mWindowHandle))) { close(); - OSMessageBox("Can't make GL device context", "Error", OSMB_OK); + OSMessageBox(mCallbacks->translateString("MBDevContextErr"), mCallbacks->translateString("MBError"), OSMB_OK); return FALSE; } if (!SetPixelFormat(mhDC, pixel_format, &pfd)) { close(); - OSMessageBox("Can't set pixel format", "Error", OSMB_OK); + OSMessageBox(mCallbacks->translateString("MBPixelFmtSetErr"), + mCallbacks->translateString("MBError"), OSMB_OK); return FALSE; } @@ -1366,7 +1366,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO &pfd)) { close(); - OSMessageBox("Can't get pixel format description", "Error", OSMB_OK); + OSMessageBox(mCallbacks->translateString("MBPixelFmtDescErr"), mCallbacks->translateString("MBError"), OSMB_OK); return FALSE; } @@ -1379,29 +1379,14 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO if (pfd.cColorBits < 32 || GetDeviceCaps(mhDC, BITSPIXEL) < 32) { close(); - OSMessageBox( - "Second Life requires True Color (32-bit) to run in a window.\n" - "Please go to Control Panels -> Display -> Settings and\n" - "set the screen to 32-bit color.\n" - "Alternately, if you choose to run fullscreen, Second Life\n" - "will automatically adjust the screen each time it runs.", - "Error", - OSMB_OK); + OSMessageBox(mCallbacks->translateString("MBTrueColorWindow"), mCallbacks->translateString("MBError"), OSMB_OK); return FALSE; } if (pfd.cAlphaBits < 8) { close(); - OSMessageBox( - "Second Life is unable to run because it can't get an 8 bit alpha\n" - "channel. Usually this is due to video card driver issues.\n" - "Please make sure you have the latest video card drivers installed.\n" - "Also be sure your monitor is set to True Color (32-bit) in\n" - "Control Panels -> Display -> Settings.\n" - "If you continue to receive this message, contact customer service.", - "Error", - OSMB_OK); + OSMessageBox(mCallbacks->translateString("MBAlpha"), mCallbacks->translateString("MBError"), OSMB_OK); return FALSE; } @@ -1454,28 +1439,21 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO if (!mhRC && !(mhRC = wglCreateContext(mhDC))) { close(); - OSMessageBox("Can't create GL rendering context", "Error", OSMB_OK); + OSMessageBox(mCallbacks->translateString("MBGLContextErr"), mCallbacks->translateString("MBError"), OSMB_OK); return FALSE; } if (!wglMakeCurrent(mhDC, mhRC)) { close(); - OSMessageBox("Can't activate GL rendering context", "Error", OSMB_OK); + OSMessageBox(mCallbacks->translateString("MBGLContextActErr"), mCallbacks->translateString("MBError"), OSMB_OK); return FALSE; } if (!gGLManager.initGL()) { close(); - OSMessageBox( - "Second Life is unable to run because your video card drivers\n" - "did not install properly, are out of date, or are for unsupported\n" - "hardware. Please make sure you have the latest video card drivers\n" - "and even if you do have the latest, try reinstalling them.\n\n" - "If you continue to receive this message, contact customer service.", - "Error", - OSMB_OK); + OSMessageBox(mCallbacks->translateString("MBVideoDrvErr"), mCallbacks->translateString("MBError"), OSMB_OK); return FALSE; } diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp index 9488e7a25..86dd63f37 100644 --- a/indra/llxml/llcontrol.cpp +++ b/indra/llxml/llcontrol.cpp @@ -1150,7 +1150,7 @@ static std::string get_warn_name(const std::string& name) return warnname; } -void LLControlGroup::addWarning(const std::string& name) +LLControlVariable *LLControlGroup::addWarning(const std::string& name) { // Note: may get called more than once per warning // (e.g. if allready loaded from a settings file), @@ -1159,6 +1159,7 @@ void LLControlGroup::addWarning(const std::string& name) std::string comment = std::string("Enables ") + name + std::string(" warning dialog"); declareBOOL(warnname, TRUE, comment); mWarnings.insert(warnname); + return getControl(warnname); } BOOL LLControlGroup::getWarning(const std::string& name) diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h index a20bd1d6a..47df59d5e 100644 --- a/indra/llxml/llcontrol.h +++ b/indra/llxml/llcontrol.h @@ -336,7 +336,7 @@ public: // Ignorable Warnings // Add a config variable to be reset on resetWarnings() - void addWarning(const std::string& name); + LLControlVariable *addWarning(const std::string& name); BOOL getWarning(const std::string& name); void setWarning(const std::string& name, BOOL val); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 39b74df92..fc402c862 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -426,7 +426,6 @@ set(viewer_SOURCE_FILES lltoolselectrect.cpp lltoolview.cpp lltracker.cpp - lltrans.cpp lltranslate.cpp lluploaddialog.cpp lluploadfloaterobservers.cpp @@ -900,7 +899,6 @@ set(viewer_HEADER_FILES lltoolselectrect.h lltoolview.h lltracker.h - lltrans.h lltranslate.h lluiconstants.h lluploaddialog.h diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index f81728318..23a8025f3 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -130,7 +130,7 @@ #include "llviewermenu.h" #include "llselectmgr.h" #include "lltrans.h" -#include "lluitrans.h" +#include "lltrans.h" #include "lltracker.h" #include "llviewerparcelmgr.h" #include "llworldmapview.h" @@ -365,6 +365,22 @@ class LLDeferredTaskList: public LLSingleton signal_t mSignal; }; + +//---------------------------------------------------------------------------- + +// List of entries from strings.xml to always replace +static std::set default_trans_args; +void init_default_trans_args() +{ + default_trans_args.insert("SECOND_LIFE"); // World + default_trans_args.insert("APP_NAME"); + default_trans_args.insert("CAPITALIZED_APP_NAME"); + default_trans_args.insert("SECOND_LIFE_GRID"); + default_trans_args.insert("SUPPORT_SITE"); + default_trans_args.insert("CURRENCY"); + default_trans_args.insert("GRID_OWNER"); +} + //---------------------------------------------------------------------------- // File scope definitons const char *VFS_DATA_FILE_BASE = "data.db2.x."; @@ -598,7 +614,10 @@ bool LLAppViewer::init() // // OK to write stuff to logs now, we've now crash reported if necessary // - if (!initConfiguration()) + + init_default_trans_args(); + + if (!initConfiguration()) return false; LL_INFOS("InitInfo") << "Configuration initialized." << LL_ENDL ; @@ -688,12 +707,13 @@ bool LLAppViewer::init() ); LLWeb::initClass(); // do this after LLUI + LLUICtrlFactory::getInstance()->setupPaths(); // update paths with correct language set + LLTrans::parseStrings("strings.xml", default_trans_args); + LLTextEditor::setURLCallbacks(&LLWeb::loadURL, &LLURLDispatcher::dispatchFromTextEditor, &LLURLDispatcher::dispatchFromTextEditor); - LLUICtrlFactory::getInstance()->setupPaths(); // update paths with correct language set - ///////////////////////////////////////////////// // // Load settings files @@ -753,18 +773,8 @@ bool LLAppViewer::init() if (!initCache()) { std::ostringstream msg; - msg << - gSecondLife << " is unable to access a file that it needs.\n" - "\n" - "This can be because you somehow have multiple copies running, " - "or your system incorrectly thinks a file is open. " - "If this message persists, restart your computer and try again. " - "If it continues to persist, you may need to completely uninstall " << - gSecondLife << " and reinstall it."; - OSMessageBox( - msg.str(), - LLStringUtil::null, - OSMB_OK); + msg << LLTrans::getString("MBUnableToAccessFile"); + OSMessageBox(msg.str(),LLStringUtil::null,OSMB_OK); return 1; } LL_INFOS("InitInfo") << "Cache initialization is done." << LL_ENDL ; @@ -1964,6 +1974,9 @@ bool LLAppViewer::initConfiguration() return false; } + LLUICtrlFactory::getInstance()->setupPaths(); // setup paths for LLTrans based on settings files only + LLTrans::parseStrings("strings.xml", default_trans_args); + //COA vars in gSavedSettings will be linked to gSavedPerAccountSettings entries that will be created if not present. //Signals will be shared between linked vars. gSavedSettings.connectCOAVars(gSavedPerAccountSettings); @@ -2048,15 +2061,8 @@ bool LLAppViewer::initConfiguration() llinfos << "Command line usage:\n" << clp << llendl; std::ostringstream msg; - msg << "Second Life found an error parsing the command line. \n" - << "Please see: http://wiki.secondlife.com/wiki/Client_parameters \n" - << "Error: " << clp.getErrorMessage(); - - OSMessageBox( - msg.str(), - LLStringUtil::null, - OSMB_OK); - + msg << LLTrans::getString("MBCmdLineError") << clp.getErrorMessage(); + OSMessageBox(msg.str(),LLStringUtil::null,OSMB_OK); return false; } @@ -2100,7 +2106,7 @@ bool LLAppViewer::initConfiguration() if(clp.hasOption("help")) { std::ostringstream msg; - msg << "Command line usage:\n" << clp; + msg << LLTrans::getString("MBCmdLineUsg") << "\n" << clp; llinfos << msg.str() << llendl; OSMessageBox( @@ -2264,7 +2270,7 @@ bool LLAppViewer::initConfiguration() #if LL_DARWIN // Initialize apple menubar and various callbacks - init_apple_menu(gSecondLife.c_str()); + init_apple_menu(LLTrans::getString("APP_NAME").c_str()); #if __ppc__ // If the CPU doesn't have Altivec (i.e. it's not at least a G4), don't go any further. @@ -2272,7 +2278,7 @@ bool LLAppViewer::initConfiguration() if(!gSysCPU.hasAltivec()) { std::ostringstream msg; - msg << gSecondLife << " requires a processor with AltiVec (G4 or later)."; + msg << LLTrans::getString("MBRequiresAltiVec"); OSMessageBox( msg.str(), LLStringUtil::null, @@ -2286,10 +2292,11 @@ bool LLAppViewer::initConfiguration() // Display splash screen. Must be after above check for previous // crash as this dialog is always frontmost. - std::ostringstream splash_msg; - splash_msg << "Loading " << gSecondLife << "..."; + std::string splash_msg; + LLStringUtil::format_map_t args; + splash_msg = LLTrans::getString("StartupLoading", args); LLSplashScreen::show(); - LLSplashScreen::update(splash_msg.str()); + LLSplashScreen::update(splash_msg); //LLVolumeMgr::initClass(); LLVolumeMgr* volume_manager = new LLVolumeMgr(); @@ -2303,12 +2310,11 @@ bool LLAppViewer::initConfiguration() // // Set the name of the window // -#if LL_RELEASE_FOR_DOWNLOAD - gWindowTitle = gSecondLife; -#elif LL_DEBUG - gWindowTitle = gSecondLife + std::string(" [DEBUG] ") + gArgs; + gWindowTitle = LLTrans::getString("APP_NAME"); +#if LL_DEBUG + gWindowTitle += std::string(" [DEBUG] ") + gArgs; #else - gWindowTitle = gSecondLife + std::string(" ") + gArgs; + gWindowTitle += std::string(" ") + gArgs; #endif LLStringUtil::truncate(gWindowTitle, 255); @@ -2345,11 +2351,7 @@ bool LLAppViewer::initConfiguration() if (mSecondInstance) { std::ostringstream msg; - msg << - gSecondLife << " is already running.\n" - "\n" - "Check your task bar for a minimized copy of the program.\n" - "If this message persists, restart your computer.", + msg << LLTrans::getString("MBAlreadyRunning"); OSMessageBox( msg.str(), LLStringUtil::null, @@ -2418,20 +2420,17 @@ void LLAppViewer::checkForCrash(void) // Pop up a freeze or crash warning dialog // S32 choice; - if(gCrashSettings.getS32(CRASH_BEHAVIOR_SETTING) == CRASH_BEHAVIOR_ASK) + const S32 cb = gCrashSettings.getS32(CRASH_BEHAVIOR_SETTING); + if(cb == CRASH_BEHAVIOR_ASK) { std::ostringstream msg; - msg << gSecondLife - << " appears to have frozen or crashed on the previous run.\n" - << "Would you like to send a crash report?"; - std::string alert; - alert = gSecondLife; - alert += " Alert"; + msg << LLTrans::getString("MBFrozenCrashed"); + std::string alert = LLTrans::getString("APP_NAME") + " " + LLTrans::getString("MBAlert"); choice = OSMessageBox(msg.str(), alert, OSMB_YESNO); } - else if(gCrashSettings.getS32(CRASH_BEHAVIOR_SETTING) == CRASH_BEHAVIOR_NEVER_SEND) + else if(cb == CRASH_BEHAVIOR_NEVER_SEND) { choice = OSBTN_NO; } @@ -2512,9 +2511,6 @@ bool LLAppViewer::initWindow() LLUI::sWindow = gViewerWindow->getWindow(); - LLTrans::parseStrings("strings.xml"); - LLUITrans::parseStrings("ui_strings.xml"); - // Show watch cursor gViewerWindow->setCursor(UI_CURSOR_WAIT); @@ -2637,7 +2633,7 @@ void LLAppViewer::writeSystemInfo() gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)true; // Dump some debugging info - LL_INFOS("SystemInfo") << gSecondLife + LL_INFOS("SystemInfo") << LLTrans::getString("APP_NAME") << " version " << LL_VERSION_MAJOR << "." << LL_VERSION_MINOR << "." << LL_VERSION_PATCH << LL_ENDL; @@ -3237,14 +3233,14 @@ bool LLAppViewer::initCache() if (mPurgeCache && !read_only) { - LLSplashScreen::update("Clearing cache..."); + LLSplashScreen::update(LLTrans::getString("StartupClearingCache")); purgeCache(); // texture_cache_mismatch = false; // } - LLSplashScreen::update("Initializing Texture Cache..."); + LLSplashScreen::update(LLTrans::getString("StartupInitializingTextureCache")); // Init the texture cache // Allocate 80% of the cache size for textures @@ -3272,7 +3268,7 @@ bool LLAppViewer::initCache() LLVOCache::getInstance()->initCache(LL_PATH_CACHE, gSavedSettings.getU32("CacheNumberOfRegionsForObjects"), getObjectCacheVersion()) ; - LLSplashScreen::update("Initializing VFS..."); + LLSplashScreen::update(LLTrans::getString("StartupInitializingVFS")); // Init the VFS vfs_size = llmin(vfs_size + extra, MAX_VFS_SIZE); @@ -3433,7 +3429,7 @@ void LLAppViewer::addOnIdleCallback(const boost::function& cb) void LLAppViewer::purgeCache() { - LL_INFOS("AppCache") << "Purging Cache and Texture Cache..." << llendl; + LL_INFOS("AppCache") << "Purging Cache and Texture Cache..." << LL_ENDL; LLAppViewer::getTextureCache()->purgeCache(LL_PATH_CACHE); LLVOCache::getInstance()->removeCache(LL_PATH_CACHE); std::string mask = "*.*"; @@ -4076,7 +4072,7 @@ void LLAppViewer::idleShutdown() S32 finished_uploads = total_uploads - pending_uploads; F32 percent = 100.f * finished_uploads / total_uploads; gViewerWindow->setProgressPercent(percent); - gViewerWindow->setProgressString("Saving final data..."); + gViewerWindow->setProgressString(LLTrans::getString("SavingSettings")); return; } @@ -4088,7 +4084,7 @@ void LLAppViewer::idleShutdown() // Wait for a LogoutReply message gViewerWindow->setShowProgress(!gSavedSettings.getBOOL("AscentDisableLogoutScreens")); gViewerWindow->setProgressPercent(100.f); - gViewerWindow->setProgressString("Logging out..."); + gViewerWindow->setProgressString(LLTrans::getString("LoggingOut")); return; } @@ -4300,8 +4296,8 @@ void LLAppViewer::idleNetwork() { LLUUID this_region_id = agent_region->getRegionID(); bool this_region_alive = agent_region->isAlive(); - if (mAgentRegionLastAlive && !this_region_alive // newly dead - && mAgentRegionLastID == this_region_id) // same region + if ((mAgentRegionLastAlive && !this_region_alive) // newly dead + && (mAgentRegionLastID == this_region_id)) // same region { forceDisconnect(LLTrans::getString("AgentLostConnection")); } diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 133e97aea..79da09dfc 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -64,6 +64,7 @@ #include "llfindlocale.h" #include "llcommandlineparser.h" +#include "lltrans.h" // *FIX:Mani - This hack is to fix a linker issue with libndofdev.lib // The lib was compiled under VS2005 - in VS2003 we need to remap assert @@ -469,7 +470,7 @@ bool LLAppViewerWin32::initHardwareTest() // but vram. vram_only = TRUE; - LLSplashScreen::update("Detecting hardware..."); + LLSplashScreen::update(LLTrans::getString("StartupDetectingHardware")); LL_DEBUGS("AppInit") << "Attempting to poll DirectX for hardware info" << LL_ENDL; gDXHardware.setWriteDebugFunc(write_debug_dx); @@ -483,19 +484,10 @@ bool LLAppViewerWin32::initHardwareTest() // Warn them that runnin without DirectX 9 will // not allow us to tell them about driver issues std::ostringstream msg; - msg << - LLAppViewer::instance()->getSecondLifeTitle() << " is unable to detect DirectX 9.0b or greater.\n" - "\n" << - LLAppViewer::instance()->getSecondLifeTitle() << " uses DirectX to detect hardware and/or\n" - "outdated drivers that can cause stability problems,\n" - "poor performance and crashes. While you can run\n" << - LLAppViewer::instance()->getSecondLifeTitle() << " without it, we highly recommend running\n" - "with DirectX 9.0b\n" - "\n" - "Do you wish to continue?\n"; + msg << LLTrans::getString ("MBNoDirectX"); S32 button = OSMessageBox( msg.str(), - "Warning", + LLTrans::getString("MBWarning"), OSMB_YESNO); if (OSBTN_NO== button) { @@ -511,10 +503,12 @@ bool LLAppViewerWin32::initHardwareTest() gSavedSettings.setBOOL("ProbeHardwareOnStartup", FALSE); // Disable so debugger can work - std::ostringstream splash_msg; - splash_msg << "Loading " << LLAppViewer::instance()->getSecondLifeTitle() << "..."; + std::string splash_msg; + LLStringUtil::format_map_t args; + args["[APP_NAME]"] = LLAppViewer::instance()->getSecondLifeTitle(); + splash_msg = LLTrans::getString("StartupLoading", args); - LLSplashScreen::update(splash_msg.str()); + LLSplashScreen::update(splash_msg); } if (!restoreErrorTrap()) diff --git a/indra/newview/llfirstuse.cpp b/indra/newview/llfirstuse.cpp index d59167ddf..b8e8b37dc 100644 --- a/indra/newview/llfirstuse.cpp +++ b/indra/newview/llfirstuse.cpp @@ -95,7 +95,6 @@ void LLFirstUse::useBalanceIncrease(S32 delta) LLSD args; args["AMOUNT"] = llformat("%d",delta); - args["CURRENCY"] = gHippoGridManager->getConnectedGrid()->getCurrencySymbol(); LLNotificationsUtil::add("FirstBalanceIncrease", args); } } @@ -110,7 +109,6 @@ void LLFirstUse::useBalanceDecrease(S32 delta) LLSD args; args["AMOUNT"] = llformat("%d",-delta); - args["CURRENCY"] = gHippoGridManager->getConnectedGrid()->getCurrencySymbol(); LLNotificationsUtil::add("FirstBalanceDecrease", args); } } diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp index bd8cd5286..c80708879 100644 --- a/indra/newview/llfloaterbuyland.cpp +++ b/indra/newview/llfloaterbuyland.cpp @@ -1042,18 +1042,17 @@ void LLFloaterBuyLandUI::refreshUI() cost_per_sqm = (F32)mParcelPrice / (F32)mParcelActualArea; } - LLStringUtil::format_map_t info_price_args; - info_price_args["[PRICE]"] = llformat("%d", mParcelPrice); - info_price_args["[PRICE_PER_SQM]"] = llformat("%.1f", cost_per_sqm); + string_args["[PRICE]"] = llformat("%d", mParcelPrice); + string_args["[PRICE_PER_SQM]"] = llformat("%.1f", cost_per_sqm); if (mParcelSoldWithObjects) { - info_price_args["[SOLD_WITH_OBJECTS]"] = getString("sold_with_objects"); + string_args["[SOLD_WITH_OBJECTS]"] = getString("sold_with_objects"); } else { - info_price_args["[SOLD_WITH_OBJECTS]"] = getString("sold_without_objects"); + string_args["[SOLD_WITH_OBJECTS]"] = getString("sold_without_objects"); } - childSetText("info_price", getString("info_price_string", info_price_args)); + childSetText("info_price", getString("info_price_string", string_args)); childSetVisible("info_price", mParcelIsForSale); } else diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 9882a71e8..451d4472b 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -946,7 +946,6 @@ void LLPanelLandGeneral::onClickBuyPass(void* data) LLSD args; args["COST"] = cost; - args["CURRENCY"] = gHippoGridManager->getConnectedGrid()->getCurrencySymbol(); args["PARCEL_NAME"] = parcel_name; args["TIME"] = time; diff --git a/indra/newview/llfloateropenobject.cpp b/indra/newview/llfloateropenobject.cpp index 6a762d00a..7465eb94d 100644 --- a/indra/newview/llfloateropenobject.cpp +++ b/indra/newview/llfloateropenobject.cpp @@ -157,26 +157,51 @@ void LLFloaterOpenObject::moveToInventory(bool wear) { parent_category_id = gInventory.getRootFolderID(); } - LLUUID category_id = gInventory.createNewCategory(parent_category_id, - LLFolderType::FT_NONE, - name); - LLCatAndWear* data = new LLCatAndWear; - data->mCatID = category_id; - data->mWear = wear; + LLCategoryCreate* cat_data = new LLCategoryCreate(object_id, wear); + + LLUUID category_id = gInventory.createNewCategory(parent_category_id, + LLFolderType::FT_NONE, + name, + callbackCreateInventoryCategory, + (void*)cat_data); + + //If we get a null category ID, we are using a capability in createNewCategory and we will + //handle the following in the callbackCreateInventoryCategory routine. + if ( category_id.notNull() ) + { + LLSD result; + result["folder_id"] = category_id; + //Reduce redundant code by just calling the callback. Dur. + callbackCreateInventoryCategory(result,cat_data); + } +} + +// static +void LLFloaterOpenObject::callbackCreateInventoryCategory(const LLSD& result, void* data) +{ + LLCategoryCreate* cat_data = (LLCategoryCreate*)data; + + LLUUID category_id = result["folder_id"].asUUID(); + LLCatAndWear* wear_data = new LLCatAndWear; + + wear_data->mCatID = category_id; + wear_data->mWear = cat_data->mWear; + wear_data->mFolderResponded = true; // Copy and/or move the items into the newly created folder. // Ignore any "you're going to break this item" messages. - BOOL success = move_inv_category_world_to_agent(object_id, category_id, TRUE, + BOOL success = move_inv_category_world_to_agent(cat_data->mObjectID, category_id, TRUE, callbackMoveInventory, - (void*)data); + (void*)wear_data); if (!success) { - delete data; - data = NULL; - + delete wear_data; + wear_data = NULL; + LLNotificationsUtil::add("OpenObjectCannotCopy"); } + delete cat_data; } // static diff --git a/indra/newview/llfloateropenobject.h b/indra/newview/llfloateropenobject.h index 27653a5c9..8c00cc7f7 100644 --- a/indra/newview/llfloateropenobject.h +++ b/indra/newview/llfloateropenobject.h @@ -49,11 +49,21 @@ class LLFloaterOpenObject public: static void show(); static void dirty(); - + + class LLCategoryCreate + { + public: + LLCategoryCreate(LLUUID object_id, bool wear) : mObjectID(object_id), mWear(wear) {} + public: + LLUUID mObjectID; + bool mWear; + }; + struct LLCatAndWear { LLUUID mCatID; bool mWear; + bool mFolderResponded; }; protected: @@ -67,6 +77,7 @@ protected: static void onClickMoveToInventory(void* data); static void onClickMoveAndWear(void* data); + static void callbackCreateInventoryCategory(const LLSD& result, void* data); static void callbackMoveInventory(S32 result, void* data); static void* createPanelInventory(void* data); diff --git a/indra/newview/llfloaterpostcard.cpp b/indra/newview/llfloaterpostcard.cpp index a1b86b238..f4aa77aa9 100644 --- a/indra/newview/llfloaterpostcard.cpp +++ b/indra/newview/llfloaterpostcard.cpp @@ -55,6 +55,7 @@ #include "llstatusbar.h" #include "llviewerregion.h" #include "lleconomy.h" +#include "lltrans.h" #include "llgl.h" #include "llglheaders.h" @@ -362,7 +363,7 @@ bool LLFloaterPostcard::missingSubjMsgAlertCallback(const LLSD& notification, co { // Stuff the subject back into the form. LLStringUtil::format_map_t targs; - targs["[GRID_NAME]"] = gHippoGridManager->getConnectedGrid()->getGridName(); + targs["[SECOND_LIFE]"] = LLTrans::getString("SECOND_LIFE"); std::string subj = getString("default_subject"); LLStringUtil::format(subj, targs); diff --git a/indra/newview/llhoverview.cpp b/indra/newview/llhoverview.cpp index 171977066..ce2bb321a 100644 --- a/indra/newview/llhoverview.cpp +++ b/indra/newview/llhoverview.cpp @@ -482,7 +482,6 @@ void LLHoverView::updateText() else if (for_sale) { LLStringUtil::format_map_t args; - args["[CURRENCY]"] = gHippoGridManager->getConnectedGrid()->getCurrencySymbol(); args["[AMOUNT]"] = llformat("%d", nodep->mSaleInfo.getSalePrice()); line.append(LLTrans::getString("TooltipForSaleL$", args)); suppressObjectHoverDisplay = FALSE; // Show tip @@ -686,7 +685,6 @@ void LLHoverView::updateText() if (hover_parcel && hover_parcel->getParcelFlag(PF_FOR_SALE)) { LLStringUtil::format_map_t args; - args["[CURRENCY]"] = gHippoGridManager->getConnectedGrid()->getCurrencySymbol(); args["[AMOUNT]"] = llformat("%d", hover_parcel->getSalePrice()); line = LLTrans::getString("TooltipForSaleL$", args); mText.push_back(line); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index a773a196a..9d4edc275 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -2097,15 +2097,15 @@ void LLRightClickInventoryFetchDescendentsObserver::done() class LLInventoryCopyAndWearObserver : public LLInventoryObserver { public: - LLInventoryCopyAndWearObserver(const LLUUID& cat_id, int count) : - mCatID(cat_id), mContentsCount(count), mFolderAdded(FALSE) {} + LLInventoryCopyAndWearObserver(const LLUUID& cat_id, int count, bool folder_added=false) : + mCatID(cat_id), mContentsCount(count), mFolderAdded(folder_added) {} virtual ~LLInventoryCopyAndWearObserver() {} virtual void changed(U32 mask); protected: LLUUID mCatID; int mContentsCount; - BOOL mFolderAdded; + bool mFolderAdded; }; @@ -2923,7 +2923,7 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response object->getInventoryContents(inventory_objects); int contents_count = inventory_objects.size()-1; //subtract one for containing folder - LLInventoryCopyAndWearObserver* inventoryObserver = new LLInventoryCopyAndWearObserver(cat_and_wear->mCatID, contents_count); + LLInventoryCopyAndWearObserver* inventoryObserver = new LLInventoryCopyAndWearObserver(cat_and_wear->mCatID, contents_count, cat_and_wear->mFolderResponded); gInventory.addObserver(inventoryObserver); } diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index ecafb56b9..68a52b1f2 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -492,13 +492,65 @@ LLUUID LLInventoryModel::findCategoryByName(std::string name) return LLUUID::null; } +class LLCreateInventoryCategoryResponder : public LLHTTPClient::Responder +{ +public: + LLCreateInventoryCategoryResponder(LLInventoryModel* model, + void (*callback)(const LLSD&, void*), + void* user_data) : + mModel(model), + mCallback(callback), + mData(user_data) + { + } + + virtual void error(U32 status, const std::string& reason) + { + LL_WARNS("InvAPI") << "CreateInventoryCategory failed. status = " << status << ", reasion = \"" << reason << "\"" << LL_ENDL; + } + + virtual void result(const LLSD& content) + { + //Server has created folder. + + LLUUID category_id = content["folder_id"].asUUID(); + + + // Add the category to the internal representation + LLPointer cat = + new LLViewerInventoryCategory( category_id, + content["parent_id"].asUUID(), + (LLFolderType::EType)content["type"].asInteger(), + content["name"].asString(), + gAgent.getID() ); + cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL); + cat->setDescendentCount(0); + LLInventoryModel::LLCategoryUpdate update(cat->getParentUUID(), 1); + mModel->accountForUpdate(update); + mModel->updateCategory(cat); + + if (mCallback && mData) + { + mCallback(content, mData); + } + + } + +private: + void (*mCallback)(const LLSD&, void*); + void* mData; + LLInventoryModel* mModel; +}; + // Convenience function to create a new category. You could call // updateCategory() with a newly generated UUID category, but this // version will take care of details like what the name should be // based on preferred type. Returns the UUID of the new category. LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, LLFolderType::EType preferred_type, - const std::string& pname) + const std::string& pname, + void (*callback)(const LLSD&, void*)/*=NULL*/, + void* user_data/*=NULL*/) { LLUUID id; if(!isInventoryUsable()) @@ -524,6 +576,35 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, else name.assign(NEW_CATEGORY_NAMES[preferred_type]); + if ( callback && user_data ) //callback required for acked message. + { + LLViewerRegion* viewer_region = gAgent.getRegion(); + std::string url; + if ( viewer_region ) + url = viewer_region->getCapability("CreateInventoryCategory"); + + if (!url.empty()) + { + //Let's use the new capability. + + LLSD request, body; + body["folder_id"] = id; + body["parent_id"] = parent_id; + body["type"] = (LLSD::Integer) preferred_type; + body["name"] = name; + + request["message"] = "CreateInventoryCategory"; + request["payload"] = body; + +// viewer_region->getCapAPI().post(request); + LLHTTPClient::post( + url, + body, + new LLCreateInventoryCategoryResponder(this, callback, user_data) ); + return LLUUID::null; + } + } + // Add the category to the internal representation LLPointer cat = new LLViewerInventoryCategory(id, parent_id, preferred_type, name, gAgent.getID()); diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index c5b94a0f4..b3608a536 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -393,7 +393,9 @@ public: // name based on type, pass in a NULL to the 'name' parameter. LLUUID createNewCategory(const LLUUID& parent_id, LLFolderType::EType preferred_type, - const std::string& name); + const std::string& namevoid, + void (*callback)(const LLSD&, void*) = NULL, + void* user_data = NULL); // Internal methods that add inventory and make sure that all of // the internal data structures are consistent. These methods diff --git a/indra/newview/llnotify.cpp b/indra/newview/llnotify.cpp index 5d73bf540..20145004f 100644 --- a/indra/newview/llnotify.cpp +++ b/indra/newview/llnotify.cpp @@ -44,6 +44,7 @@ #include "lliconctrl.h" #include "lltextbox.h" #include "lltexteditor.h" +#include "lltrans.h" #include "lluiconstants.h" #include "llui.h" #include "llxmlnode.h" @@ -581,14 +582,15 @@ void LLNotifyBox::close() void LLNotifyBox::format(std::string& msg, const LLStringUtil::format_map_t& args) { - // XUI:translate! + // add default substitutions LLStringUtil::format_map_t targs = args; - targs["[SECOND_LIFE]"] = gHippoGridManager->getConnectedGrid()->getGridName(); - targs["[GRID_NAME]"] = gHippoGridManager->getConnectedGrid()->getGridName(); - targs["[GRID_OWNER]"] = gHippoGridManager->getConnectedGrid()->getGridOwner(); - targs["[GRID_SITE]"] = gHippoGridManager->getConnectedGrid()->getWebSite(); - targs["[CURRENCY]"] = gHippoGridManager->getConnectedGrid()->getCurrencySymbol(); - targs["[VIEWER_NAME]"] = "Singularity Viewer"; + const LLStringUtil::format_map_t& default_args = LLTrans::getDefaultArgs(); + for (LLStringUtil::format_map_t::const_iterator iter = default_args.begin(); + iter != default_args.end(); ++iter) + { + targs[iter->first] = iter->second; + } + LLStringUtil::format(msg, targs); } diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp index 45dfb60b9..c34f1aa30 100644 --- a/indra/newview/llpanelclassified.cpp +++ b/indra/newview/llpanelclassified.cpp @@ -883,7 +883,6 @@ void LLPanelClassified::callbackGotPriceForListing(S32 option, std::string text, LLSD args; std::string price_text = llformat("%d", MINIMUM_PRICE_FOR_LISTING); args["MIN_PRICE"] = price_text; - args["[CURRENCY]"] = gHippoGridManager->getConnectedGrid()->getCurrencySymbol(); LLNotificationsUtil::add("MinClassifiedPrice", args); return; diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp index 044b40337..d608f7a98 100644 --- a/indra/newview/llpanelgroupgeneral.cpp +++ b/indra/newview/llpanelgroupgeneral.cpp @@ -372,7 +372,6 @@ void LLPanelGroupGeneral::onClickJoin(void *userdata) S32 cost = gdatap->mMembershipFee; LLSD args; args["COST"] = llformat("%d", cost); - args["CURRENCY"] = gHippoGridManager->getConnectedGrid()->getCurrencySymbol(); LLSD payload; payload["group_id"] = self->mGroupID; diff --git a/indra/newview/llpanelinventory.cpp b/indra/newview/llpanelinventory.cpp index bfb4ca1d1..536322782 100644 --- a/indra/newview/llpanelinventory.cpp +++ b/indra/newview/llpanelinventory.cpp @@ -245,7 +245,6 @@ void LLTaskInvFVBridge::buyItem() { LLSD args; args["PRICE"] = llformat("%d",sale_info.getSalePrice()); - args["CURRENCY"] = gHippoGridManager->getConnectedGrid()->getCurrencySymbol(); args["OWNER"] = owner_name; if (sale_info.getSaleType() != LLSaleInfo::FS_CONTENTS) { diff --git a/indra/newview/llpanelmsgs.cpp b/indra/newview/llpanelmsgs.cpp index 42fb393ca..54e2f7dbe 100644 --- a/indra/newview/llpanelmsgs.cpp +++ b/indra/newview/llpanelmsgs.cpp @@ -40,6 +40,7 @@ #include "llviewercontrol.h" #include "lluictrlfactory.h" #include "llfirstuse.h" +#include "llnotificationtemplate.h" //----------------------------------------------------------------------------- LLPanelMsgs::LLPanelMsgs() : @@ -71,11 +72,14 @@ BOOL LLPanelMsgs::postBuild() return TRUE; } -void LLPanelMsgs::buildLists() -{ - LLScrollListCtrl& disabled_popups = getChildRef("disabled_popups"); - LLScrollListCtrl& enabled_popups = getChildRef("enabled_popups"); +void LLPanelMsgs::buildLists() //void LLFloaterPreference::buildPopupLists() in v3 +{ + LLScrollListCtrl& disabled_popups = + getChildRef("disabled_popups"); + LLScrollListCtrl& enabled_popups = + getChildRef("enabled_popups"); + disabled_popups.deleteAllItems(); enabled_popups.deleteAllItems(); @@ -90,14 +94,20 @@ void LLPanelMsgs::buildLists() if (ignore == LLNotificationForm::IGNORE_NO) continue; + LLSD params; + params["name"] = (*iter).first; + LLNotificationPtr notification = LLNotificationPtr(new LLNotification(params)); + LLSD row; - row["columns"][0]["value"] = formp->getIgnoreMessage(); + std::string ignore_msg = formp->getIgnoreMessage(); + LLStringUtil::format(ignore_msg,notification->getSubstitutions()); + row["columns"][0]["value"] = ignore_msg; row["columns"][0]["font"] = "SANSSERIF_SMALL"; row["columns"][0]["width"] = 300; LLScrollListItem* item = NULL; - bool show_popup = gSavedSettings.getWarning(templatep->mName); + bool show_popup = !formp->getIgnored(); if (!show_popup) { if (ignore == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE) diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 191b8c918..3fd18cf7d 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -263,6 +263,9 @@ static bool gUseCircuitCallbackCalled = false; EStartupState LLStartUp::gStartupState = STATE_FIRST; +static U64 gFirstSimHandle = 0; +static LLHost gFirstSim; +static std::string gFirstSimSeedCap; // // local function declaration // @@ -374,9 +377,6 @@ bool idle_startup() static std::string password; static std::vector requested_options; - static U64 first_sim_handle = 0; - static LLHost first_sim; - static std::string first_sim_seed_cap; static U32 first_sim_size_x = 256; static U32 first_sim_size_y = 256; @@ -823,7 +823,6 @@ bool idle_startup() set_startup_status(0.03f, msg.c_str(), gAgent.mMOTD.c_str()); display_startup(); // LLViewerMedia::initBrowser(); - LLStartUp::setStartupState( STATE_LOGIN_SHOW ); return FALSE; } @@ -991,7 +990,14 @@ bool idle_startup() } gHippoGridManager->setCurrentGridAsConnected(); - gHippoLimits->setLimits(); + gHippoLimits->setLimits(); + if(!gHippoGridManager->getConnectedGrid()->isSecondLife()) + { + LLTrans::setDefaultArg("[CURRENCY]",gHippoGridManager->getConnectedGrid()->getCurrencySymbol()); //replace [CURRENCY] with OS$, not L$ for instance. + LLTrans::setDefaultArg("[SECOND_LIFE]", gHippoGridManager->getConnectedGrid()->getGridName()); + LLTrans::setDefaultArg("[SECOND_LIFE_GRID]", gHippoGridManager->getConnectedGrid()->getGridName() + " Grid"); + LLTrans::setDefaultArg("[GRID_OWNER]", gHippoGridManager->getConnectedGrid()->getGridOwner()); + } // create necessary directories // *FIX: these mkdir's should error check @@ -1135,7 +1141,7 @@ bool idle_startup() // Display the startup progress bar. gViewerWindow->setShowProgress(!gSavedSettings.getBOOL("AscentDisableLogoutScreens")); - gViewerWindow->setProgressCancelButtonVisible(TRUE, std::string("Quit")); // *TODO: Translate + gViewerWindow->setProgressCancelButtonVisible(TRUE, LLTrans::getString("Quit")); // Poke the VFS, which could potentially block for a while if // Windows XP is acting up @@ -1220,9 +1226,7 @@ bool idle_startup() } auth_method = "login_to_simulator"; - LLStringUtil::format_map_t args; - args["[APP_NAME]"] = LLAppViewer::instance()->getSecondLifeTitle(); - auth_desc = LLTrans::getString("LoginInProgress", args); + auth_desc = LLTrans::getString("LoginInProgress"); LLStartUp::setStartupState( STATE_XMLRPC_LEGACY_LOGIN ); // XMLRPC } @@ -1365,7 +1369,7 @@ bool idle_startup() LL_DEBUGS("AppInit") << "STATE_LOGIN_NO_DATA_YET" << LL_ENDL; // If we get here we have gotten past the potential stall // in curl, so take "may appear frozen" out of progress bar. JC - auth_desc = "Logging in..."; + auth_desc = LLTrans::getString("LoginInProgressNoFrozen"); set_startup_status(progress, auth_desc, auth_message); // Process messages to keep from dropping circuit. LLMessageSystem* msg = gMessageSystem; @@ -1431,7 +1435,7 @@ bool idle_startup() } else { - emsg << "Login failed.\n"; + emsg << LLTrans::getString("LoginFailed") + "\n"; reason_response = LLUserAuth::getInstance()->getResponse("reason"); message_response = LLUserAuth::getInstance()->getResponse("message"); @@ -1571,7 +1575,7 @@ bool idle_startup() text = LLUserAuth::getInstance()->getResponse("secure_session_id"); if(!text.empty()) gAgent.mSecureSessionID.set(text); - text = LLUserAuth::getInstance()->getResponse("firsst_name"); + text = LLUserAuth::getInstance()->getResponse("first_name"); if(!text.empty()) { // Remove quotes from string. Login.cgi sends these to force @@ -1663,10 +1667,10 @@ bool idle_startup() if(!sim_ip_str.empty() && !sim_port_str.empty()) { U32 sim_port = strtoul(sim_port_str.c_str(), NULL, 10); - first_sim.set(sim_ip_str, sim_port); - if (first_sim.isOk()) + gFirstSim.set(sim_ip_str, sim_port); + if (gFirstSim.isOk()) { - gMessageSystem->enableCircuit(first_sim, TRUE); + gMessageSystem->enableCircuit(gFirstSim, TRUE); } } std::string region_x_str = LLUserAuth::getInstance()->getResponse("region_x"); @@ -1675,7 +1679,7 @@ bool idle_startup() { U32 region_x = strtoul(region_x_str.c_str(), NULL, 10); U32 region_y = strtoul(region_y_str.c_str(), NULL, 10); - first_sim_handle = to_region_handle(region_x, region_y); + gFirstSimHandle = to_region_handle(region_x, region_y); } text = LLUserAuth::getInstance()->getResponse("region_size_x"); @@ -1698,7 +1702,7 @@ bool idle_startup() } text = LLUserAuth::getInstance()->getResponse("seed_capability"); - if (!text.empty()) first_sim_seed_cap = text; + if (!text.empty()) gFirstSimSeedCap = text; text = LLUserAuth::getInstance()->getResponse("seconds_since_epoch"); if(!text.empty()) @@ -1874,7 +1878,7 @@ bool idle_startup() if(gAgentID.notNull() && gAgentSessionID.notNull() && gMessageSystem->mOurCircuitCode - && first_sim.isOk()) + && gFirstSim.isOk()) // OGPX : Inventory root might be null in OGP. // && gAgent.mInventoryRootID.notNull()) { @@ -1970,14 +1974,14 @@ bool idle_startup() // This is necessary because creating objects before this is set will result in a // bad mPositionAgent cache. - gAgent.initOriginGlobal(from_region_handle(first_sim_handle)); + gAgent.initOriginGlobal(from_region_handle(gFirstSimHandle)); - LLWorld::getInstance()->addRegion(first_sim_handle, first_sim, first_sim_size_x, first_sim_size_y); + LLWorld::getInstance()->addRegion(gFirstSimHandle, gFirstSim, first_sim_size_x, first_sim_size_y); - LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(first_sim_handle); + LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(gFirstSimHandle); LL_INFOS("AppInit") << "Adding initial simulator " << regionp->getOriginGlobal() << LL_ENDL; - regionp->setSeedCapability(first_sim_seed_cap); + regionp->setSeedCapability(gFirstSimSeedCap); LL_DEBUGS("AppInit") << "Waiting for seed grant ...." << LL_ENDL; // Set agent's initial region to be the one we just created. @@ -2019,6 +2023,25 @@ bool idle_startup() //--------------------------------------------------------------------- if(STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState()) { + /*LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(gFirstSimHandle); + if (regionp->capabilitiesReceived()) + { + LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED ); + } + else + { + U32 num_retries = regionp->getNumSeedCapRetries(); + if (num_retries > 0) + { + LLStringUtil::format_map_t args; + args["[NUMBER]"] = llformat("%d", num_retries + 1); + set_startup_status(0.4f, LLTrans::getString("LoginRetrySeedCapGrant", args), gAgent.mMOTD); + } + else + { + set_startup_status(0.4f, LLTrans::getString("LoginRequestSeedCapGrant"), gAgent.mMOTD); + } + }*/ return FALSE; } @@ -2215,16 +2238,16 @@ bool idle_startup() gUseCircuitCallbackCalled = FALSE; - msg->enableCircuit(first_sim, TRUE); + msg->enableCircuit(gFirstSim, TRUE); // now, use the circuit info to tell simulator about us! - LL_INFOS("AppInit") << "viewer: UserLoginLocationReply() Enabling " << first_sim << " with code " << msg->mOurCircuitCode << LL_ENDL; + LL_INFOS("AppInit") << "viewer: UserLoginLocationReply() Enabling " << gFirstSim << " with code " << msg->mOurCircuitCode << LL_ENDL; msg->newMessageFast(_PREHASH_UseCircuitCode); msg->nextBlockFast(_PREHASH_CircuitCode); msg->addU32Fast(_PREHASH_Code, msg->mOurCircuitCode); msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); msg->addUUIDFast(_PREHASH_ID, gAgent.getID()); msg->sendReliable( - first_sim, + gFirstSim, MAX_TIMEOUT_COUNT, FALSE, TIMEOUT_SECONDS, diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 89f6615aa..21218e07a 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -774,7 +774,6 @@ bool join_group_response(const LLSD& notification, const LLSD& response) delete_context_data = FALSE; LLSD args; args["COST"] = llformat("%d", fee); - args["CURRENCY"] = gHippoGridManager->getConnectedGrid()->getCurrencySymbol(); // Set the fee for next time to 0, so that we don't keep // asking about a fee. LLSD next_payload = notification["payload"]; @@ -3921,7 +3920,7 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**) << x << ":" << y << " current pos " << gAgent.getPositionGlobal() << LL_ENDL; - LLAppViewer::instance()->forceDisconnect("You were sent to an invalid region."); + LLAppViewer::instance()->forceDisconnect(LLTrans::getString("SentToInvalidRegion")); return; } diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 9bbd9ca2a..57b53031e 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1493,6 +1493,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) //capabilityNames.append("AvatarPickerSearch"); //Display name/SLID lookup (llfloateravatarpicker.cpp) capabilityNames.append("ChatSessionRequest"); capabilityNames.append("CopyInventoryFromNotecard"); + capabilityNames.append("CreateInventoryCategory"); capabilityNames.append("DispatchRegionInfo"); capabilityNames.append("EstateChangeInfo"); capabilityNames.append("EventQueueGet"); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index ea1f6f91d..582107ddb 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -65,6 +65,7 @@ #include "llrect.h" #include "llsky.h" #include "llstring.h" +#include "lltrans.h" #include "llui.h" #include "lluuid.h" #include "llview.h" @@ -1228,7 +1229,7 @@ BOOL LLViewerWindow::handleActivate(LLWindow *window, BOOL activated) { // if we're in world, show a progress bar to hide reloading of textures llinfos << "Restoring GL during activate" << llendl; - restoreGL("Restoring..."); + restoreGL(LLTrans::getString("ProgressRestoring")); } else { @@ -1403,6 +1404,27 @@ void LLViewerWindow::handlePauseWatchdog(LLWindow *window) LLAppViewer::instance()->pauseMainloopTimeout(); } +//virtual +std::string LLViewerWindow::translateString(const char* tag) +{ + return LLTrans::getString( std::string(tag) ); +} + +//virtual +std::string LLViewerWindow::translateString(const char* tag, + const std::map& args) +{ + // LLTrans uses a special subclass of std::string for format maps, + // but we must use std::map<> in these callbacks, otherwise we create + // a dependency between LLWindow and LLFormatMapString. So copy the data. + LLStringUtil::format_map_t args_copy; + std::map::const_iterator it = args.begin(); + for ( ; it != args.end(); ++it) + { + args_copy[it->first] = it->second; + } + return LLTrans::getString( std::string(tag), args_copy); +} // // Classes @@ -1466,12 +1488,13 @@ LLViewerWindow::LLViewerWindow( if (NULL == mWindow) { - LLSplashScreen::update("Graphics Initialization Failed. Please Update Your Graphics Driver!"); + LLSplashScreen::update(LLTrans::getString("StartupRequireDriverUpdate")); LL_WARNS("Window") << "Failed to create window, to be shutting Down, be sure your graphics driver is updated." << llendl ; ms_sleep(5000) ; //wait for 5 seconds. - LLSplashScreen::update("Shutting down..."); + + LLSplashScreen::update(LLTrans::getString("ShuttingDown")); #if LL_LINUX || LL_SOLARIS llwarns << "Unable to create window, be sure screen is set at 32-bit color and your graphics driver is configured correctly. See README-linux.txt or README-solaris.txt for further information." << llendl; @@ -4577,7 +4600,7 @@ void LLViewerWindow::drawMouselookInstructions() } // Draw instructions for mouselook ("Press ESC to leave Mouselook" in a box at the top of the screen.) - const std::string instructions = "Press ESC to leave Mouselook."; + const std::string instructions = LLTrans::getString("LeaveMouselook"); const LLFontGL* font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF ); const S32 INSTRUCTIONS_PAD = 5; @@ -4983,7 +5006,7 @@ void LLViewerWindow::restartDisplay(BOOL show_progress_bar) stopGL(); if (show_progress_bar) { - restoreGL("Changing Resolution..."); + restoreGL(LLTrans::getString("ProgressChangingResolution")); } else { @@ -5070,7 +5093,7 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size, llinfos << "Restoring GL during resolution change" << llendl; if (show_progress_bar) { - restoreGL("Changing Resolution..."); + restoreGL(LLTrans::getString("ProgressChangingResolution")); } else { diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 1be59a452..6e8bf7e56 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -183,6 +183,9 @@ public: /*virtual*/ void handlePingWatchdog(LLWindow *window, const char * msg); /*virtual*/ void handlePauseWatchdog(LLWindow *window); /*virtual*/ void handleResumeWatchdog(LLWindow *window); + /*virtual*/ std::string translateString(const char* tag); + /*virtual*/ std::string translateString(const char* tag, + const std::map& args); // diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index 85751370c..1ff20dbb1 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -45,6 +45,7 @@ #include "llhttpnode.h" #include "llregionhandle.h" #include "llsurface.h" +#include "lltrans.h" #include "llviewercamera.h" #include "llviewertexture.h" #include "llviewertexturelist.h" @@ -278,7 +279,7 @@ void LLWorld::removeRegion(const LLHost &host) llwarns << "gFrameTimeSeconds " << gFrameTimeSeconds << llendl; llwarns << "Disabling region " << regionp->getName() << " that agent is in!" << llendl; - LLAppViewer::instance()->forceDisconnect("You have been disconnected from the region you were in."); + LLAppViewer::instance()->forceDisconnect(LLTrans::getString("YouHaveBeenDisconnected")); regionp->saveObjectCache() ; //force to save objects here in case that the object cache is about to be destroyed. return; diff --git a/indra/newview/skins/default/xui/en-us/floater_postcard.xml b/indra/newview/skins/default/xui/en-us/floater_postcard.xml index 1ac44fd2b..b6aabcf94 100644 --- a/indra/newview/skins/default/xui/en-us/floater_postcard.xml +++ b/indra/newview/skins/default/xui/en-us/floater_postcard.xml @@ -43,8 +43,8 @@