diff options
Diffstat (limited to 'indra/llui/llnotifications.h')
-rwxr-xr-x[-rw-r--r--] | indra/llui/llnotifications.h | 657 |
1 files changed, 410 insertions, 247 deletions
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 400491a154..3cf432f330 100644..100755 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -3,31 +3,25 @@ * @brief Non-UI manager and support for keeping a prioritized list of notifications * @author Q (with assistance from Richard and Coco) * -* $LicenseInfo:firstyear=2008&license=viewergpl$ -* -* Copyright (c) 2008-2009, Linden Research, Inc. -* +* $LicenseInfo:firstyear=2008&license=viewerlgpl$ * 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 +* 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. * -* 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 +* 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. * -* 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. +* 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 * -* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO -* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, -* COMPLETENESS OR PERFORMANCE. +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -93,19 +87,22 @@ #include <boost/shared_ptr.hpp> #include <boost/enable_shared_from_this.hpp> #include <boost/type_traits.hpp> +#include <boost/signals2.hpp> +#include <boost/range.hpp> -// we want to minimize external dependencies, but this one is important -#include "llsd.h" - -// and we need this to manage the notification callbacks #include "llevents.h" #include "llfunctorregistry.h" -#include "llpointer.h" #include "llinitparam.h" -#include "llnotificationslistener.h" +#include "llinstancetracker.h" +#include "llmortician.h" #include "llnotificationptr.h" +#include "llpointer.h" +#include "llrefcount.h" +#include "llsdparam.h" - +#include "llnotificationslistener.h" + +class LLAvatarName; typedef enum e_notification_priority { NOTIFICATION_PRIORITY_UNSPECIFIED, @@ -115,8 +112,28 @@ typedef enum e_notification_priority NOTIFICATION_PRIORITY_CRITICAL } ENotificationPriority; +struct NotificationPriorityValues : public LLInitParam::TypeValuesHelper<ENotificationPriority, NotificationPriorityValues> +{ + static void declareValues(); +}; + +class LLNotificationResponderInterface +{ +public: + LLNotificationResponderInterface(){}; + virtual ~LLNotificationResponderInterface(){}; + + virtual void handleRespond(const LLSD& notification, const LLSD& response) = 0; + + virtual LLSD asLLSD() = 0; + + virtual void fromLLSD(const LLSD& params) = 0; +}; + typedef boost::function<void (const LLSD&, const LLSD&)> LLNotificationResponder; +typedef boost::shared_ptr<LLNotificationResponderInterface> LLNotificationResponderPtr; + typedef LLFunctorRegistry<LLNotificationResponder> LLNotificationFunctorRegistry; typedef LLFunctorRegistration<LLNotificationResponder> LLNotificationFunctorRegistration; @@ -125,6 +142,7 @@ typedef LLFunctorRegistration<LLNotificationResponder> LLNotificationFunctorRegi class LLNotificationContext : public LLInstanceTracker<LLNotificationContext, LLUUID> { public: + LLNotificationContext() : LLInstanceTracker<LLNotificationContext, LLUUID>(LLUUID::generateNewID()) { } @@ -147,6 +165,70 @@ class LLNotificationForm LOG_CLASS(LLNotificationForm); public: + struct FormElementBase : public LLInitParam::Block<FormElementBase> + { + Optional<std::string> name; + Optional<bool> enabled; + + FormElementBase(); + }; + + struct FormIgnore : public LLInitParam::Block<FormIgnore, FormElementBase> + { + Optional<std::string> text; + Optional<bool> save_option; + Optional<std::string> control; + Optional<bool> invert_control; + + FormIgnore(); + }; + + struct FormButton : public LLInitParam::Block<FormButton, FormElementBase> + { + Mandatory<S32> index; + Mandatory<std::string> text; + Optional<std::string> ignore; + Optional<bool> is_default; + + Mandatory<std::string> type; + + FormButton(); + }; + + struct FormInput : public LLInitParam::Block<FormInput, FormElementBase> + { + Mandatory<std::string> type; + Optional<S32> width; + Optional<S32> max_length_chars; + Optional<std::string> text; + + Optional<std::string> value; + FormInput(); + }; + + struct FormElement : public LLInitParam::ChoiceBlock<FormElement> + { + Alternative<FormButton> button; + Alternative<FormInput> input; + + FormElement(); + }; + + struct FormElements : public LLInitParam::Block<FormElements> + { + Multiple<FormElement> elements; + FormElements(); + }; + + struct Params : public LLInitParam::Block<Params> + { + Optional<std::string> name; + Optional<FormIgnore> ignore; + Optional<FormElements> form_elements; + + Params(); + }; + typedef enum e_ignore_type { IGNORE_NO, @@ -156,112 +238,54 @@ public: } EIgnoreType; LLNotificationForm(); + LLNotificationForm(const LLNotificationForm&); LLNotificationForm(const LLSD& sd); - LLNotificationForm(const std::string& name, - const LLPointer<class LLXMLNode> xml_node); + LLNotificationForm(const std::string& name, const Params& p); + void fromLLSD(const LLSD& sd); LLSD asLLSD() const; S32 getNumElements() { return mFormData.size(); } LLSD getElement(S32 index) { return mFormData.get(index); } LLSD getElement(const std::string& element_name); - bool hasElement(const std::string& element_name); - void addElement(const std::string& type, const std::string& name, const LLSD& value = LLSD()); + void getElements(LLSD& elements, S32 offset = 0); + bool hasElement(const std::string& element_name) const; + bool getElementEnabled(const std::string& element_name) const; + void setElementEnabled(const std::string& element_name, bool enabled); + void addElement(const std::string& type, const std::string& name, const LLSD& value = LLSD(), bool enabled = true); void formatElements(const LLSD& substitutions); // 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; } private: - LLSD mFormData; - EIgnoreType mIgnore; - std::string mIgnoreMsg; + LLSD mFormData; + EIgnoreType mIgnore; + 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; - - U32 mURLOpenExternally; - //This is a flag that tells if the url needs to open externally dispite - //what the user setting is. - - // 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 typedef boost::shared_ptr<LLNotificationTemplate> LLNotificationTemplatePtr; + +struct LLNotificationVisibilityRule; + +typedef boost::shared_ptr<LLNotificationVisibilityRule> LLNotificationVisibilityRulePtr; + /** * @class LLNotification * @brief The object that expresses the details of a notification @@ -282,40 +306,52 @@ LOG_CLASS(LLNotification); friend class LLNotifications; public: + // parameter object used to instantiate a new notification struct Params : public LLInitParam::Block<Params> { friend class LLNotification; Mandatory<std::string> name; - - // optional - Optional<LLSD> substitutions; - Optional<LLSD> payload; - Optional<ENotificationPriority> priority; - Optional<LLSD> form_elements; - Optional<LLDate> time_stamp; + Optional<LLUUID> id; + Optional<LLSD> substitutions, + form_elements, + payload; + Optional<ENotificationPriority, NotificationPriorityValues> priority; + Optional<LLDate> time_stamp, + expiry; Optional<LLNotificationContext*> context; Optional<void*> responder; + Optional<bool> offer_from_agent; + Optional<bool> is_dnd; - struct Functor : public LLInitParam::Choice<Functor> + struct Functor : public LLInitParam::ChoiceBlock<Functor> { Alternative<std::string> name; Alternative<LLNotificationFunctorRegistry::ResponseFunctor> function; + Alternative<LLNotificationResponderPtr> responder; + Alternative<LLSD> responder_sd; Functor() - : name("functor_name"), - function("functor") + : name("responseFunctor"), + function("functor"), + responder("responder"), + responder_sd("responder_sd") {} }; Optional<Functor> functor; Params() : name("name"), + id("id"), priority("priority", NOTIFICATION_PRIORITY_UNSPECIFIED), - time_stamp("time_stamp"), + time_stamp("time"), payload("payload"), - form_elements("form_elements") + form_elements("form"), + substitutions("substitutions"), + expiry("expiry"), + offer_from_agent("offer_from_agent", false), + is_dnd("is_dnd", false) { time_stamp = LLDate::now(); responder = NULL; @@ -324,9 +360,13 @@ public: Params(const std::string& _name) : name("name"), priority("priority", NOTIFICATION_PRIORITY_UNSPECIFIED), - time_stamp("time_stamp"), + time_stamp("time"), payload("payload"), - form_elements("form_elements") + form_elements("form"), + substitutions("substitutions"), + expiry("expiry"), + offer_from_agent("offer_from_agent", false), + is_dnd("is_dnd", false) { functor.name = _name; name = _name; @@ -335,9 +375,11 @@ public: } }; + LLNotificationResponderPtr getResponderPtr() { return mResponder; } + private: - LLUUID mId; + const LLUUID mId; LLSD mPayload; LLSD mSubstitutions; LLDate mTimestamp; @@ -348,12 +390,14 @@ private: bool mIgnored; ENotificationPriority mPriority; LLNotificationFormPtr mForm; - void* mResponderObj; - bool mIsReusable; - + void* mResponderObj; // TODO - refactor/remove this field + LLNotificationResponderPtr mResponder; + bool mOfferFromAgent; + bool mIsDND; + // a reference to the template LLNotificationTemplatePtr mTemplatep; - + /* We want to be able to store and reload notifications so that they can survive a shutdown/restart of the client. So we can't simply pass in callbacks; @@ -373,25 +417,17 @@ private: void init(const std::string& template_name, const LLSD& form_elements); - LLNotification(const Params& p); - - // 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), 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); + LLNotification(const LLSDParamAdapter<Params>& p); void setResponseFunctor(std::string const &responseFunctorName); void setResponseFunctor(const LLNotificationFunctorRegistry::ResponseFunctor& cb); + void setResponseFunctor(const LLNotificationResponderPtr& responder); + typedef enum e_response_template_type { WITHOUT_DEFAULT_BUTTON, @@ -427,9 +463,15 @@ public: // ["time"] = time at which notification was generated; // ["expiry"] = time at which notification expires; // ["responseFunctor"] = name of registered functor that handles responses to notification; - LLSD asLLSD(); + LLSD asLLSD(bool excludeTemplateElements = false); + + const LLNotificationFormPtr getForm(); + void updateForm(const LLNotificationFormPtr& form); + + void repost(); void respond(const LLSD& sd); + void respondWithDefault(); void* getResponder() { return mResponderObj; } @@ -447,6 +489,13 @@ public: return mRespondedTo; } + bool isActive() const + { + return !isRespondedTo() + && !isCancelled() + && !isExpired(); + } + const LLSD& getResponse() { return mResponse; } bool isIgnored() const @@ -454,11 +503,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; @@ -479,30 +529,43 @@ public: return mTimestamp; } - std::string getType() const + bool getOfferFromAgent() const { - return (mTemplatep ? mTemplatep->mType : ""); + return mOfferFromAgent; } + bool isDND() const + { + return mIsDND; + } + + void setDND(const bool flag) + { + mIsDND = flag; + } + + std::string getType() const; std::string getMessage() const; + std::string getFooter() const; std::string getLabel() const; - std::string getURL() const; -// { -// return (mTemplatep ? mTemplatep->mURL : ""); -// } - - S32 getURLOption() const - { - return (mTemplatep ? mTemplatep->mURLOption : -1); - } - - S32 getURLOpenExternally() const + S32 getURLOption() const; + S32 getURLOpenExternally() const; + bool canLogToChat() const; + bool canLogToIM() const; + bool canShowToast() const; + bool hasFormElements() const; + void playSound(); + + typedef enum e_combine_behavior { - return(mTemplatep? mTemplatep->mURLOpenExternally : -1); - } + REPLACE_WITH_NEW, + KEEP_OLD, + CANCEL_OLD + + } ECombineBehavior; - const LLNotificationFormPtr getForm(); + ECombineBehavior getCombineBehavior() const; const LLDate getExpiration() const { @@ -519,10 +582,6 @@ public: return mId; } - bool isReusable() { return mIsReusable; } - - void setReusable(bool reusable) { mIsReusable = reusable; } - // comparing two notifications normally means comparing them by UUID (so we can look them // up quickly this way) bool operator<(const LLNotification& rhs) const @@ -570,7 +629,9 @@ public: std::string summarize() const; - bool hasUniquenessConstraints() const { return (mTemplatep ? mTemplatep->mUnique : false);} + bool hasUniquenessConstraints() const; + + bool matchesTag(const std::string& tag); virtual ~LLNotification() {} }; @@ -632,51 +693,24 @@ namespace LLNotificationFilters namespace LLNotificationComparators { - typedef enum e_direction { ORDER_DECREASING, ORDER_INCREASING } EDirection; - - // generic order functor that takes method or member variable reference - template<typename T> - struct orderBy + struct orderByUUID { - typedef boost::function<T (LLNotificationPtr)> field_t; - orderBy(field_t field, EDirection direction = ORDER_INCREASING) : mField(field), mDirection(direction) {} bool operator()(LLNotificationPtr lhs, LLNotificationPtr rhs) { - if (mDirection == ORDER_DECREASING) - { - return mField(lhs) > mField(rhs); - } - else - { - return mField(lhs) < mField(rhs); - } + return lhs->id() < rhs->id(); } - - field_t mField; - EDirection mDirection; - }; - - struct orderByUUID : public orderBy<const LLUUID&> - { - orderByUUID(EDirection direction = ORDER_INCREASING) : orderBy<const LLUUID&>(&LLNotification::id, direction) {} - }; - - struct orderByDate : public orderBy<const LLDate&> - { - orderByDate(EDirection direction = ORDER_INCREASING) : orderBy<const LLDate&>(&LLNotification::getDate, direction) {} }; }; typedef boost::function<bool (LLNotificationPtr)> LLNotificationFilter; -typedef boost::function<bool (LLNotificationPtr, LLNotificationPtr)> LLNotificationComparator; -typedef std::set<LLNotificationPtr, LLNotificationComparator> LLNotificationSet; +typedef std::set<LLNotificationPtr, LLNotificationComparators::orderByUUID> LLNotificationSet; typedef std::multimap<std::string, LLNotificationPtr> LLNotificationMap; // ======================================================== // Abstract base class (interface) for a channel; also used for the master container. // This lets us arrange channels into a call hierarchy. -// We maintain a heirarchy of notification channels; events are always started at the top +// We maintain a hierarchy of notification channels; events are always started at the top // and propagated through the hierarchy only if they pass a filter. // Any channel can be created with a parent. A null parent (empty string) means it's // tied to the root of the tree (the LLNotifications class itself). @@ -690,12 +724,14 @@ typedef std::multimap<std::string, LLNotificationPtr> LLNotificationMap; // all of the built-in tests should attach to the "Visible" channel // class LLNotificationChannelBase : - public LLEventTrackable + public LLEventTrackable, + public LLRefCount { LOG_CLASS(LLNotificationChannelBase); public: - LLNotificationChannelBase(LLNotificationFilter filter, LLNotificationComparator comp) : - mFilter(filter), mItems(comp) + LLNotificationChannelBase(LLNotificationFilter filter) + : mFilter(filter), + mItems() {} virtual ~LLNotificationChannelBase() {} // you can also connect to a Channel, so you can be notified of @@ -761,6 +797,9 @@ protected: virtual void onDelete(LLNotificationPtr p) {} virtual void onChange(LLNotificationPtr p) {} + virtual void onFilterPass(LLNotificationPtr p) {} + virtual void onFilterFail(LLNotificationPtr p) {} + bool updateItem(const LLSD& payload, LLNotificationPtr pNotification); LLNotificationFilter mFilter; }; @@ -770,63 +809,58 @@ protected: // destroy it, but if it becomes necessary to do so, the shared_ptr model // will ensure that we don't leak resources. class LLNotificationChannel; -typedef boost::shared_ptr<LLNotificationChannel> LLNotificationChannelPtr; +typedef boost::intrusive_ptr<LLNotificationChannel> LLNotificationChannelPtr; // manages a list of notifications // Note that if this is ever copied around, we might find ourselves with multiple copies // of a queue with notifications being added to different nonequivalent copies. So we -// make it inherit from boost::noncopyable, and then create a map of shared_ptr to manage it. -// -// NOTE: LLNotificationChannel is self-registering. The *correct* way to create one is to -// do something like: -// LLNotificationChannel::buildChannel("name", "parent"...); -// This returns an LLNotificationChannelPtr, which you can store, or -// you can then retrieve the channel by using the registry: -// LLNotifications::instance().getChannel("name")... +// make it inherit from boost::noncopyable, and then create a map of LLPointer to manage it. // class LLNotificationChannel : boost::noncopyable, - public LLNotificationChannelBase + public LLNotificationChannelBase, + public LLInstanceTracker<LLNotificationChannel, std::string> { LOG_CLASS(LLNotificationChannel); public: + // Notification Channels have a filter, which determines which notifications + // will be added to this channel. + // Channel filters cannot change. + struct Params : public LLInitParam::Block<Params> + { + Mandatory<std::string> name; + Optional<LLNotificationFilter> filter; + Multiple<std::string> sources; + }; + + LLNotificationChannel(const Params& p = Params()); + LLNotificationChannel(const std::string& name, const std::string& parent, LLNotificationFilter filter); + virtual ~LLNotificationChannel() {} typedef LLNotificationSet::iterator Iterator; std::string getName() const { return mName; } - std::string getParentChannelName() { return mParent; } + typedef std::vector<std::string>::const_iterator parents_iter; + boost::iterator_range<parents_iter> getParents() const + { + return boost::iterator_range<parents_iter>(mParents); + } + + void connectToChannel(const std::string& channel_name); bool isEmpty() const; + S32 size() const; Iterator begin(); Iterator end(); - - // Channels have a comparator to control sort order; - // the default sorts by arrival date - void setComparator(LLNotificationComparator comparator); + size_t size(); std::string summarize(); - // factory method for constructing these channels; since they're self-registering, - // we want to make sure that you can't use new to make them - static LLNotificationChannelPtr buildChannel(const std::string& name, const std::string& parent, - LLNotificationFilter filter=LLNotificationFilters::includeEverything, - LLNotificationComparator comparator=LLNotificationComparators::orderByUUID()); - -protected: - // Notification Channels have a filter, which determines which notifications - // will be added to this channel. - // Channel filters cannot change. - // Channels have a protected constructor so you can't make smart pointers that don't - // come from our internal reference; call NotificationChannel::build(args) - LLNotificationChannel(const std::string& name, const std::string& parent, - LLNotificationFilter filter, LLNotificationComparator comparator); - private: std::string mName; - std::string mParent; - LLNotificationComparator mComparator; + std::vector<std::string> mParents; }; // An interface class to provide a clean linker seam to the LLNotifications class. @@ -849,10 +883,21 @@ class LLNotifications : friend class LLSingleton<LLNotifications>; public: - // load notification descriptions from file; + + // Needed to clear up RefCounted things prior to actual destruction + // as the singleton nature of the class makes them do "bad things" + // on at least Mac, if not all 3 platforms + // + void clear(); + + // load all notification descriptions from file + // calling more than once will overwrite existing templates + // but never delete a template + bool loadTemplates(); + + // load visibility rules from file; // OK to call more than once because it will reload - bool loadTemplates(); - LLPointer<class LLXMLNode> checkForXMLTemplate(LLPointer<class LLXMLNode> item); + bool loadVisibilityRules(); // Add a simple notification (from XUI) void addFromCallback(const LLSD& name); @@ -874,6 +919,7 @@ public: void add(const LLNotificationPtr pNotif); void cancel(LLNotificationPtr pNotif); + void cancelByName(const std::string& name); void update(const LLNotificationPtr pNotif); LLNotificationPtr find(LLUUID uuid); @@ -897,17 +943,13 @@ public: // test for existence bool templateExists(const std::string& name); - // useful if you're reloading the file - void clearTemplates(); // erase all templates + typedef std::list<LLNotificationVisibilityRulePtr> VisibilityRuleList; + void forceResponse(const LLNotification::Params& params, S32 option); void createDefaultChannels(); - typedef std::map<std::string, LLNotificationChannelPtr> ChannelMap; - ChannelMap mChannels; - - void addChannel(LLNotificationChannelPtr pChan); LLNotificationChannelPtr getChannel(const std::string& channelName); std::string getGlobalString(const std::string& key) const; @@ -915,6 +957,8 @@ public: void setIgnoreAllNotifications(bool ignore); bool getIgnoreAllNotifications(); + bool isVisibleByRules(LLNotificationPtr pNotification); + private: // we're a singleton, so we don't have a public constructor LLNotifications(); @@ -930,15 +974,12 @@ private: LLNotificationChannelPtr pHistoryChannel; LLNotificationChannelPtr pExpirationChannel; - // put your template in - bool addTemplate(const std::string& name, LLNotificationTemplatePtr theTemplate); TemplateMap mTemplates; + VisibilityRuleList mVisibilityRules; + std::string mFileName; - typedef std::map<std::string, LLPointer<class LLXMLNode> > XMLTemplateMap; - XMLTemplateMap mXmlTemplates; - LLNotificationMap mUniqueNotifications; typedef std::map<std::string, std::string> GlobalStringMap; @@ -946,9 +987,131 @@ private: bool mIgnoreAllNotifications; - boost::scoped_ptr<LLNotificationsListener> mListener; + boost::scoped_ptr<LLNotificationsListener> mListener; + + std::vector<LLNotificationChannelPtr> mDefaultChannels; +}; + +/** + * Abstract class for postponed notifications. + * Provides possibility to add notification after specified by id avatar or group will be + * received from cache name. The object of this type automatically well be deleted + * by cleanup method after respond will be received from cache name. + * + * To add custom postponed notification to the notification system client should: + * 1 create class derived from LLPostponedNotification; + * 2 call LLPostponedNotification::add method; + */ +class LLPostponedNotification : public LLMortician +{ +public: + /** + * Performs hooking cache name callback which will add notification to notifications system. + * Type of added notification should be specified by template parameter T + * and non-private derived from LLPostponedNotification class, + * otherwise compilation error will occur. + */ + template<class T> + static void add(const LLNotification::Params& params, + const LLUUID& id, bool is_group) + { + // upcast T to the base type to restrict T derivation from LLPostponedNotification + LLPostponedNotification* thiz = new T(); + thiz->mParams = params; + + // Avoid header file dependency on llcachename.h + thiz->lookupName(id, is_group); + } + +private: + void lookupName(const LLUUID& id, bool is_group); + // only used for groups + void onGroupNameCache(const LLUUID& id, const std::string& full_name, bool is_group); + // only used for avatars + void fetchAvatarName(const LLUUID& id); + void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); + // used for both group and avatar names + void finalizeName(const std::string& name); + + void cleanup() + { + die(); + } + +protected: + LLPostponedNotification() + : mParams(), + mName(), + mAvatarNameCacheConnection() + {} + + virtual ~LLPostponedNotification() + { + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + } + + /** + * Abstract method provides possibility to modify notification parameters and + * will be called after cache name retrieve information about avatar or group + * and before notification will be added to the notification system. + */ + virtual void modifyNotificationParams() = 0; + + LLNotification::Params mParams; + std::string mName; + boost::signals2::connection mAvatarNameCacheConnection; }; +// Stores only persistent notifications. +// Class users can use connectChanged() to process persistent notifications +// (see LLPersistentNotificationStorage for example). +class LLPersistentNotificationChannel : public LLNotificationChannel +{ + LOG_CLASS(LLPersistentNotificationChannel); +public: + LLPersistentNotificationChannel() + : LLNotificationChannel("Persistent", "Visible", ¬ificationFilter) + {} + + typedef std::vector<LLNotificationPtr> history_list_t; + history_list_t::iterator beginHistory() { sortHistory(); return mHistory.begin(); } + history_list_t::iterator endHistory() { return mHistory.end(); } + +private: + struct sortByTime + { + S32 operator ()(const LLNotificationPtr& a, const LLNotificationPtr& b) + { + return a->getDate() < b->getDate(); + } + }; + + void sortHistory() + { + std::sort(mHistory.begin(), mHistory.end(), sortByTime()); + } + + // The channel gets all persistent notifications except those that have been canceled + static bool notificationFilter(LLNotificationPtr pNotification) + { + bool handle_notification = false; + + handle_notification = pNotification->isPersistent() + && !pNotification->isCancelled(); + + return handle_notification; + } + + void onAdd(LLNotificationPtr p) + { + mHistory.push_back(p); + } + + std::vector<LLNotificationPtr> mHistory; +}; #endif//LL_LLNOTIFICATIONS_H |