diff options
Diffstat (limited to 'indra/newview/llconversationlog.cpp')
-rw-r--r-- | indra/newview/llconversationlog.cpp | 354 |
1 files changed, 354 insertions, 0 deletions
diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp new file mode 100644 index 0000000000..137b97326c --- /dev/null +++ b/indra/newview/llconversationlog.cpp @@ -0,0 +1,354 @@ +/** + * @file llconversationlog.h + * + * $LicenseInfo:firstyear=2002&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 "llagent.h" +#include "llconversationlog.h" +#include "lltrans.h" + +struct Conversation_params +{ + Conversation_params(time_t time) + : mTime(time), + mTimestamp(LLConversation::createTimestamp(time)) + {} + + time_t mTime; + std::string mTimestamp; + SessionType mConversationType; + std::string mConversationName; + std::string mHistoryFileName; + LLUUID mSessionID; + LLUUID mParticipantID; + bool mIsVoice; + bool mHasOfflineIMs; +}; + +/************************************************************************/ +/* LLConversation implementation */ +/************************************************************************/ + +LLConversation::LLConversation(const Conversation_params& params) +: mTime(params.mTime), + mTimestamp(params.mTimestamp), + mConversationType(params.mConversationType), + mConversationName(params.mConversationName), + mHistoryFileName(params.mHistoryFileName), + mSessionID(params.mSessionID), + mParticipantID(params.mParticipantID), + mIsVoice(params.mIsVoice), + mHasOfflineIMs(params.mHasOfflineIMs) +{ + setListenIMFloaterOpened(); +} + +LLConversation::LLConversation(const LLIMModel::LLIMSession& session) +: mTime(time_corrected()), + mTimestamp(createTimestamp(mTime)), + mConversationType(session.mSessionType), + mConversationName(session.mName), + mHistoryFileName(session.mHistoryFileName), + mSessionID(session.mSessionID), + mParticipantID(session.mOtherParticipantID), + mIsVoice(session.mStartedAsIMCall), + mHasOfflineIMs(session.mHasOfflineMessage) +{ + setListenIMFloaterOpened(); +} + +LLConversation::LLConversation(const LLConversation& conversation) +{ + mTime = conversation.getTime(); + mTimestamp = conversation.getTimestamp(); + mConversationType = conversation.getConversationType(); + mConversationName = conversation.getConversationName(); + mHistoryFileName = conversation.getHistoryFileName(); + mSessionID = conversation.getSessionID(); + mParticipantID = conversation.getParticipantID(); + mIsVoice = conversation.isVoice(); + mHasOfflineIMs = conversation.hasOfflineMessages(); + + setListenIMFloaterOpened(); +} + +LLConversation::~LLConversation() +{ + mIMFloaterShowedConnection.disconnect(); +} + +void LLConversation::onIMFloaterShown(const LLUUID& session_id) +{ + if (mSessionID == session_id) + { + mHasOfflineIMs = false; + } +} + +// static +const std::string LLConversation::createTimestamp(const time_t& utc_time) +{ + std::string timeStr; + LLSD substitution; + substitution["datetime"] = (S32) utc_time; + + timeStr = "["+LLTrans::getString ("TimeMonth")+"]/[" + +LLTrans::getString ("TimeDay")+"]/[" + +LLTrans::getString ("TimeYear")+"] [" + +LLTrans::getString ("TimeHour")+"]:[" + +LLTrans::getString ("TimeMin")+"]"; + + + LLStringUtil::format (timeStr, substitution); + return timeStr; +} + +void LLConversation::setListenIMFloaterOpened() +{ + LLIMFloater* floater = LLIMFloater::findInstance(mSessionID); + + bool has_offline_ims = !mIsVoice && mHasOfflineIMs; + bool ims_are_read = LLIMFloater::isVisible(floater) && floater->hasFocus(); + + // we don't need to listen for im floater with this conversation is opened + // if floater is already opened or this conversation doesn't have unread offline messages + if (has_offline_ims && !ims_are_read) + { + mIMFloaterShowedConnection = LLIMFloater::setIMFloaterShowedCallback(boost::bind(&LLConversation::onIMFloaterShown, this, _1)); + } +} +/************************************************************************/ +/* LLConversationLogFriendObserver implementation */ +/************************************************************************/ + +// Note : An LLSingleton like LLConversationLog cannot be an LLFriendObserver +// at the same time. +// This is because avatar observers are deleted by the observed object which +// conflicts with the way LLSingleton are deleted. + +class LLConversationLogFriendObserver : public LLFriendObserver +{ +public: + LLConversationLogFriendObserver() {} + virtual ~LLConversationLogFriendObserver() {} + virtual void changed(U32 mask); +}; + +void LLConversationLogFriendObserver::changed(U32 mask) +{ + if (mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE)) + { + LLConversationLog::instance().notifyObservers(); + } +} + +/************************************************************************/ +/* LLConversationLog implementation */ +/************************************************************************/ + +LLConversationLog::LLConversationLog() +{ + loadFromFile(getFileName()); + + LLIMMgr::instance().addSessionObserver(this); + + mFriendObserver = new LLConversationLogFriendObserver; + LLAvatarTracker::instance().addObserver(mFriendObserver); +} +void LLConversationLog::logConversation(const LLConversation& conversation) +{ + mConversations.push_back(conversation); + notifyObservers(); +} + +void LLConversationLog::removeConversation(const LLConversation& conversation) +{ + conversations_vec_t::iterator conv_it = mConversations.begin(); + for(; conv_it != mConversations.end(); ++conv_it) + { + if (conv_it->getSessionID() == conversation.getSessionID() && conv_it->getTime() == conversation.getTime()) + { + mConversations.erase(conv_it); + notifyObservers(); + return; + } + } +} + +const LLConversation* LLConversationLog::getConversation(const LLUUID& session_id) +{ + conversations_vec_t::const_iterator conv_it = mConversations.begin(); + for(; conv_it != mConversations.end(); ++conv_it) + { + if (conv_it->getSessionID() == session_id) + { + return &*conv_it; + } + } + + return NULL; +} + +void LLConversationLog::addObserver(LLConversationLogObserver* observer) +{ + mObservers.insert(observer); +} + +void LLConversationLog::removeObserver(LLConversationLogObserver* observer) +{ + mObservers.erase(observer); +} + +void LLConversationLog::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) +{ + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); + if (session) + { + LLConversation conversation(*session); + LLConversationLog::instance().logConversation(conversation); + } +} + +void LLConversationLog::cache() +{ + saveToFile(getFileName()); +} + +std::string LLConversationLog::getFileName() +{ + std::string agent_id_string; + gAgent.getID().toString(agent_id_string); + + return gDirUtilp->getExpandedFilename(LL_PATH_CACHE, agent_id_string) + ".call_log"; +} + +bool LLConversationLog::saveToFile(const std::string& filename) +{ + if(!filename.size()) + { + llwarns << "Call log list filename is empty!" << llendl; + return false; + } + + LLFILE* fp = LLFile::fopen(filename, "wb"); + if (!fp) + { + llwarns << "Couldn't open call log list" << filename << llendl; + return false; + } + + std::string participant_id; + std::string conversation_id; + + conversations_vec_t::const_iterator conv_it = mConversations.begin(); + for (; conv_it != mConversations.end(); ++conv_it) + { + conv_it->getSessionID().toString(conversation_id); + conv_it->getParticipantID().toString(participant_id); + + // examples of two file entries + // [1343221177] 0 1 0 John Doe| 7e4ec5be-783f-49f5-71dz-16c58c64c145 4ec62a74-c246-0d25-2af6-846beac2aa55 john.doe| + // [1343222639] 2 0 0 Ad-hoc Conference| c3g67c89-c479-4c97-b21d-32869bcfe8rc 68f1c33e-4135-3e3e-a897-8c9b23115c09 Ad-hoc Conference hash597394a0-9982-766d-27b8-c75560213b9a| + + fprintf(fp, "[%d] %d %d %d %s| %s %s %s|\n", + (S32)conv_it->getTime(), + (S32)conv_it->getConversationType(), + (S32)conv_it->isVoice(), + (S32)conv_it->hasOfflineMessages(), + conv_it->getConversationName().c_str(), + participant_id.c_str(), + conversation_id.c_str(), + conv_it->getHistoryFileName().c_str()); + } + fclose(fp); + return true; +} +bool LLConversationLog::loadFromFile(const std::string& filename) +{ + if(!filename.size()) + { + llwarns << "Call log list filename is empty!" << llendl; + return false; + } + + LLFILE* fp = LLFile::fopen(filename, "rb"); + if (!fp) + { + llwarns << "Couldn't open call log list" << filename << llendl; + return false; + } + + char buffer[MAX_STRING]; + char conv_name_buffer[MAX_STRING]; + char part_id_buffer[MAX_STRING]; + char conv_id_buffer[MAX_STRING]; + char history_file_name[MAX_STRING]; + int is_voice; + int has_offline_ims; + int stype; + S32 time; + + while (!feof(fp) && fgets(buffer, MAX_STRING, fp)) + { + conv_name_buffer[0] = '\0'; + part_id_buffer[0] = '\0'; + conv_id_buffer[0] = '\0'; + + sscanf(buffer, "[%d] %d %d %d %[^|]| %s %s %[^|]|", + &time, + &stype, + &is_voice, + &has_offline_ims, + conv_name_buffer, + part_id_buffer, + conv_id_buffer, + history_file_name); + + Conversation_params params(time); + params.mConversationType = (SessionType)stype; + params.mIsVoice = is_voice; + params.mHasOfflineIMs = has_offline_ims; + params.mConversationName = std::string(conv_name_buffer); + params.mParticipantID = LLUUID(part_id_buffer); + params.mSessionID = LLUUID(conv_id_buffer); + params.mHistoryFileName = std::string(history_file_name); + + LLConversation conversation(params); + mConversations.push_back(conversation); + } + fclose(fp); + + notifyObservers(); + return true; +} + +void LLConversationLog::notifyObservers() +{ + std::set<LLConversationLogObserver*>::const_iterator iter = mObservers.begin(); + for (; iter != mObservers.end(); ++iter) + { + (*iter)->changed(); + } +} |