Merge branch 'master' of git://github.com/Shyotl/SingularityViewer

This commit is contained in:
Lirusaito
2012-01-11 02:28:14 -05:00
31 changed files with 504 additions and 321 deletions

View File

@@ -108,6 +108,7 @@ set(llui_HEADER_FILES
llnotificationptr.h
llnotifications.h
llnotificationsutil.h
llnotificationtemplate.h
llpanel.h
llprogressbar.h
llradiogroup.h

View File

@@ -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<std::string>& required_fields) const
{
for(std::vector<std::string>::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<std::string>::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

View File

@@ -217,6 +217,9 @@ public:
// appends form elements from another form serialized as LLSD
void append(const LLSD& sub_form);
std::string getDefaultOption();
LLPointer<class LLControlVariable> 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<class LLControlVariable> mIgnoreSetting;
bool mInvertSetting;
};
typedef boost::shared_ptr<LLNotificationForm> 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<std::string> 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<std::string>& 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<T (LLNotificationPtr)> 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)

View File

@@ -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<LLNotificationForm> 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<std::string> 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

View File

@@ -85,8 +85,20 @@ 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<std::string, LLTransTemplate > template_map_t;
static template_map_t sStringTemplates;

View File

@@ -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();
}