Automated merge with ssh://hg.lindenlab.com/viewer/viewer-2-0/
commit
6ed6bed5ac
|
|
@ -10,10 +10,10 @@
|
|||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llnotificationslistener.h"
|
||||
|
||||
#include "llnotifications.h"
|
||||
#include "llsd.h"
|
||||
#include "llui.h"
|
||||
|
||||
LLNotificationsListener::LLNotificationsListener(LLNotifications & notifications) :
|
||||
LLEventAPI("LLNotifications",
|
||||
|
|
@ -24,6 +24,47 @@ LLNotificationsListener::LLNotificationsListener(LLNotifications & notifications
|
|||
"Add a notification with specified [\"name\"], [\"substitutions\"] and [\"payload\"].\n"
|
||||
"If optional [\"reply\"] specified, arrange to send user response on that LLEventPump.",
|
||||
&LLNotificationsListener::requestAdd);
|
||||
add("listChannels",
|
||||
"Post to [\"reply\"] a map of info on existing channels",
|
||||
&LLNotificationsListener::listChannels,
|
||||
LLSD().with("reply", LLSD()));
|
||||
add("listChannelNotifications",
|
||||
"Post to [\"reply\"] an array of info on notifications in channel [\"channel\"]",
|
||||
&LLNotificationsListener::listChannelNotifications,
|
||||
LLSD().with("reply", LLSD()).with("channel", LLSD()));
|
||||
add("respond",
|
||||
"Respond to notification [\"uuid\"] with data in [\"response\"]",
|
||||
&LLNotificationsListener::respond,
|
||||
LLSD().with("uuid", LLSD()));
|
||||
add("cancel",
|
||||
"Cancel notification [\"uuid\"]",
|
||||
&LLNotificationsListener::cancel,
|
||||
LLSD().with("uuid", LLSD()));
|
||||
add("ignore",
|
||||
"Ignore future notification [\"name\"]\n"
|
||||
"(from <notification name= > in notifications.xml)\n"
|
||||
"according to boolean [\"ignore\"].\n"
|
||||
"If [\"name\"] is omitted or undefined, [un]ignore all future notifications.\n"
|
||||
"Note that ignored notifications are not forwarded unless intercepted before\n"
|
||||
"the \"Ignore\" channel.",
|
||||
&LLNotificationsListener::ignore);
|
||||
add("forward",
|
||||
"Forward to [\"pump\"] future notifications on channel [\"channel\"]\n"
|
||||
"according to boolean [\"forward\"]. When enabled, only types matching\n"
|
||||
"[\"types\"] are forwarded, as follows:\n"
|
||||
"omitted or undefined: forward all notifications\n"
|
||||
"string: forward only the specific named [sig]type\n"
|
||||
"array of string: forward any notification matching any named [sig]type.\n"
|
||||
"When boolean [\"respond\"] is true, we auto-respond to each forwarded\n"
|
||||
"notification.",
|
||||
&LLNotificationsListener::forward,
|
||||
LLSD().with("channel", LLSD()));
|
||||
}
|
||||
|
||||
// This is here in the .cpp file so we don't need the definition of class
|
||||
// Forwarder in the header file.
|
||||
LLNotificationsListener::~LLNotificationsListener()
|
||||
{
|
||||
}
|
||||
|
||||
void LLNotificationsListener::requestAdd(const LLSD& event_data) const
|
||||
|
|
@ -57,3 +98,227 @@ void LLNotificationsListener::NotificationResponder(const std::string& reply_pum
|
|||
reponse_event["response"] = response;
|
||||
LLEventPumps::getInstance()->obtain(reply_pump).post(reponse_event);
|
||||
}
|
||||
|
||||
void LLNotificationsListener::listChannels(const LLSD& params) const
|
||||
{
|
||||
LLReqID reqID(params);
|
||||
LLSD response(reqID.makeResponse());
|
||||
for (LLNotifications::ChannelMap::const_iterator cmi(mNotifications.mChannels.begin()),
|
||||
cmend(mNotifications.mChannels.end());
|
||||
cmi != cmend; ++cmi)
|
||||
{
|
||||
LLSD channelInfo;
|
||||
channelInfo["parent"] = cmi->second->getParentChannelName();
|
||||
response[cmi->first] = channelInfo;
|
||||
}
|
||||
LLEventPumps::instance().obtain(params["reply"]).post(response);
|
||||
}
|
||||
|
||||
void LLNotificationsListener::listChannelNotifications(const LLSD& params) const
|
||||
{
|
||||
LLReqID reqID(params);
|
||||
LLSD response(reqID.makeResponse());
|
||||
LLNotificationChannelPtr channel(mNotifications.getChannel(params["channel"]));
|
||||
if (channel)
|
||||
{
|
||||
LLSD notifications(LLSD::emptyArray());
|
||||
for (LLNotificationChannel::Iterator ni(channel->begin()), nend(channel->end());
|
||||
ni != nend; ++ni)
|
||||
{
|
||||
notifications.append(asLLSD(*ni));
|
||||
}
|
||||
response["notifications"] = notifications;
|
||||
}
|
||||
LLEventPumps::instance().obtain(params["reply"]).post(response);
|
||||
}
|
||||
|
||||
void LLNotificationsListener::respond(const LLSD& params) const
|
||||
{
|
||||
LLNotificationPtr notification(mNotifications.find(params["uuid"]));
|
||||
if (notification)
|
||||
{
|
||||
notification->respond(params["response"]);
|
||||
}
|
||||
}
|
||||
|
||||
void LLNotificationsListener::cancel(const LLSD& params) const
|
||||
{
|
||||
LLNotificationPtr notification(mNotifications.find(params["uuid"]));
|
||||
if (notification)
|
||||
{
|
||||
mNotifications.cancel(notification);
|
||||
}
|
||||
}
|
||||
|
||||
void LLNotificationsListener::ignore(const LLSD& params) const
|
||||
{
|
||||
// Calling a method named "ignore", but omitting its "ignore" Boolean
|
||||
// argument, should by default cause something to be ignored. Explicitly
|
||||
// pass ["ignore"] = false to cancel ignore.
|
||||
bool ignore = true;
|
||||
if (params.has("ignore"))
|
||||
{
|
||||
ignore = params["ignore"].asBoolean();
|
||||
}
|
||||
// This method can be used to affect either a single notification name or
|
||||
// all future notifications. The two use substantially different mechanisms.
|
||||
if (params["name"].isDefined())
|
||||
{
|
||||
// ["name"] was passed: ignore just that notification
|
||||
LLUI::sSettingGroups["ignores"]->setBOOL(params["name"], ignore);
|
||||
}
|
||||
else
|
||||
{
|
||||
// no ["name"]: ignore all future notifications
|
||||
mNotifications.setIgnoreAllNotifications(ignore);
|
||||
}
|
||||
}
|
||||
|
||||
class LLNotificationsListener::Forwarder: public LLEventTrackable
|
||||
{
|
||||
LOG_CLASS(LLNotificationsListener::Forwarder);
|
||||
public:
|
||||
Forwarder(LLNotifications& llnotifications, const std::string& channel):
|
||||
mNotifications(llnotifications),
|
||||
mRespond(false)
|
||||
{
|
||||
// Connect to the specified channel on construction. Because
|
||||
// LLEventTrackable is a base, we should automatically disconnect when
|
||||
// destroyed.
|
||||
LLNotificationChannelPtr channelptr(llnotifications.getChannel(channel));
|
||||
if (channelptr)
|
||||
{
|
||||
// Try connecting at the front of the 'changed' signal. That way
|
||||
// we shouldn't get starved by preceding listeners.
|
||||
channelptr->connectAtFrontChanged(boost::bind(&Forwarder::handle, this, _1));
|
||||
}
|
||||
}
|
||||
|
||||
void setPumpName(const std::string& name) { mPumpName = name; }
|
||||
void setTypes(const LLSD& types) { mTypes = types; }
|
||||
void setRespond(bool respond) { mRespond = respond; }
|
||||
|
||||
private:
|
||||
bool handle(const LLSD& notification) const;
|
||||
bool matchType(const LLSD& filter, const std::string& type) const;
|
||||
|
||||
LLNotifications& mNotifications;
|
||||
std::string mPumpName;
|
||||
LLSD mTypes;
|
||||
bool mRespond;
|
||||
};
|
||||
|
||||
void LLNotificationsListener::forward(const LLSD& params)
|
||||
{
|
||||
std::string channel(params["channel"]);
|
||||
// First decide whether we're supposed to start forwarding or stop it.
|
||||
// Default to true.
|
||||
bool forward = true;
|
||||
if (params.has("forward"))
|
||||
{
|
||||
forward = params["forward"].asBoolean();
|
||||
}
|
||||
if (! forward)
|
||||
{
|
||||
// This is a request to stop forwarding notifications on the specified
|
||||
// channel. The rest of the params don't matter.
|
||||
// Because mForwarders contains scoped_ptrs, erasing the map entry
|
||||
// DOES delete the heap Forwarder object. Because Forwarder derives
|
||||
// from LLEventTrackable, destroying it disconnects it from the
|
||||
// channel.
|
||||
mForwarders.erase(channel);
|
||||
return;
|
||||
}
|
||||
// From here on, we know we're being asked to start (or modify) forwarding
|
||||
// on the specified channel. Find or create an appropriate Forwarder.
|
||||
ForwarderMap::iterator
|
||||
entry(mForwarders.insert(ForwarderMap::value_type(channel, ForwarderMap::mapped_type())).first);
|
||||
if (! entry->second)
|
||||
{
|
||||
entry->second.reset(new Forwarder(mNotifications, channel));
|
||||
}
|
||||
// Now, whether this Forwarder is brand-new or not, update it with the new
|
||||
// request info.
|
||||
Forwarder& fwd(*entry->second);
|
||||
fwd.setPumpName(params["pump"]);
|
||||
fwd.setTypes(params["types"]);
|
||||
fwd.setRespond(params["respond"]);
|
||||
}
|
||||
|
||||
bool LLNotificationsListener::Forwarder::handle(const LLSD& notification) const
|
||||
{
|
||||
LL_INFOS("LLNotificationsListener") << "handle(" << notification << ")" << LL_ENDL;
|
||||
if (notification["sigtype"].asString() == "delete")
|
||||
{
|
||||
LL_INFOS("LLNotificationsListener") << "ignoring delete" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
LLNotificationPtr note(mNotifications.find(notification["id"]));
|
||||
if (! note)
|
||||
{
|
||||
LL_INFOS("LLNotificationsListener") << notification["id"] << " not found" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
if (! matchType(mTypes, note->getType()))
|
||||
{
|
||||
LL_INFOS("LLNotificationsListener") << "didn't match types " << mTypes << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
LL_INFOS("LLNotificationsListener") << "sending via '" << mPumpName << "'" << LL_ENDL;
|
||||
// This is a notification we care about. Forward it through specified
|
||||
// LLEventPump.
|
||||
LLEventPumps::instance().obtain(mPumpName).post(asLLSD(note));
|
||||
// Are we also being asked to auto-respond?
|
||||
if (mRespond)
|
||||
{
|
||||
LL_INFOS("LLNotificationsListener") << "should respond" << LL_ENDL;
|
||||
note->respond(LLSD::emptyMap());
|
||||
// Did that succeed in removing the notification? Only cancel() if
|
||||
// it's still around -- otherwise we get an LL_ERRS crash!
|
||||
note = mNotifications.find(notification["id"]);
|
||||
if (note)
|
||||
{
|
||||
LL_INFOS("LLNotificationsListener") << "respond() didn't clear, canceling" << LL_ENDL;
|
||||
mNotifications.cancel(note);
|
||||
}
|
||||
}
|
||||
return false; // let other listeners get same notification
|
||||
}
|
||||
|
||||
bool LLNotificationsListener::Forwarder::matchType(const LLSD& filter, const std::string& type) const
|
||||
{
|
||||
// Decide whether this notification matches filter:
|
||||
// undefined: forward all notifications
|
||||
if (filter.isUndefined())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// array of string: forward any notification matching any named type
|
||||
if (filter.isArray())
|
||||
{
|
||||
for (LLSD::array_const_iterator ti(filter.beginArray()), tend(filter.endArray());
|
||||
ti != tend; ++ti)
|
||||
{
|
||||
if (ti->asString() == type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Didn't match any entry in the array
|
||||
return false;
|
||||
}
|
||||
// string: forward only the specific named type
|
||||
return (filter.asString() == type);
|
||||
}
|
||||
|
||||
LLSD LLNotificationsListener::asLLSD(LLNotificationPtr note)
|
||||
{
|
||||
LLSD notificationInfo(note->asLLSD());
|
||||
// For some reason the following aren't included in asLLSD().
|
||||
notificationInfo["summary"] = note->summarize();
|
||||
notificationInfo["id"] = note->id();
|
||||
notificationInfo["type"] = note->getType();
|
||||
notificationInfo["message"] = note->getMessage();
|
||||
notificationInfo["label"] = note->getLabel();
|
||||
return notificationInfo;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,10 @@
|
|||
#define LL_LLNOTIFICATIONSLISTENER_H
|
||||
|
||||
#include "lleventapi.h"
|
||||
#include "llnotificationptr.h"
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
class LLNotifications;
|
||||
class LLSD;
|
||||
|
|
@ -21,13 +25,27 @@ class LLNotificationsListener : public LLEventAPI
|
|||
{
|
||||
public:
|
||||
LLNotificationsListener(LLNotifications & notifications);
|
||||
|
||||
void requestAdd(LLSD const & event_data) const;
|
||||
~LLNotificationsListener();
|
||||
|
||||
private:
|
||||
void requestAdd(LLSD const & event_data) const;
|
||||
|
||||
void NotificationResponder(const std::string& replypump,
|
||||
const LLSD& notification,
|
||||
const LLSD& response) const;
|
||||
|
||||
void listChannels(const LLSD& params) const;
|
||||
void listChannelNotifications(const LLSD& params) const;
|
||||
void respond(const LLSD& params) const;
|
||||
void cancel(const LLSD& params) const;
|
||||
void ignore(const LLSD& params) const;
|
||||
void forward(const LLSD& params);
|
||||
|
||||
static LLSD asLLSD(LLNotificationPtr);
|
||||
|
||||
class Forwarder;
|
||||
typedef std::map<std::string, boost::shared_ptr<Forwarder> > ForwarderMap;
|
||||
ForwarderMap mForwarders;
|
||||
LLNotifications & mNotifications;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#include "llfloater.h"
|
||||
#include "llui.h"
|
||||
#include "llnotificationptr.h"
|
||||
#include "llerror.h"
|
||||
|
||||
class LLButton;
|
||||
class LLCheckBoxCtrl;
|
||||
|
|
@ -53,6 +54,7 @@ class LLLineEditor;
|
|||
class LLToastAlertPanel
|
||||
: public LLToastPanel
|
||||
{
|
||||
LOG_CLASS(LLToastAlertPanel);
|
||||
public:
|
||||
typedef bool (*display_callback_t)(S32 modal);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue