summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/llui/llspinctrl.cpp5
-rw-r--r--indra/llui/llspinctrl.h1
-rw-r--r--indra/newview/llappviewer.cpp5
-rw-r--r--indra/newview/llconversationlog.cpp171
-rw-r--r--indra/newview/llconversationlog.h46
-rw-r--r--indra/newview/llconversationloglist.cpp57
-rw-r--r--indra/newview/llconversationloglist.h9
-rw-r--r--indra/newview/llconversationloglistitem.cpp10
-rw-r--r--indra/newview/llconversationloglistitem.h8
-rw-r--r--indra/newview/llconversationmodel.cpp38
-rw-r--r--indra/newview/llconversationmodel.h15
-rw-r--r--indra/newview/llfloaterconversationlog.cpp25
-rw-r--r--indra/newview/llfloaterconversationlog.h7
-rw-r--r--indra/newview/llfloaterconversationpreview.cpp8
-rw-r--r--indra/newview/llimfloatercontainer.cpp26
-rw-r--r--indra/newview/llimfloatercontainer.h2
-rw-r--r--indra/newview/lllogchat.cpp17
-rw-r--r--indra/newview/lllogchat.h4
-rw-r--r--indra/newview/llparticipantlist.cpp2
-rw-r--r--indra/newview/skins/default/xui/en/floater_conversation_log.xml5
-rw-r--r--indra/newview/skins/default/xui/en/floater_conversation_preview.xml29
-rw-r--r--indra/newview/skins/default/xui/en/floater_im_container.xml2
22 files changed, 313 insertions, 179 deletions
diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp
index 934879cdfd..8a728df2e7 100644
--- a/indra/llui/llspinctrl.cpp
+++ b/indra/llui/llspinctrl.cpp
@@ -52,6 +52,7 @@ LLSpinCtrl::Params::Params()
: label_width("label_width"),
decimal_digits("decimal_digits"),
allow_text_entry("allow_text_entry", true),
+ allow_digits_only("allow_digits_only", false),
label_wrap("label_wrap", false),
text_enabled_color("text_enabled_color"),
text_disabled_color("text_disabled_color"),
@@ -129,6 +130,10 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p)
params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM);
mEditor = LLUICtrlFactory::create<LLLineEditor> (params);
mEditor->setFocusReceivedCallback( boost::bind(&LLSpinCtrl::onEditorGainFocus, _1, this ));
+ if (p.allow_digits_only)
+ {
+ mEditor->setPrevalidateInput(LLTextValidate::validateNonNegativeS32NoSpace);
+ }
//RN: this seems to be a BAD IDEA, as it makes the editor behavior different when it has focus
// than when it doesn't. Instead, if you always have to double click to select all the text,
// it's easier to understand
diff --git a/indra/llui/llspinctrl.h b/indra/llui/llspinctrl.h
index 87814f838e..e34add879d 100644
--- a/indra/llui/llspinctrl.h
+++ b/indra/llui/llspinctrl.h
@@ -44,6 +44,7 @@ public:
Optional<S32> label_width;
Optional<U32> decimal_digits;
Optional<bool> allow_text_entry;
+ Optional<bool> allow_digits_only;
Optional<bool> label_wrap;
Optional<LLUIColor> text_enabled_color;
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 4dacde4792..08a1a237f5 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1834,10 +1834,7 @@ bool LLAppViewer::cleanup()
LLMuteList::getInstance()->cache(gAgent.getID());
//save call log list
- if (gSavedPerAccountSettings.getBOOL("LogInstantMessages"))
- {
- LLConversationLog::instance().cache();
- }
+ LLConversationLog::instance().cache();
if (mPurgeOnExit)
{
diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp
index cc02e18698..27be2bc5ae 100644
--- a/indra/newview/llconversationlog.cpp
+++ b/indra/newview/llconversationlog.cpp
@@ -37,7 +37,7 @@ struct Conversation_params
Conversation_params(time_t time)
: mTime(time),
mTimestamp(LLConversation::createTimestamp(time)),
- mIsConversationPast(true)
+ mIsVoice(false)
{}
time_t mTime;
@@ -48,7 +48,6 @@ struct Conversation_params
LLUUID mSessionID;
LLUUID mParticipantID;
bool mIsVoice;
- bool mIsConversationPast;
bool mHasOfflineIMs;
};
@@ -65,7 +64,6 @@ LLConversation::LLConversation(const Conversation_params& params)
mSessionID(params.mSessionID),
mParticipantID(params.mParticipantID),
mIsVoice(params.mIsVoice),
- mIsConversationPast(params.mIsConversationPast),
mHasOfflineIMs(params.mHasOfflineIMs)
{
setListenIMFloaterOpened();
@@ -80,7 +78,6 @@ LLConversation::LLConversation(const LLIMModel::LLIMSession& session)
mSessionID(session.mSessionID),
mParticipantID(session.mOtherParticipantID),
mIsVoice(session.mStartedAsIMCall),
- mIsConversationPast(false),
mHasOfflineIMs(session.mHasOfflineMessage)
{
setListenIMFloaterOpened();
@@ -96,7 +93,6 @@ LLConversation::LLConversation(const LLConversation& conversation)
mSessionID = conversation.getSessionID();
mParticipantID = conversation.getParticipantID();
mIsVoice = conversation.isVoice();
- mIsConversationPast = conversation.isConversationPast();
mHasOfflineIMs = conversation.hasOfflineMessages();
setListenIMFloaterOpened();
@@ -107,12 +103,10 @@ LLConversation::~LLConversation()
mIMFloaterShowedConnection.disconnect();
}
-void LLConversation::setIsVoice(bool is_voice)
+void LLConversation::updateTimestamp()
{
- if (mIsConversationPast)
- return;
-
- mIsVoice = is_voice;
+ mTime = time_corrected();
+ mTimestamp = createTimestamp(mTime);
}
void LLConversation::onIMFloaterShown(const LLUUID& session_id)
@@ -154,14 +148,18 @@ void LLConversation::setListenIMFloaterOpened()
LLIMFloater* floater = LLIMFloater::findInstance(mSessionID);
bool has_offline_ims = !mIsVoice && mHasOfflineIMs;
- bool ims_are_read = LLIMFloater::isVisible(floater) && floater->hasFocus();
+ bool offline_ims_visible = 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)
+ if (has_offline_ims && !offline_ims_visible)
{
mIMFloaterShowedConnection = LLIMFloater::setIMFloaterShowedCallback(boost::bind(&LLConversation::onIMFloaterShown, this, _1));
}
+ else
+ {
+ mHasOfflineIMs = false;
+ }
}
/************************************************************************/
@@ -195,40 +193,107 @@ void LLConversationLogFriendObserver::changed(U32 mask)
LLConversationLog::LLConversationLog()
{
- loadFromFile(getFileName());
-
LLControlVariable* ctrl = gSavedPerAccountSettings.getControl("LogInstantMessages").get();
if (ctrl)
{
- ctrl->getSignal()->connect(boost::bind(&LLConversationLog::observeIMSession, this));
-
+ ctrl->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2));
if (ctrl->getValue().asBoolean())
{
- LLIMMgr::instance().addSessionObserver(this);
+ enableLogging(true);
}
}
-
- mFriendObserver = new LLConversationLogFriendObserver;
- LLAvatarTracker::instance().addObserver(mFriendObserver);
-
}
-void LLConversationLog::observeIMSession()
+void LLConversationLog::enableLogging(bool enable)
{
- if (gSavedPerAccountSettings.getBOOL("LogInstantMessages"))
+ if (enable)
{
+ loadFromFile(getFileName());
+
LLIMMgr::instance().addSessionObserver(this);
+ newMessageSignalConnection = LLIMModel::instance().addNewMsgCallback(boost::bind(&LLConversationLog::onNewMessageReceived, this, _1));
+
+ mFriendObserver = new LLConversationLogFriendObserver;
+ LLAvatarTracker::instance().addObserver(mFriendObserver);
}
else
{
+ saveToFile(getFileName());
+
LLIMMgr::instance().removeSessionObserver(this);
+ newMessageSignalConnection.disconnect();
+ LLAvatarTracker::instance().removeObserver(mFriendObserver);
+ mConversations.clear();
}
+
+ notifyObservers();
}
-void LLConversationLog::logConversation(const LLConversation& conversation)
+void LLConversationLog::logConversation(const LLUUID& session_id)
{
- mConversations.push_back(conversation);
- notifyObservers();
+ LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id);
+ LLConversation* conversation = findConversation(session_id);
+
+ if (session && conversation)
+ {
+ updateConversationTimestamp(conversation);
+ }
+ else if (session && !conversation)
+ {
+ createConversation(session_id);
+ }
+}
+
+void LLConversationLog::createConversation(const LLUUID& session_id)
+{
+ LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id);
+
+ if (session)
+ {
+ LLConversation conversation(*session);
+ mConversations.push_back(conversation);
+
+ if (LLIMModel::LLIMSession::P2P_SESSION == session->mSessionType)
+ {
+ LLAvatarNameCache::get(session->mOtherParticipantID, boost::bind(&LLConversationLog::onAvatarNameCache, this, _1, _2, session));
+ }
+
+ notifyObservers();
+ }
+}
+
+void LLConversationLog::updateConversationName(const LLUUID& session_id, const std::string& name)
+{
+ LLConversation* conversation = findConversation(session_id);
+
+ if (conversation)
+ {
+ conversation->setConverstionName(name);
+ notifyPrticularConversationObservers(session_id, LLConversationLogObserver::CHANGED_NAME);
+ }
+}
+
+void LLConversationLog::updateConversationTimestamp(LLConversation* conversation)
+{
+ if (conversation)
+ {
+ conversation->updateTimestamp();
+ notifyPrticularConversationObservers(conversation->getSessionID(), LLConversationLogObserver::CHANGED_TIME);
+ }
+}
+
+LLConversation* LLConversationLog::findConversation(const LLUUID& session_id)
+{
+ conversations_vec_t::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::removeConversation(const LLConversation& conversation)
@@ -271,41 +336,17 @@ void LLConversationLog::removeObserver(LLConversationLogObserver* 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)
- {
- if (LLIMModel::LLIMSession::P2P_SESSION == session->mSessionType)
- {
- LLAvatarNameCache::get(session->mOtherParticipantID, boost::bind(&LLConversationLog::onAvatarNameCache, this, _1, _2, session));
- }
- else
- {
- LLConversation conversation(*session);
- LLConversationLog::instance().logConversation(conversation);
- session->mVoiceChannel->setStateChangedCallback(boost::bind(&LLConversationLog::onVoiceChannelConnected, this, _5, _2));
- }
- }
+ logConversation(session_id);
}
-void LLConversationLog::sessionRemoved(const LLUUID& session_id)
+void LLConversationLog::cache()
{
- conversations_vec_t::reverse_iterator rev_iter = mConversations.rbegin();
-
- for (; rev_iter != mConversations.rend(); ++rev_iter)
+ if (gSavedPerAccountSettings.getBOOL("LogInstantMessages"))
{
- if (rev_iter->getSessionID() == session_id && !rev_iter->isConversationPast())
- {
- rev_iter->setIsPast(true);
- return; // return here because only one session with session_id may be active
- }
+ saveToFile(getFileName());
}
}
-void LLConversationLog::cache()
-{
- saveToFile(getFileName());
-}
-
std::string LLConversationLog::getFileName()
{
std::string filename = "conversation";
@@ -314,7 +355,7 @@ std::string LLConversationLog::getFileName()
bool LLConversationLog::saveToFile(const std::string& filename)
{
- if(!filename.size())
+ if (!filename.size())
{
llwarns << "Call log list filename is empty!" << llendl;
return false;
@@ -442,25 +483,13 @@ void LLConversationLog::notifyPrticularConversationObservers(const LLUUID& sessi
}
}
-void LLConversationLog::onVoiceChannelConnected(const LLUUID& session_id, const LLVoiceChannel::EState& state)
+void LLConversationLog::onNewMessageReceived(const LLSD& data)
{
- conversations_vec_t::reverse_iterator rev_iter = mConversations.rbegin();
-
- for (; rev_iter != mConversations.rend(); ++rev_iter)
- {
- if (rev_iter->getSessionID() == session_id && !rev_iter->isConversationPast() && LLVoiceChannel::STATE_CALL_STARTED == state)
- {
- rev_iter->setIsVoice(true);
- notifyPrticularConversationObservers(session_id, LLConversationLogObserver::VOICE_STATE);
- return; // return here because only one session with session_id may be active
- }
- }
+ const LLUUID session_id = data["session_id"].asUUID();
+ logConversation(session_id);
}
void LLConversationLog::onAvatarNameCache(const LLUUID& participant_id, const LLAvatarName& av_name, LLIMModel::LLIMSession* session)
{
- LLConversation conversation(*session);
- conversation.setConverstionName(av_name.getCompleteName());
- LLConversationLog::instance().logConversation(conversation);
- session->mVoiceChannel->setStateChangedCallback(boost::bind(&LLConversationLog::onVoiceChannelConnected, this, _5, _2));
+ updateConversationName(session->mSessionID, av_name.getCompleteName());
}
diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h
index 16be37d67a..a458e975bb 100644
--- a/indra/newview/llconversationlog.h
+++ b/indra/newview/llconversationlog.h
@@ -57,16 +57,19 @@ public:
const std::string& getTimestamp() const { return mTimestamp; }
const time_t& getTime() const { return mTime; }
bool isVoice() const { return mIsVoice; }
- bool isConversationPast() const { return mIsConversationPast; }
bool hasOfflineMessages() const { return mHasOfflineIMs; }
void setIsVoice(bool is_voice);
- void setIsPast (bool is_past) { mIsConversationPast = is_past; }
void setConverstionName(std::string conv_name) { mConversationName = conv_name; }
bool isOlderThan(U32 days) const;
/*
+ * updates last interaction time
+ */
+ void updateTimestamp();
+
+ /*
* Resets flag of unread offline message to false when im floater with this conversation is opened.
*/
void onIMFloaterShown(const LLUUID& session_id);
@@ -86,7 +89,7 @@ private:
boost::signals2::connection mIMFloaterShowedConnection;
- time_t mTime; // start time of conversation
+ time_t mTime; // last interaction time
SessionType mConversationType;
std::string mConversationName;
std::string mHistoryFileName;
@@ -94,8 +97,7 @@ private:
LLUUID mParticipantID;
bool mIsVoice;
bool mHasOfflineIMs;
- bool mIsConversationPast; // once session is finished conversation became past forever
- std::string mTimestamp; // conversation start time in form of: mm/dd/yyyy hh:mm
+ std::string mTimestamp; // last interaction time in form of: mm/dd/yyyy hh:mm
};
/**
@@ -112,32 +114,26 @@ class LLConversationLog : public LLSingleton<LLConversationLog>, LLIMSessionObse
friend class LLSingleton<LLConversationLog>;
public:
- /**
- * adds conversation to the conversation list and notifies observers
- */
- void logConversation(const LLConversation& conversation);
void removeConversation(const LLConversation& conversation);
/**
* Returns first conversation with matched session_id
*/
- const LLConversation* getConversation(const LLUUID& session_id);
+ const LLConversation* getConversation(const LLUUID& session_id);
+ const std::vector<LLConversation>& getConversations() { return mConversations; }
void addObserver(LLConversationLogObserver* observer);
void removeObserver(LLConversationLogObserver* observer);
- const std::vector<LLConversation>& getConversations() { return mConversations; }
-
// LLIMSessionObserver triggers
virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id);
- virtual void sessionRemoved(const LLUUID& session_id);
+ virtual void sessionRemoved(const LLUUID& session_id){} // Stub
virtual void sessionVoiceOrIMStarted(const LLUUID& session_id){}; // Stub
virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id){}; // Stub
void notifyObservers();
- void notifyPrticularConversationObservers(const LLUUID& session_id, U32 mask);
- void onVoiceChannelConnected(const LLUUID& session_id, const LLVoiceChannel::EState& state);
+ void onNewMessageReceived(const LLSD& data);
/**
* public method which is called on viewer exit to save conversation log
@@ -148,7 +144,14 @@ private:
LLConversationLog();
- void observeIMSession();
+ void enableLogging(bool enable);
+
+ /**
+ * adds conversation to the conversation list and notifies observers
+ */
+ void logConversation(const LLUUID& session_id);
+
+ void notifyPrticularConversationObservers(const LLUUID& session_id, U32 mask);
/**
* constructs file name in which conversations log will be saved
@@ -161,11 +164,19 @@ private:
void onAvatarNameCache(const LLUUID& participant_id, const LLAvatarName& av_name, LLIMModel::LLIMSession* session);
+ void createConversation(const LLUUID& session_id);
+ void updateConversationTimestamp(LLConversation* conversation);
+ void updateConversationName(const LLUUID& session_id, const std::string& name);
+
+ LLConversation* findConversation(const LLUUID& session_id);
+
typedef std::vector<LLConversation> conversations_vec_t;
std::vector<LLConversation> mConversations;
std::set<LLConversationLogObserver*> mObservers;
LLFriendObserver* mFriendObserver; // Observer of the LLAvatarTracker instance
+
+ boost::signals2::connection newMessageSignalConnection;
};
class LLConversationLogObserver
@@ -174,7 +185,8 @@ public:
enum EConversationChange
{
- VOICE_STATE = 1
+ CHANGED_TIME = 1, // last interaction time changed
+ CHANGED_NAME = 2 // conversation name changed
};
virtual ~LLConversationLogObserver(){}
diff --git a/indra/newview/llconversationloglist.cpp b/indra/newview/llconversationloglist.cpp
index d39e090c22..429e99f7ad 100644
--- a/indra/newview/llconversationloglist.cpp
+++ b/indra/newview/llconversationloglist.cpp
@@ -143,22 +143,32 @@ void LLConversationLogList::changed()
void LLConversationLogList::changed(const LLUUID& session_id, U32 mask)
{
- if (mask & LLConversationLogObserver::VOICE_STATE)
+ LLConversationLogListItem* item = getConversationLogListItem(session_id);
+
+ if (!item)
{
- std::vector<LLPanel*> panels;
- LLFlatListViewEx::getItems(panels);
+ return;
+ }
- std::vector<LLPanel*>::iterator iter = panels.begin();
+ if (mask & LLConversationLogObserver::CHANGED_TIME)
+ {
+ item->updateTimestamp();
- for (; iter != panels.end(); ++iter)
+ // if list is sorted by date and a date of some item has changed,
+ // than the whole list should be rebuilt
+ if (E_SORT_BY_DATE == getSortOrder())
{
- LLConversationLogListItem* item = dynamic_cast<LLConversationLogListItem*>(*iter);
-
- if (item && session_id == item->getConversation()->getSessionID() && !item->getConversation()->isConversationPast())
- {
- item->initIcons();
- return;
- }
+ mIsDirty = true;
+ }
+ }
+ else if (mask & LLConversationLogObserver::CHANGED_NAME)
+ {
+ item->updateName();
+ // if list is sorted by name and a name of some item has changed,
+ // than the whole list should be rebuilt
+ if (E_SORT_BY_DATE == getSortOrder())
+ {
+ mIsDirty = true;
}
}
}
@@ -401,6 +411,29 @@ const LLConversation* LLConversationLogList::getSelectedConversation()
return NULL;
}
+LLConversationLogListItem* LLConversationLogList::getConversationLogListItem(const LLUUID& session_id)
+{
+ std::vector<LLPanel*> panels;
+ LLFlatListViewEx::getItems(panels);
+ std::vector<LLPanel*>::iterator iter = panels.begin();
+
+ for (; iter != panels.end(); ++iter)
+ {
+ LLConversationLogListItem* item = dynamic_cast<LLConversationLogListItem*>(*iter);
+ if (item && session_id == item->getConversation()->getSessionID())
+ {
+ return item;
+ }
+ }
+
+ return NULL;
+}
+
+LLConversationLogList::ESortOrder LLConversationLogList::getSortOrder()
+{
+ return static_cast<ESortOrder>(gSavedSettings.getU32("CallLogSortOrder"));
+}
+
bool LLConversationLogListItemComparator::compare(const LLPanel* item1, const LLPanel* item2) const
{
const LLConversationLogListItem* conversation_item1 = dynamic_cast<const LLConversationLogListItem*>(item1);
diff --git a/indra/newview/llconversationloglist.h b/indra/newview/llconversationloglist.h
index 5e7fc0a9fb..62ec57e09e 100644
--- a/indra/newview/llconversationloglist.h
+++ b/indra/newview/llconversationloglist.h
@@ -43,6 +43,12 @@ class LLConversationLogList: public LLFlatListViewEx, public LLConversationLogOb
{
LOG_CLASS(LLConversationLogList);
public:
+
+ typedef enum e_sort_oder{
+ E_SORT_BY_NAME = 0,
+ E_SORT_BY_DATE = 1,
+ } ESortOrder;
+
struct Params : public LLInitParam::Block<Params, LLFlatListViewEx::Params>
{
Params(){};
@@ -90,6 +96,9 @@ private:
LLIMModel::LLIMSession::SType getSelectedSessionType();
const LLConversationLogListItem* getSelectedConversationPanel();
const LLConversation* getSelectedConversation();
+ LLConversationLogListItem* getConversationLogListItem(const LLUUID& session_id);
+
+ ESortOrder getSortOrder();
LLHandle<LLToggleableMenu> mContextMenu;
bool mIsDirty;
diff --git a/indra/newview/llconversationloglistitem.cpp b/indra/newview/llconversationloglistitem.cpp
index dddf216592..fac6130371 100644
--- a/indra/newview/llconversationloglistitem.cpp
+++ b/indra/newview/llconversationloglistitem.cpp
@@ -117,6 +117,16 @@ void LLConversationLogListItem::initIcons()
}
}
+void LLConversationLogListItem::updateTimestamp()
+{
+ mConversationDate->setValue(mConversation->getTimestamp());
+}
+
+void LLConversationLogListItem::updateName()
+{
+ mConversationName->setValue(mConversation->getConversationName());
+}
+
void LLConversationLogListItem::onMouseEnter(S32 x, S32 y, MASK mask)
{
getChildView("hovered_icon")->setVisible(true);
diff --git a/indra/newview/llconversationloglistitem.h b/indra/newview/llconversationloglistitem.h
index 2aaafa0fba..1bf7a0ed93 100644
--- a/indra/newview/llconversationloglistitem.h
+++ b/indra/newview/llconversationloglistitem.h
@@ -64,10 +64,16 @@ public:
void onDoubleClick();
- void initIcons();
+ /**
+ * updates string value of last interaction time from conversation
+ */
+ void updateTimestamp();
+ void updateName();
private:
+ void initIcons();
+
const LLConversation* mConversation;
LLTextBox* mConversationName;
diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp
index 51a37fe856..c36c3cbc65 100644
--- a/indra/newview/llconversationmodel.cpp
+++ b/indra/newview/llconversationmodel.cpp
@@ -78,14 +78,6 @@ void LLConversationItem::showProperties(void)
{
}
-bool LLConversationSort::operator()(const LLConversationItem* const& a, const LLConversationItem* const& b) const
-{
- // We compare only by name for the moment
- // *TODO : Implement the sorting by date
- S32 compare = LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName());
- return (compare < 0);
-}
-
//
// LLConversationItemSession
//
@@ -202,12 +194,38 @@ void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_nam
{
mName = av_name.mDisplayName;
// *TODO : we should also store that one, to be used in the tooltip : av_name.mUsername
- // *TODO : we need to request or initiate a list resort
mNeedsRefresh = true;
+ if (mParent)
+ {
+ mParent->requestSort();
+ }
}
void LLConversationItemParticipant::dumpDebugData()
{
llinfos << "Merov debug : participant, uuid = " << mUUID << ", name = " << mName << ", muted = " << mIsMuted << ", moderator = " << mIsModerator << llendl;
-}
+}
+
+//
+// LLConversationSort
+//
+
+bool LLConversationSort::operator()(const LLConversationItem* const& a, const LLConversationItem* const& b) const
+{
+ // For the moment, we sort only by name
+ // *TODO : Implement the sorting by date as well (most recent first)
+ // *TODO : Check the type of item (session/participants) as order should be different for both (eventually)
+ S32 compare = LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName());
+ return (compare < 0);
+}
+
+//
+// LLConversationViewModel
+//
+
+void LLConversationViewModel::sort(LLFolderViewFolder* folder)
+{
+ base_t::sort(folder);
+}
+
// EOF
diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h
index e5c727feae..f95db9a9d7 100644
--- a/indra/newview/llconversationmodel.h
+++ b/indra/newview/llconversationmodel.h
@@ -210,23 +210,14 @@ private:
class LLConversationSort
{
public:
- LLConversationSort(U32 order = 0)
- : mSortOrder(order),
- mByDate(false),
- mByName(false)
- {
- mByDate = (order & LLConversationFilter::SO_DATE);
- mByName = (order & LLConversationFilter::SO_NAME);
- }
+ LLConversationSort(U32 order = 0) : mSortOrder(order) { }
- bool isByDate() const { return mByDate; }
+ bool isByDate() const { return (mSortOrder & LLConversationFilter::SO_DATE); }
U32 getSortOrder() const { return mSortOrder; }
bool operator()(const LLConversationItem* const& a, const LLConversationItem* const& b) const;
private:
U32 mSortOrder;
- bool mByDate;
- bool mByName;
};
class LLConversationViewModel
@@ -235,7 +226,7 @@ class LLConversationViewModel
public:
typedef LLFolderViewModel<LLConversationSort, LLConversationItem, LLConversationItem, LLConversationFilter> base_t;
- void sort(LLFolderViewFolder* folder) { } // *TODO : implement conversation sort
+ void sort(LLFolderViewFolder* folder);
bool contentsReady() { return true; } // *TODO : we need to check that participants names are available somewhat
bool startDrag(std::vector<LLFolderViewModelItem*>& items) { return false; } // We do not allow drag of conversation items
diff --git a/indra/newview/llfloaterconversationlog.cpp b/indra/newview/llfloaterconversationlog.cpp
index 4375ce5726..089aec1905 100644
--- a/indra/newview/llfloaterconversationlog.cpp
+++ b/indra/newview/llfloaterconversationlog.cpp
@@ -45,11 +45,11 @@ BOOL LLFloaterConversationLog::postBuild()
switch (gSavedSettings.getU32("CallLogSortOrder"))
{
- case E_SORT_BY_NAME:
+ case LLConversationLogList::E_SORT_BY_NAME:
mConversationLogList->sortByName();
break;
- case E_SORT_BY_DATE:
+ case LLConversationLogList::E_SORT_BY_DATE:
mConversationLogList->sortByDate();
break;
}
@@ -63,6 +63,13 @@ BOOL LLFloaterConversationLog::postBuild()
getChild<LLFilterEditor>("people_filter_input")->setCommitCallback(boost::bind(&LLFloaterConversationLog::onFilterEdit, this, _2));
+ LLControlVariable* ctrl = gSavedPerAccountSettings.getControl("LogInstantMessages").get();
+ if (ctrl)
+ {
+ ctrl->getSignal()->connect(boost::bind(&LLFloaterConversationLog::onCallLoggingEnabledDisabled, this, _2));
+ onCallLoggingEnabledDisabled(ctrl->getValue().asBoolean());
+ }
+
return LLFloater::postBuild();
}
@@ -87,12 +94,12 @@ void LLFloaterConversationLog::onCustomAction (const LLSD& userdata)
if ("sort_by_name" == command_name)
{
mConversationLogList->sortByName();
- gSavedSettings.setU32("CallLogSortOrder", E_SORT_BY_NAME);
+ gSavedSettings.setU32("CallLogSortOrder", LLConversationLogList::E_SORT_BY_NAME);
}
else if ("sort_by_date" == command_name)
{
mConversationLogList->sortByDate();
- gSavedSettings.setU32("CallLogSortOrder", E_SORT_BY_DATE);
+ gSavedSettings.setU32("CallLogSortOrder", LLConversationLogList::E_SORT_BY_DATE);
}
else if ("sort_friends_on_top" == command_name)
{
@@ -117,11 +124,11 @@ bool LLFloaterConversationLog::isActionChecked(const LLSD& userdata)
if ("sort_by_name" == command_name)
{
- return sort_order == E_SORT_BY_NAME;
+ return sort_order == LLConversationLogList::E_SORT_BY_NAME;
}
else if ("sort_by_date" == command_name)
{
- return sort_order == E_SORT_BY_DATE;
+ return sort_order == LLConversationLogList::E_SORT_BY_DATE;
}
else if ("sort_friends_on_top" == command_name)
{
@@ -130,3 +137,9 @@ bool LLFloaterConversationLog::isActionChecked(const LLSD& userdata)
return false;
}
+
+void LLFloaterConversationLog::onCallLoggingEnabledDisabled(bool enabled)
+{
+ std::string no_items_msg = enabled ? "" : getString("logging_calls_disabled");
+ mConversationLogList->setNoItemsCommentText(no_items_msg);
+}
diff --git a/indra/newview/llfloaterconversationlog.h b/indra/newview/llfloaterconversationlog.h
index 7d788c0290..9e79cbd7d8 100644
--- a/indra/newview/llfloaterconversationlog.h
+++ b/indra/newview/llfloaterconversationlog.h
@@ -34,11 +34,6 @@ class LLFloaterConversationLog : public LLFloater
{
public:
- typedef enum e_sort_oder{
- E_SORT_BY_NAME = 0,
- E_SORT_BY_DATE = 1,
- } ESortOrder;
-
LLFloaterConversationLog(const LLSD& key);
virtual ~LLFloaterConversationLog(){};
@@ -54,6 +49,8 @@ private:
bool isActionEnabled(const LLSD& userdata);
bool isActionChecked(const LLSD& userdata);
+ void onCallLoggingEnabledDisabled(bool enabled);
+
LLConversationLogList* mConversationLogList;
};
diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp
index c9d9d7aa3b..88efc39764 100644
--- a/indra/newview/llfloaterconversationpreview.cpp
+++ b/indra/newview/llfloaterconversationpreview.cpp
@@ -65,9 +65,11 @@ BOOL LLFloaterConversationPreview::postBuild()
std::string title = getString("Title", args);
setTitle(title);
- getChild<LLLineEditor>("description")->setValue(name);
+ LLSD load_params;
+ load_params["load_all_history"] = true;
+ load_params["cut_off_todays_date"] = false;
- LLLogChat::loadChatHistory(file, mMessages, true);
+ LLLogChat::loadChatHistory(file, mMessages, load_params);
mCurrentPage = mMessages.size() / mPageSize;
mPageSpinner = getChild<LLSpinCtrl>("history_page_spin");
@@ -138,7 +140,7 @@ void LLFloaterConversationPreview::showHistory()
void LLFloaterConversationPreview::onMoreHistoryBtnClick()
{
- mCurrentPage = mPageSpinner->getValueF32();
+ mCurrentPage = (int)(mPageSpinner->getValueF32());
if (--mCurrentPage < 0)
{
return;
diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp
index 79009942bf..6aa7a2e054 100644
--- a/indra/newview/llimfloatercontainer.cpp
+++ b/indra/newview/llimfloatercontainer.cpp
@@ -46,6 +46,7 @@
#include "lltransientfloatermgr.h"
#include "llviewercontrol.h"
#include "llconversationview.h"
+#include "llcallbacklist.h"
//
// LLIMFloaterContainer
@@ -67,6 +68,8 @@ LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed)
LLIMFloaterContainer::~LLIMFloaterContainer()
{
+ gIdleCallbacks.deleteFunction(idle, this);
+
mNewMessageConnection.disconnect();
LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this);
@@ -118,7 +121,7 @@ BOOL LLIMFloaterContainer::postBuild()
mConversationsListPanel = getChild<LLPanel>("conversations_list_panel");
- // CHUI-98 : View Model for conversations
+ // Create the root model and view for all conversation sessions
LLConversationItem* base_item = new LLConversationItem(getRootViewModel());
LLFolderView::Params p(LLUICtrlFactory::getDefaultParams<LLFolderView>());
@@ -171,6 +174,10 @@ BOOL LLIMFloaterContainer::postBuild()
gIdleCallbacks.addFunction(idle, (void*)this);
mInitialized = true;
+
+ // Add callback: we'll take care of view updates on idle
+ gIdleCallbacks.addFunction(idle, this);
+
return TRUE;
}
@@ -383,6 +390,13 @@ void LLIMFloaterContainer::draw()
}
}
+ // CHUI-308 : Hack! We shouldn't have to do that but we have too as long as
+ // we don't have a scroll container.
+ // *TODO: Take those 3 lines out once we implement the scroll container.
+ repositioningWidgets();
+ mConversationsRoot->setRect(mConversationsListPanel->getLocalRect());
+ mConversationsRoot->setFollowsAll();
+
if (mTabContainer->getTabCount() == 0)
{
// Do not close the container when every conversation is torn off because the user
@@ -496,6 +510,13 @@ void LLIMFloaterContainer::updateState(bool collapse, S32 delta_width)
setCanResize(is_left_pane_expanded || is_right_pane_expanded);
setCanMinimize(is_left_pane_expanded || is_right_pane_expanded);
+ // force set correct size for the title after show/hide minimize button
+ LLRect cur_rect = getRect();
+ LLRect force_rect = cur_rect;
+ force_rect.mRight = cur_rect.mRight + 1;
+ setRect(force_rect);
+ setRect(cur_rect);
+
// restore floater's resize limits (prevent collapse when left panel is expanded)
if (is_left_pane_expanded && !is_right_pane_expanded)
{
@@ -625,7 +646,7 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid)
}
if (!item)
{
- llinfos << "Merov debug : Couldn't create conversation session item : " << display_name << llendl;
+ llwarns << "Couldn't create conversation session item : " << display_name << llendl;
return;
}
// *TODO: Should we flag LLConversationItemSession with a mIsNearbyChat?
@@ -645,7 +666,6 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid)
// Note: usually, we do not get an updated avatar list at that point
LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = item->getChildrenBegin();
LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = item->getChildrenEnd();
- llinfos << "Merov debug : create participant, children size = " << item->getChildrenCount() << llendl;
while (current_participant_model != end_participant_model)
{
LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>(*current_participant_model);
diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h
index 427baa03e3..bda1ce0cb1 100644
--- a/indra/newview/llimfloatercontainer.h
+++ b/indra/newview/llimfloatercontainer.h
@@ -77,6 +77,8 @@ public:
void collapseMessagesPane(bool collapse);
+ // Callbacks
+ static void idle(void* user_data);
// LLIMSessionObserver observe triggers
/*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id);
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index 073f5f00c5..3692658e9e 100644
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -387,13 +387,16 @@ void append_to_last_message(std::list<LLSD>& messages, const std::string& line)
}
// static
-void LLLogChat::loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, bool load_all_history/*= false*/)
+void LLLogChat::loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params)
{
if (file_name.empty())
{
llwarns << "Session name is Empty!" << llendl;
return ;
}
+
+ bool load_all_history = load_params.has("load_all_history") ? load_params["load_all_history"].asBoolean() : false;
+
//LL_INFOS("") << "Loading:" << file_name << LL_ENDL;/* uncomment if you want to verify step, delete on commit */
//LL_INFOS("") << "Current:" << makeLogFileName(file_name) << LL_ENDL;/* uncomment if you want to verify step, delete on commit */
LLFILE* fptr = LLFile::fopen(makeLogFileName(file_name), "r");/*Flawfinder: ignore*/
@@ -449,7 +452,7 @@ void LLLogChat::loadChatHistory(const std::string& file_name, std::list<LLSD>& m
else
{
LLSD item;
- if (!LLChatLogParser::parse(line, item))
+ if (!LLChatLogParser::parse(line, item, load_params))
{
item[IM_TEXT] = line;
}
@@ -500,10 +503,11 @@ void LLChatLogFormatter::format(const LLSD& im, std::ostream& ostr) const
}
}
-bool LLChatLogParser::parse(std::string& raw, LLSD& im)
+bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params)
{
if (!raw.length()) return false;
+ bool cut_off_todays_date = parse_params.has("cut_off_todays_date") ? parse_params["cut_off_todays_date"].asBoolean() : true;
im = LLSD::emptyMap();
//matching a timestamp
@@ -518,7 +522,12 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im)
boost::trim(timestamp);
timestamp.erase(0, 1);
timestamp.erase(timestamp.length()-1, 1);
- LLLogChatTimeScanner::instance().checkAndCutOffDate(timestamp);
+
+ if (cut_off_todays_date)
+ {
+ LLLogChatTimeScanner::instance().checkAndCutOffDate(timestamp);
+ }
+
im[IM_TIME] = timestamp;
}
else
diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h
index 95f83e64e5..d3e9adcc37 100644
--- a/indra/newview/lllogchat.h
+++ b/indra/newview/lllogchat.h
@@ -55,7 +55,7 @@ public:
void (*callback)(ELogLineType, const LLSD&, void*),
void* userdata);
- static void loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, bool load_all_history = false);
+ static void loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params = LLSD());
private:
static std::string cleanFileName(std::string filename);
};
@@ -105,7 +105,7 @@ public:
*
* @return false if failed to parse mandatory data - message text
*/
- static bool parse(std::string& raw, LLSD& im);
+ static bool parse(std::string& raw, LLSD& im, const LLSD& parse_params = LLSD());
protected:
LLChatLogParser();
diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp
index 2282734109..0d1a37c835 100644
--- a/indra/newview/llparticipantlist.cpp
+++ b/indra/newview/llparticipantlist.cpp
@@ -675,8 +675,6 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id)
// *TODO : Merov : need to update the online/offline status of the participant.
// Hack for this: LLAvatarTracker::instance().isBuddyOnline(avatar_id))
- llinfos << "Merov debug : added participant, name = " << participant->getName() << llendl;
-
// Add the participant model to the session's children list
addParticipant(participant);
diff --git a/indra/newview/skins/default/xui/en/floater_conversation_log.xml b/indra/newview/skins/default/xui/en/floater_conversation_log.xml
index 9cdeb0d788..df78bbccec 100644
--- a/indra/newview/skins/default/xui/en/floater_conversation_log.xml
+++ b/indra/newview/skins/default/xui/en/floater_conversation_log.xml
@@ -13,6 +13,11 @@
reuse_instance="true"
title="CONVERSATION LOG"
width="450">
+
+ <string name="logging_calls_disabled">
+ Conversations are not being logged. To log conversations in the future, select "Save IM logs in my computer" under Preferences > Privacy.
+ </string>
+
<panel
follows="left|top|right"
height="27"
diff --git a/indra/newview/skins/default/xui/en/floater_conversation_preview.xml b/indra/newview/skins/default/xui/en/floater_conversation_preview.xml
index d74c2c252d..0e5af67f68 100644
--- a/indra/newview/skins/default/xui/en/floater_conversation_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_conversation_preview.xml
@@ -14,41 +14,17 @@
name="Title">
CONVERSATION: [NAME]
</floater.string>
- <text
- type="string"
- length="1"
- follows="left|top"
- font="SansSerif"
- height="19"
- layout="topleft"
- left="10"
- name="desc txt"
- top="22"
- width="90">
- Description:
- </text>
- <line_editor
- border_style="line"
- border_thickness="1"
- enabled="false"
- follows="left|top|right"
- font="SansSerif"
- height="22"
- layout="topleft"
- left_pad="0"
- max_length_bytes="127"
- name="description"
- width="296" />
<chat_history
font="SansSerifSmall"
follows="all"
visible="true"
- height="310"
+ height="330"
name="chat_history"
notify_unread_msg="false"
parse_highlights="true"
parse_urls="true"
left="5"
+ top_pad="25"
width="390">
</chat_history>
<text
@@ -63,6 +39,7 @@
width="35">
</text>
<spinner
+ allow_digits_only="true"
decimal_digits="0"
follows="bottom|right"
height="23"
diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml
index 1583add857..413e66738d 100644
--- a/indra/newview/skins/default/xui/en/floater_im_container.xml
+++ b/indra/newview/skins/default/xui/en/floater_im_container.xml
@@ -36,7 +36,7 @@
name="conversations_layout_panel"
min_dim="38"
width="268"
- expanded_min_dim="165">
+ expanded_min_dim="120">
<layout_stack
animate="false"
follows="left|top|right"