From 5df9d52d48b56a5d8f36a45ced0393c99473f536 Mon Sep 17 00:00:00 2001 From: William Todd Stinson Date: Wed, 12 Dec 2012 18:49:07 -0800 Subject: CHUI-499: Refactoring the persistent notification storage so that I can reuse the functionality for do-not-disturb mode. --- indra/newview/llpersistentnotificationstorage.cpp | 210 ++++++++++++++++++++++ 1 file changed, 210 insertions(+) create mode 100644 indra/newview/llpersistentnotificationstorage.cpp (limited to 'indra/newview/llpersistentnotificationstorage.cpp') 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 + static LLNotificationResponderInterface* create(const LLSD& params) + { + RESPONDER_TYPE* responder = new RESPONDER_TYPE(); + responder->fromLLSD(params); + return responder; + } + + typedef boost::function responder_constructor_t; + + static void add(const std::string& notification_name, const responder_constructor_t& ctr); + + typedef std::map build_map_t; + + static build_map_t sBuildMap; +}; + +LLPersistentNotificationStorage::LLPersistentNotificationStorage() + : LLSingleton() + , 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 history_channel = boost::dynamic_pointer_cast(LLNotifications::instance().getChannel("Persistent")); + if (!history_channel) + { + return; + } + + LLSD output = LLSD::emptyMap(); + LLSD& data = output["data"]; + + for ( std::vector::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(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); + add("UserGiveItem", &create); +} + +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 -- cgit v1.3 From 6b9ead91459d702727b54ab7e51614c2d5959f5f Mon Sep 17 00:00:00 2001 From: William Todd Stinson Date: Tue, 18 Dec 2012 23:07:27 -0800 Subject: CHUI-499: Refactoring the LLPersistentNotificationStorage implementation for shared usage with the new LLDoNotDisturbNotificationStorage class. --- indra/newview/llnotificationstorage.cpp | 69 +++++++++++++++++++++++ indra/newview/llnotificationstorage.h | 3 + indra/newview/llpersistentnotificationstorage.cpp | 67 +--------------------- 3 files changed, 73 insertions(+), 66 deletions(-) (limited to 'indra/newview/llpersistentnotificationstorage.cpp') diff --git a/indra/newview/llnotificationstorage.cpp b/indra/newview/llnotificationstorage.cpp index d25a212059..4746e4bbd4 100644 --- a/indra/newview/llnotificationstorage.cpp +++ b/indra/newview/llnotificationstorage.cpp @@ -29,14 +29,39 @@ #include "llnotificationstorage.h" #include +#include #include "llerror.h" #include "llfile.h" +#include "llnotifications.h" #include "llpointer.h" #include "llsd.h" #include "llsdserialize.h" +#include "llsingleton.h" +#include "llviewermessage.h" +class LLResponderRegistry : public LLSingleton +{ +public: + LLResponderRegistry(); + ~LLResponderRegistry(); + + LLNotificationResponderInterface* createResponder(const std::string& pNotificationName, const LLSD& pParams); + +protected: + +private: + template static LLNotificationResponderInterface* create(const LLSD& pParams); + + typedef boost::function responder_constructor_t; + + void add(const std::string& pNotificationName, const responder_constructor_t& pConstructor); + + typedef std::map build_map_t; + build_map_t mBuildMap; +}; + LLNotificationStorage::LLNotificationStorage(std::string pFileName) : mFileName(pFileName) { @@ -90,3 +115,47 @@ bool LLNotificationStorage::readNotifications(LLSD& pNotificationData) const return didFileRead; } + +LLNotificationResponderInterface* LLNotificationStorage::createResponder(const std::string& pNotificationName, const LLSD& pParams) const +{ + return LLResponderRegistry::getInstance()->createResponder(pNotificationName, pParams); +} + +LLResponderRegistry::LLResponderRegistry() + : LLSingleton() + , mBuildMap() +{ + add("ObjectGiveItem", &create); + add("UserGiveItem", &create); +} + +LLResponderRegistry::~LLResponderRegistry() +{ +} + +LLNotificationResponderInterface* LLResponderRegistry::createResponder(const std::string& pNotificationName, const LLSD& pParams) +{ + build_map_t::const_iterator it = mBuildMap.find(pNotificationName); + if(mBuildMap.end() == it) + { + return NULL; + } + responder_constructor_t ctr = it->second; + return ctr(pParams); +} + +template LLNotificationResponderInterface* LLResponderRegistry::create(const LLSD& pParams) +{ + RESPONDER_TYPE* responder = new RESPONDER_TYPE(); + responder->fromLLSD(pParams); + return responder; +} + +void LLResponderRegistry::add(const std::string& pNotificationName, const responder_constructor_t& pConstructor) +{ + if (mBuildMap.find(pNotificationName) != mBuildMap.end()) + { + LL_ERRS("LLResponderRegistry") << "Responder is already registered : " << pNotificationName << LL_ENDL; + } + mBuildMap.insert(std::make_pair(pNotificationName, pConstructor)); +} diff --git a/indra/newview/llnotificationstorage.h b/indra/newview/llnotificationstorage.h index ab4da4e73f..7aabf7d09e 100644 --- a/indra/newview/llnotificationstorage.h +++ b/indra/newview/llnotificationstorage.h @@ -31,6 +31,7 @@ #include "llerror.h" +class LLNotificationResponderInterface; class LLSD; class LLNotificationStorage @@ -44,6 +45,8 @@ protected: bool writeNotifications(const LLSD& pNotificationData) const; bool readNotifications(LLSD& pNotificationData) const; + LLNotificationResponderInterface* createResponder(const std::string& pNotificationName, const LLSD& pParams) const; + private: std::string mFileName; }; diff --git a/indra/newview/llpersistentnotificationstorage.cpp b/indra/newview/llpersistentnotificationstorage.cpp index 7aaad64fd7..224aaa2146 100644 --- a/indra/newview/llpersistentnotificationstorage.cpp +++ b/indra/newview/llpersistentnotificationstorage.cpp @@ -36,34 +36,6 @@ #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 - static LLNotificationResponderInterface* create(const LLSD& params) - { - RESPONDER_TYPE* responder = new RESPONDER_TYPE(); - responder->fromLLSD(params); - return responder; - } - - typedef boost::function responder_constructor_t; - - static void add(const std::string& notification_name, const responder_constructor_t& ctr); - - typedef std::map build_map_t; - - static build_map_t sBuildMap; -}; - LLPersistentNotificationStorage::LLPersistentNotificationStorage() : LLSingleton() , LLNotificationStorage(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "open_notifications.xml")) @@ -114,7 +86,6 @@ 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)); @@ -144,8 +115,7 @@ void LLPersistentNotificationStorage::loadNotifications() LLSD notification_params = *notification_it; LLNotificationPtr notification(new LLNotification(notification_params)); - LLNotificationResponderPtr responder(LLResponderRegistry:: - createResponder(notification_params["name"], notification_params["responder"])); + LLNotificationResponderPtr responder(createResponder(notification_params["name"], notification_params["responder"])); notification->setResponseFunctor(responder); instance.add(notification); @@ -172,39 +142,4 @@ bool LLPersistentNotificationStorage::onPersistentChannelChanged(const LLSD& pay return false; } -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLResponderRegistry::build_map_t LLResponderRegistry::sBuildMap; - -void LLResponderRegistry::registerResponders() -{ - sBuildMap.clear(); - - add("ObjectGiveItem", &create); - add("UserGiveItem", &create); -} - -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 -- cgit v1.3 From c55e4a61242cd3cf94e0a28398fd33a4eb8ea683 Mon Sep 17 00:00:00 2001 From: Cho Date: Fri, 8 Feb 2013 02:03:28 +0000 Subject: CHUI-703 FIX Notification buttons: "Join","Decline","Info" are duplicated after relogin while group invitation Changed LLPersistentNotificationStorage::saveNotification() to use notification->asLLSD(true) to skip duplicates Changed LLDockControl::mDockWidget to be a LLHandle instead of a LLView* to fix crash (from accessing deleted LLView) --- indra/llui/lldockcontrol.cpp | 31 +++++++++++++---------- indra/llui/lldockcontrol.h | 4 +-- indra/newview/llpersistentnotificationstorage.cpp | 2 +- 3 files changed, 21 insertions(+), 16 deletions(-) (limited to 'indra/newview/llpersistentnotificationstorage.cpp') diff --git a/indra/llui/lldockcontrol.cpp b/indra/llui/lldockcontrol.cpp index af39e41fa6..602113432e 100644 --- a/indra/llui/lldockcontrol.cpp +++ b/indra/llui/lldockcontrol.cpp @@ -31,7 +31,6 @@ LLDockControl::LLDockControl(LLView* dockWidget, LLFloater* dockableFloater, const LLUIImagePtr& dockTongue, DocAt dockAt, get_allowed_rect_callback_t get_allowed_rect_callback) : - mDockWidget(dockWidget), mDockableFloater(dockableFloater), mDockTongue(dockTongue), mDockTongueX(0), @@ -39,6 +38,11 @@ LLDockControl::LLDockControl(LLView* dockWidget, LLFloater* dockableFloater, { mDockAt = dockAt; + if (dockWidget != NULL) + { + mDockWidget = dockWidget->getHandle(); + } + if (dockableFloater->isDocked()) { on(); @@ -62,7 +66,7 @@ LLDockControl::LLDockControl(LLView* dockWidget, LLFloater* dockableFloater, repositionDockable(); } - if (mDockWidget != NULL) + if (getDock() != NULL) { mDockWidgetVisible = isDockVisible(); } @@ -78,14 +82,15 @@ LLDockControl::~LLDockControl() void LLDockControl::setDock(LLView* dockWidget) { - mDockWidget = dockWidget; - if (mDockWidget != NULL) + if (dockWidget != NULL) { + mDockWidget = dockWidget->getHandle(); repositionDockable(); mDockWidgetVisible = isDockVisible(); } else { + mDockWidget = LLHandle(); mDockWidgetVisible = false; } } @@ -97,8 +102,8 @@ void LLDockControl::getAllowedRect(LLRect& rect) void LLDockControl::repositionDockable() { - if (!mDockWidget) return; - LLRect dockRect = mDockWidget->calcScreenRect(); + if (!getDock()) return; + LLRect dockRect = getDock()->calcScreenRect(); LLRect rootRect; LLRect floater_rect = mDockableFloater->calcScreenRect(); mGetAllowedRectCallback(rootRect); @@ -150,13 +155,13 @@ bool LLDockControl::isDockVisible() { bool res = true; - if (mDockWidget != NULL) + if (getDock() != NULL) { //we should check all hierarchy - res = mDockWidget->isInVisibleChain(); + res = getDock()->isInVisibleChain(); if (res) { - LLRect dockRect = mDockWidget->calcScreenRect(); + LLRect dockRect = getDock()->calcScreenRect(); switch (mDockAt) { @@ -169,7 +174,7 @@ bool LLDockControl::isDockVisible() // assume that parent for all dockable floaters // is the root view LLRect dockParentRect = - mDockWidget->getRootView()->calcScreenRect(); + getDock()->getRootView()->calcScreenRect(); if (dockRect.mRight <= dockParentRect.mLeft || dockRect.mLeft >= dockParentRect.mRight) { @@ -189,7 +194,7 @@ bool LLDockControl::isDockVisible() void LLDockControl::moveDockable() { // calculate new dockable position - LLRect dockRect = mDockWidget->calcScreenRect(); + LLRect dockRect = getDock()->calcScreenRect(); LLRect rootRect; mGetAllowedRectCallback(rootRect); @@ -263,7 +268,7 @@ void LLDockControl::moveDockable() // calculate dock tongue position - dockParentRect = mDockWidget->getParent()->calcScreenRect(); + dockParentRect = getDock()->getParent()->calcScreenRect(); if (dockRect.getCenterX() < dockParentRect.mLeft) { mDockTongueX = dockParentRect.mLeft - mDockTongue->getWidth() / 2; @@ -299,7 +304,7 @@ void LLDockControl::moveDockable() } // calculate dock tongue position - dockParentRect = mDockWidget->getParent()->calcScreenRect(); + dockParentRect = getDock()->getParent()->calcScreenRect(); if (dockRect.getCenterX() < dockParentRect.mLeft) { mDockTongueX = dockParentRect.mLeft - mDockTongue->getWidth() / 2; diff --git a/indra/llui/lldockcontrol.h b/indra/llui/lldockcontrol.h index c9602011f6..a1cfa0072c 100644 --- a/indra/llui/lldockcontrol.h +++ b/indra/llui/lldockcontrol.h @@ -63,7 +63,7 @@ public: void setDock(LLView* dockWidget); LLView* getDock() { - return mDockWidget; + return mDockWidget.get(); } void repositionDockable(); void drawToungue(); @@ -83,7 +83,7 @@ private: bool mRecalculateDockablePosition; bool mDockWidgetVisible; DocAt mDockAt; - LLView* mDockWidget; + LLHandle mDockWidget; LLRect mPrevDockRect; LLRect mRootRect; LLRect mFloaterRect; diff --git a/indra/newview/llpersistentnotificationstorage.cpp b/indra/newview/llpersistentnotificationstorage.cpp index 224aaa2146..11c12e6c10 100644 --- a/indra/newview/llpersistentnotificationstorage.cpp +++ b/indra/newview/llpersistentnotificationstorage.cpp @@ -75,7 +75,7 @@ void LLPersistentNotificationStorage::saveNotifications() continue; } - data.append(notification->asLLSD()); + data.append(notification->asLLSD(true)); } writeNotifications(output); -- cgit v1.3