diff options
-rw-r--r-- | indra/llui/llnotifications.h | 2 | ||||
-rwxr-xr-x | indra/newview/CMakeLists.txt | 2 | ||||
-rw-r--r-- | indra/newview/llchannelmanager.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llnotificationstorage.cpp | 203 | ||||
-rw-r--r-- | indra/newview/llnotificationstorage.h | 34 | ||||
-rw-r--r-- | indra/newview/llpersistentnotificationstorage.cpp | 210 | ||||
-rw-r--r-- | indra/newview/llpersistentnotificationstorage.h | 63 |
7 files changed, 322 insertions, 194 deletions
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 056a316d40..8bb79b57e3 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -1026,7 +1026,7 @@ protected: // Stores only persistent notifications. // Class users can use connectChanged() to process persistent notifications -// (see LLNotificationStorage for example). +// (see LLPersistentNotificationStorage for example). class LLPersistentNotificationChannel : public LLNotificationChannel { LOG_CLASS(LLPersistentNotificationChannel); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index c9176d71fb..da1d96414b 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -448,6 +448,7 @@ set(viewer_SOURCE_FILES llpathfindingobject.cpp llpathfindingobjectlist.cpp llpathfindingpathtool.cpp + llpersistentnotificationstorage.cpp llphysicsmotion.cpp llphysicsshapebuilderutil.cpp llplacesinventorybridge.cpp @@ -1021,6 +1022,7 @@ set(viewer_HEADER_FILES llpathfindingobject.h llpathfindingobjectlist.h llpathfindingpathtool.h + llpersistentnotificationstorage.h llphysicsmotion.h llphysicsshapebuilderutil.h llplacesinventorybridge.h diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp index 987651fc80..79e2d376ea 100644 --- a/indra/newview/llchannelmanager.cpp +++ b/indra/newview/llchannelmanager.cpp @@ -29,7 +29,7 @@ #include "llchannelmanager.h" #include "llappviewer.h" -#include "llnotificationstorage.h" +#include "llpersistentnotificationstorage.h" #include "llviewercontrol.h" #include "llviewerwindow.h" #include "llrootview.h" diff --git a/indra/newview/llnotificationstorage.cpp b/indra/newview/llnotificationstorage.cpp index a31b95811e..d25a212059 100644 --- a/indra/newview/llnotificationstorage.cpp +++ b/indra/newview/llnotificationstorage.cpp @@ -25,207 +25,68 @@ */ #include "llviewerprecompiledheaders.h" // must be first include + #include "llnotificationstorage.h" -#include "llxmlnode.h" // for linux compilers +#include <string> -#include "llchannelmanager.h" -#include "llscreenchannel.h" -#include "llscriptfloater.h" +#include "llerror.h" +#include "llfile.h" +#include "llpointer.h" +#include "llsd.h" #include "llsdserialize.h" -#include "llviewermessage.h" - -////////////////////////////////////////////////////////////////////////// - -class LLResponderRegistry -{ -public: - - static void registerResponders(); - - static LLNotificationResponderInterface* createResponder(const std::string& notification_name, const LLSD& params); - -private: - - template<typename RESPONDER_TYPE> - static LLNotificationResponderInterface* create(const LLSD& params) - { - RESPONDER_TYPE* responder = new RESPONDER_TYPE(); - responder->fromLLSD(params); - return responder; - } - - typedef boost::function<LLNotificationResponderInterface* (const LLSD& params)> responder_constructor_t; - - static void add(const std::string& notification_name, const responder_constructor_t& ctr); - -private: - - typedef std::map<std::string, responder_constructor_t> build_map_t; - - static build_map_t sBuildMap; -}; -////////////////////////////////////////////////////////////////////////// -LLPersistentNotificationStorage::LLPersistentNotificationStorage() +LLNotificationStorage::LLNotificationStorage(std::string pFileName) + : mFileName(pFileName) { - mFileName = gDirUtilp->getExpandedFilename ( LL_PATH_PER_SL_ACCOUNT, "open_notifications.xml" ); } -bool LLPersistentNotificationStorage::onPersistentChannelChanged(const LLSD& payload) +LLNotificationStorage::~LLNotificationStorage() { - // we ignore "load" messages, but rewrite the persistence file on any other - const std::string sigtype = payload["sigtype"].asString(); - if ("load" != sigtype) - { - saveNotifications(); - } - return false; } -static LLFastTimer::DeclareTimer FTM_SAVE_NOTIFICATIONS("Save Notifications"); - -void LLPersistentNotificationStorage::saveNotifications() +bool LLNotificationStorage::writeNotifications(const LLSD& pNotificationData) const { - LLFastTimer _(FTM_SAVE_NOTIFICATIONS); - - llofstream notify_file(mFileName.c_str()); - if (!notify_file.is_open()) - { - llwarns << "Failed to open " << mFileName << llendl; - return; - } - LLSD output; - LLSD& data = output["data"]; + llofstream notifyFile(mFileName.c_str()); + bool didFileOpen = notifyFile.is_open(); - boost::intrusive_ptr<LLPersistentNotificationChannel> history_channel = boost::dynamic_pointer_cast<LLPersistentNotificationChannel>(LLNotifications::instance().getChannel("Persistent")); - if (!history_channel) + if (!didFileOpen) { - return; + LL_WARNS("LLNotificationStorage") << "Failed to open file '" << mFileName << "'" << LL_ENDL; } - - for ( std::vector<LLNotificationPtr>::iterator it = history_channel->beginHistory(), end_it = history_channel->endHistory(); - it != end_it; - ++it) + else { - LLNotificationPtr notification = *it; - - // After a notification was placed in Persist channel, it can become - // responded, expired or canceled - in this case we are should not save it - if(notification->isRespondedTo() || notification->isCancelled() - || notification->isExpired()) - { - continue; - } - - data.append(notification->asLLSD()); + LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter(); + formatter->format(pNotificationData, notifyFile, LLSDFormatter::OPTIONS_PRETTY); } - LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter(); - formatter->format(output, notify_file, LLSDFormatter::OPTIONS_PRETTY); + return didFileOpen; } -static LLFastTimer::DeclareTimer FTM_LOAD_NOTIFICATIONS("Load Notifications"); - -void LLPersistentNotificationStorage::loadNotifications() +bool LLNotificationStorage::readNotifications(LLSD& pNotificationData) const { - LLFastTimer _(FTM_LOAD_NOTIFICATIONS); - LLResponderRegistry::registerResponders(); + bool didFileRead; - LLNotifications::instance().getChannel("Persistent")-> - connectChanged(boost::bind(&LLPersistentNotificationStorage::onPersistentChannelChanged, this, _1)); + pNotificationData.clear(); - llifstream notify_file(mFileName.c_str()); - if (!notify_file.is_open()) + llifstream notifyFile(mFileName.c_str()); + didFileRead = notifyFile.is_open(); + if (!didFileRead) { - llwarns << "Failed to open " << mFileName << llendl; - return; + LL_WARNS("LLNotificationStorage") << "Failed to open file '" << mFileName << "'" << LL_ENDL; } - - LLSD input; - LLPointer<LLSDParser> parser = new LLSDXMLParser(); - if (parser->parse(notify_file, input, LLSDSerialize::SIZE_UNLIMITED) < 0) + else { - llwarns << "Failed to parse open notifications" << llendl; - return; - } - - if (input.isUndefined()) - { - return; - } - - LLSD& data = input["data"]; - if (data.isUndefined()) - { - return; - } - - using namespace LLNotificationsUI; - LLScreenChannel* notification_channel = dynamic_cast<LLScreenChannel*>(LLChannelManager::getInstance()-> - findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); - - LLNotifications& instance = LLNotifications::instance(); - - for (LLSD::array_const_iterator notification_it = data.beginArray(); - notification_it != data.endArray(); - ++notification_it) - { - LLSD notification_params = *notification_it; - LLNotificationPtr notification(new LLNotification(notification_params)); - - LLNotificationResponderPtr responder(LLResponderRegistry:: - createResponder(notification_params["name"], notification_params["responder"])); - notification->setResponseFunctor(responder); - - instance.add(notification); - - // hide script floaters so they don't confuse the user and don't overlap startup toast - LLScriptFloaterManager::getInstance()->setFloaterVisible(notification->getID(), false); - - if(notification_channel) + LLPointer<LLSDParser> parser = new LLSDXMLParser(); + didFileRead = (parser->parse(notifyFile, pNotificationData, LLSDSerialize::SIZE_UNLIMITED) >= 0); + if (!didFileRead) { - // hide saved toasts so they don't confuse the user - notification_channel->hideToast(notification->getID()); + LL_WARNS("LLNotificationStorage") << "Failed to parse open notifications from file '" << mFileName + << "'" << LL_ENDL; } } -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -LLResponderRegistry::build_map_t LLResponderRegistry::sBuildMap; - -void LLResponderRegistry::registerResponders() -{ - sBuildMap.clear(); - - add("ObjectGiveItem", &create<LLOfferInfo>); - add("UserGiveItem", &create<LLOfferInfo>); -} - -LLNotificationResponderInterface* LLResponderRegistry::createResponder(const std::string& notification_name, const LLSD& params) -{ - build_map_t::const_iterator it = sBuildMap.find(notification_name); - if(sBuildMap.end() == it) - { - return NULL; - } - responder_constructor_t ctr = it->second; - return ctr(params); + return didFileRead; } - -void LLResponderRegistry::add(const std::string& notification_name, const responder_constructor_t& ctr) -{ - if(sBuildMap.find(notification_name) != sBuildMap.end()) - { - llwarns << "Responder is already registered : " << notification_name << llendl; - llassert(!"Responder already registered"); - } - sBuildMap[notification_name] = ctr; -} - -// EOF diff --git a/indra/newview/llnotificationstorage.h b/indra/newview/llnotificationstorage.h index 8635c797c0..ab4da4e73f 100644 --- a/indra/newview/llnotificationstorage.h +++ b/indra/newview/llnotificationstorage.h @@ -27,32 +27,24 @@ #ifndef LL_NOTIFICATIONSTORAGE_H #define LL_NOTIFICATIONSTORAGE_H -#include "llnotifications.h" - -// Class that saves not responded(unread) notifications. -// Unread notifications are saved in open_notifications.xml in SL account folder -// -// Notifications that should be saved(if unread) are marked with persist="true" in notifications.xml -// Notifications using functor responders are saved automatically (see llviewermessage.cpp -// lure_callback_reg for example). -// Notifications using object responders(LLOfferInfo) need additional tuning. Responder object should -// be a) serializable(implement LLNotificationResponderInterface), -// b) registered with LLResponderRegistry (found in llnotificationstorage.cpp). -class LLPersistentNotificationStorage : public LLSingleton<LLPersistentNotificationStorage> -{ - LOG_CLASS(LLPersistentNotificationStorage); -public: +#include <string> - LLPersistentNotificationStorage(); +#include "llerror.h" - void saveNotifications(); +class LLSD; - void loadNotifications(); - -private: +class LLNotificationStorage +{ + LOG_CLASS(LLNotificationStorage); +public: + LLNotificationStorage(std::string pFileName); + ~LLNotificationStorage(); - bool onPersistentChannelChanged(const LLSD& payload); +protected: + bool writeNotifications(const LLSD& pNotificationData) const; + bool readNotifications(LLSD& pNotificationData) const; +private: std::string mFileName; }; diff --git a/indra/newview/llpersistentnotificationstorage.cpp b/indra/newview/llpersistentnotificationstorage.cpp new file mode 100644 index 0000000000..7aaad64fd7 --- /dev/null +++ b/indra/newview/llpersistentnotificationstorage.cpp @@ -0,0 +1,210 @@ +/** +* @file llpersistentnotificationstorage.cpp +* @brief Implementation of llpersistentnotificationstorage +* @author Stinson@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, 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$ +*/ + + +#include "llviewerprecompiledheaders.h" + +#include "llpersistentnotificationstorage.h" + +#include "llchannelmanager.h" +#include "llnotificationstorage.h" +#include "llscreenchannel.h" +#include "llscriptfloater.h" +#include "llviewermessage.h" + +class LLResponderRegistry +{ +public: + + static void registerResponders(); + + static LLNotificationResponderInterface* createResponder(const std::string& notification_name, const LLSD& params); + +protected: + +private: + template<typename RESPONDER_TYPE> + static LLNotificationResponderInterface* create(const LLSD& params) + { + RESPONDER_TYPE* responder = new RESPONDER_TYPE(); + responder->fromLLSD(params); + return responder; + } + + typedef boost::function<LLNotificationResponderInterface* (const LLSD& params)> responder_constructor_t; + + static void add(const std::string& notification_name, const responder_constructor_t& ctr); + + typedef std::map<std::string, responder_constructor_t> build_map_t; + + static build_map_t sBuildMap; +}; + +LLPersistentNotificationStorage::LLPersistentNotificationStorage() + : LLSingleton<LLPersistentNotificationStorage>() + , LLNotificationStorage(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "open_notifications.xml")) +{ +} + +LLPersistentNotificationStorage::~LLPersistentNotificationStorage() +{ +} + +static LLFastTimer::DeclareTimer FTM_SAVE_NOTIFICATIONS("Save Notifications"); + +void LLPersistentNotificationStorage::saveNotifications() +{ + LLFastTimer _(FTM_SAVE_NOTIFICATIONS); + + boost::intrusive_ptr<LLPersistentNotificationChannel> history_channel = boost::dynamic_pointer_cast<LLPersistentNotificationChannel>(LLNotifications::instance().getChannel("Persistent")); + if (!history_channel) + { + return; + } + + LLSD output = LLSD::emptyMap(); + LLSD& data = output["data"]; + + for ( std::vector<LLNotificationPtr>::iterator it = history_channel->beginHistory(), end_it = history_channel->endHistory(); + it != end_it; + ++it) + { + LLNotificationPtr notification = *it; + + // After a notification was placed in Persist channel, it can become + // responded, expired or canceled - in this case we are should not save it + if(notification->isRespondedTo() || notification->isCancelled() + || notification->isExpired()) + { + continue; + } + + data.append(notification->asLLSD()); + } + + writeNotifications(output); +} + +static LLFastTimer::DeclareTimer FTM_LOAD_NOTIFICATIONS("Load Notifications"); + +void LLPersistentNotificationStorage::loadNotifications() +{ + LLFastTimer _(FTM_LOAD_NOTIFICATIONS); + LLResponderRegistry::registerResponders(); + + LLNotifications::instance().getChannel("Persistent")-> + connectChanged(boost::bind(&LLPersistentNotificationStorage::onPersistentChannelChanged, this, _1)); + + LLSD input; + if (!readNotifications(input) ||input.isUndefined()) + { + return; + } + + LLSD& data = input["data"]; + if (data.isUndefined()) + { + return; + } + + using namespace LLNotificationsUI; + LLScreenChannel* notification_channel = dynamic_cast<LLScreenChannel*>(LLChannelManager::getInstance()-> + findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); + + LLNotifications& instance = LLNotifications::instance(); + + for (LLSD::array_const_iterator notification_it = data.beginArray(); + notification_it != data.endArray(); + ++notification_it) + { + LLSD notification_params = *notification_it; + LLNotificationPtr notification(new LLNotification(notification_params)); + + LLNotificationResponderPtr responder(LLResponderRegistry:: + createResponder(notification_params["name"], notification_params["responder"])); + notification->setResponseFunctor(responder); + + instance.add(notification); + + // hide script floaters so they don't confuse the user and don't overlap startup toast + LLScriptFloaterManager::getInstance()->setFloaterVisible(notification->getID(), false); + + if(notification_channel) + { + // hide saved toasts so they don't confuse the user + notification_channel->hideToast(notification->getID()); + } + } +} + +bool LLPersistentNotificationStorage::onPersistentChannelChanged(const LLSD& payload) +{ + // we ignore "load" messages, but rewrite the persistence file on any other + const std::string sigtype = payload["sigtype"].asString(); + if ("load" != sigtype) + { + saveNotifications(); + } + return false; +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +LLResponderRegistry::build_map_t LLResponderRegistry::sBuildMap; + +void LLResponderRegistry::registerResponders() +{ + sBuildMap.clear(); + + add("ObjectGiveItem", &create<LLOfferInfo>); + add("UserGiveItem", &create<LLOfferInfo>); +} + +LLNotificationResponderInterface* LLResponderRegistry::createResponder(const std::string& notification_name, const LLSD& params) +{ + build_map_t::const_iterator it = sBuildMap.find(notification_name); + if(sBuildMap.end() == it) + { + return NULL; + } + responder_constructor_t ctr = it->second; + return ctr(params); +} + +void LLResponderRegistry::add(const std::string& notification_name, const responder_constructor_t& ctr) +{ + if(sBuildMap.find(notification_name) != sBuildMap.end()) + { + llwarns << "Responder is already registered : " << notification_name << llendl; + llassert(!"Responder already registered"); + } + sBuildMap[notification_name] = ctr; +} + +// EOF diff --git a/indra/newview/llpersistentnotificationstorage.h b/indra/newview/llpersistentnotificationstorage.h new file mode 100644 index 0000000000..98a825d2c1 --- /dev/null +++ b/indra/newview/llpersistentnotificationstorage.h @@ -0,0 +1,63 @@ +/** +* @file llpersistentnotificationstorage.h +* @brief Header file for llpersistentnotificationstorage +* @author Stinson@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, 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_LLPERSISTENTNOTIFICATIONSTORAGE_H +#define LL_LLPERSISTENTNOTIFICATIONSTORAGE_H + +#include "llerror.h" +#include "llnotificationstorage.h" +#include "llsingleton.h" + +class LLSD; + +// Class that saves not responded(unread) notifications. +// Unread notifications are saved in open_notifications.xml in SL account folder +// +// Notifications that should be saved(if unread) are marked with persist="true" in notifications.xml +// Notifications using functor responders are saved automatically (see llviewermessage.cpp +// lure_callback_reg for example). +// Notifications using object responders(LLOfferInfo) need additional tuning. Responder object should +// be a) serializable(implement LLNotificationResponderInterface), +// b) registered with LLResponderRegistry (found in llpersistentnotificationstorage.cpp). + +class LLPersistentNotificationStorage : public LLSingleton<LLPersistentNotificationStorage>, public LLNotificationStorage +{ + LOG_CLASS(LLPersistentNotificationStorage); +public: + LLPersistentNotificationStorage(); + ~LLPersistentNotificationStorage(); + + void saveNotifications(); + void loadNotifications(); + +protected: + +private: + bool onPersistentChannelChanged(const LLSD& payload); +}; + +#endif // LL_LLPERSISTENTNOTIFICATIONSTORAGE_H + |