diff options
Diffstat (limited to 'indra')
31 files changed, 478 insertions, 115 deletions
| diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index f67c134751..fdb4108afb 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -2072,7 +2072,7 @@ LLFolderViewItem* LLFolderViewFolder::getPreviousFromChild( LLFolderViewItem* it  		if (fit != fend)  		{  			// try selecting child element of this folder -			if ((*fit)->isOpen()) +			if ((*fit)->isOpen() && include_children)  			{  				result = (*fit)->getPreviousFromChild(NULL);  			} diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 91527c68f2..0c43a571b8 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -1483,6 +1483,8 @@ BOOL LLTabContainer::setTab(S32 which)  		for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)  		{  			LLTabTuple* tuple = *iter; +			if (!tuple) +				continue;  			BOOL is_selected = ( tuple == selected_tuple );  			tuple->mButton->setUseEllipses(mUseTabEllipses);  			tuple->mButton->setHAlign(mFontHalign); diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 7cee9f5b46..4bb819a7f6 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1911,6 +1911,7 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url)  	registrar.add("Url.Execute", boost::bind(&LLUrlAction::executeSLURL, url));  	registrar.add("Url.Teleport", boost::bind(&LLUrlAction::teleportToLocation, url));  	registrar.add("Url.ShowProfile", boost::bind(&LLUrlAction::showProfile, url)); +	registrar.add("Url.SendIM", boost::bind(&LLUrlAction::sendIM, url));  	registrar.add("Url.ShowOnMap", boost::bind(&LLUrlAction::showLocationOnMap, url));  	registrar.add("Url.CopyLabel", boost::bind(&LLUrlAction::copyLabelToClipboard, url));  	registrar.add("Url.CopyUrl", boost::bind(&LLUrlAction::copyURLToClipboard, url)); diff --git a/indra/llui/llurlaction.cpp b/indra/llui/llurlaction.cpp index fd9b3d9a6d..fd872eca4b 100644 --- a/indra/llui/llurlaction.cpp +++ b/indra/llui/llurlaction.cpp @@ -157,3 +157,17 @@ void LLUrlAction::showProfile(std::string url)  		}  	}  } + +void LLUrlAction::sendIM(std::string url) +{ +	LLURI uri(url); +	LLSD path_array = uri.pathArray(); +	if (path_array.size() == 4) +	{ +		std::string id_str = path_array.get(2).asString(); +		if (LLUUID::validate(id_str)) +		{ +			executeSLURL("secondlife:///app/agent/" + id_str + "/im"); +		} +	} +} diff --git a/indra/llui/llurlaction.h b/indra/llui/llurlaction.h index c34960b826..f5f2ceba72 100644 --- a/indra/llui/llurlaction.h +++ b/indra/llui/llurlaction.h @@ -76,6 +76,7 @@ public:  	/// if the Url specifies an SL command in the form like 'app/{cmd}/{id}/*', show its profile  	static void showProfile(std::string url); +	static void sendIM(std::string url);  	/// specify the callbacks to enable this class's functionality  	typedef boost::function<void (const std::string&)> url_callback_t; diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp index f7bc19574a..6899e9a44a 100644 --- a/indra/llvfs/lldir.cpp +++ b/indra/llvfs/lldir.cpp @@ -347,6 +347,11 @@ const std::string &LLDir::getLLPluginDir() const  	return mLLPluginDir;  } +const std::string &LLDir::getUserName() const +{ +	return mUserName; +} +  static std::string ELLPathToString(ELLPath location)  {  	typedef std::map<ELLPath, const char*> ELLPathMap; diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h index 95cab65149..cc10ed5bbd 100644 --- a/indra/llvfs/lldir.h +++ b/indra/llvfs/lldir.h @@ -104,6 +104,7 @@ class LLDir  	const std::string &getUserSkinDir() const;		// User-specified skin folder with user modifications. e.g. c:\documents and settings\username\application data\second life\skins\curskin  	const std::string getSkinBaseDir() const;		// folder that contains all installed skins (not user modifications). e.g. c:\program files\second life\skins  	const std::string &getLLPluginDir() const;		// Directory containing plugins and plugin shell +	const std::string &getUserName() const;  	// Expanded filename  	std::string getExpandedFilename(ELLPath location, const std::string &filename) const; diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index b777edba77..4be169e267 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -31,6 +31,8 @@  #include "llnotificationsutil.h"  #include "lltrans.h" +#include "boost/lexical_cast.hpp" +  const int CONVERSATION_LIFETIME = 30; // lifetime of LLConversation is 30 days by spec  struct ConversationParams @@ -378,6 +380,41 @@ void LLConversationLog::cache()  	}  } +bool LLConversationLog::moveLog(const std::string &originDirectory, const std::string &targetDirectory) +{ + +	std::string backupFileName; +	unsigned backupFileCount = 0; + +	//Does the file exist in the current path, if it does lets move it +	if(LLFile::isfile(originDirectory))  +	{ +		//The target directory contains that file already, so lets store it +		if(LLFile::isfile(targetDirectory)) +		{ +			backupFileName = targetDirectory + ".backup"; + +			//If needed store backup file as .backup1 etc. +			while(LLFile::isfile(backupFileName)) +			{ +				++backupFileCount; +				backupFileName = targetDirectory + ".backup" + boost::lexical_cast<std::string>(backupFileCount); +			} + +			//Rename the file to its backup name so it is not overwritten +			LLFile::rename(targetDirectory, backupFileName); +		} + +		//Move the file from the current path to target path +		if(LLFile::rename(originDirectory, targetDirectory) != 0) +		{ +			return false; +		} +	} + +	return true; +} +  std::string LLConversationLog::getFileName()  {  	std::string filename = "conversation"; diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index fd38556131..58e698de25 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -137,6 +137,7 @@ public:  	 * public method which is called on viewer exit to save conversation log  	 */  	void cache(); +	bool moveLog(const std::string &originDirectory, const std::string &targetDirectory);  	void onClearLog();  	void onClearLogResponse(const LLSD& notification, const LLSD& response); @@ -144,6 +145,12 @@ public:  	bool getIsLoggingEnabled() { return mLoggingEnabled; }  	bool isLogEmpty() { return mConversations.empty(); } +	/** +	 * constructs file name in which conversations log will be saved +	 * file name is conversation.log +	 */ +	std::string getFileName(); +  private:  	LLConversationLog(); @@ -164,12 +171,6 @@ private:  	void notifyParticularConversationObservers(const LLUUID& session_id, U32 mask); -	/** -	 * constructs file name in which conversations log will be saved -	 * file name is conversation.log -	 */ -	std::string getFileName(); -  	bool saveToFile(const std::string& filename);  	bool loadFromFile(const std::string& filename); diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 0977056b2a..009fce0a92 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -322,7 +322,7 @@ void LLConversationItemSession::setParticipantIsMuted(const LLUUID& participant_  	LLConversationItemParticipant* participant = findParticipant(participant_id);  	if (participant)  	{ -		participant->setIsMuted(is_muted); +		participant->muteVoice(is_muted);  	}  } @@ -462,7 +462,6 @@ void LLConversationItemSession::onAvatarNameCache(const LLAvatarName& av_name)  LLConversationItemParticipant::LLConversationItemParticipant(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) :  	LLConversationItem(display_name,uuid,root_view_model), -	mIsMuted(false),  	mIsModerator(false),  	mDisplayModeratorLabel(false),  	mDistToAgent(-1.0) @@ -473,7 +472,6 @@ LLConversationItemParticipant::LLConversationItemParticipant(std::string display  LLConversationItemParticipant::LLConversationItemParticipant(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) :  	LLConversationItem(uuid,root_view_model), -	mIsMuted(false),  	mIsModerator(false),  	mDisplayModeratorLabel(false),  	mDistToAgent(-1.0) @@ -549,7 +547,7 @@ LLConversationItemSession* LLConversationItemParticipant::getParentSession()  void LLConversationItemParticipant::dumpDebugData()  { -	llinfos << "Merov debug : participant, uuid = " << mUUID << ", name = " << mName << ", display name = " << mDisplayName << ", muted = " << mIsMuted << ", moderator = " << mIsModerator << llendl; +	llinfos << "Merov debug : participant, uuid = " << mUUID << ", name = " << mName << ", display name = " << mDisplayName << ", muted = " << isVoiceMuted() << ", moderator = " << mIsModerator << llendl;  }  void LLConversationItemParticipant::setDisplayModeratorRole(bool displayRole) @@ -561,6 +559,29 @@ void LLConversationItemParticipant::setDisplayModeratorRole(bool displayRole)  	}  } +bool LLConversationItemParticipant::isVoiceMuted() +{ +	return LLMuteList::getInstance()->isMuted(mUUID, LLMute::flagVoiceChat); +} + +void LLConversationItemParticipant::muteVoice(bool mute_voice) +{ +	std::string name; +	gCacheName->getFullName(mUUID, name); +	LLMuteList * mute_listp = LLMuteList::getInstance(); +	bool voice_already_muted = mute_listp->isMuted(mUUID, name); + +	LLMute mute(mUUID, name, LLMute::AGENT); +	if (voice_already_muted && !mute_voice) +	{ +		mute_listp->remove(mute); +	} +	else if (!voice_already_muted && mute_voice) +	{ +		mute_listp->add(mute); +	} +} +  //  // LLConversationSort  //  diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index c907d1d6d2..8766585049 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -189,9 +189,9 @@ public:  	virtual const std::string& getDisplayName() const { return mDisplayName; } -	bool isMuted() { return mIsMuted; } -	bool isModerator() {return mIsModerator; } -	void setIsMuted(bool is_muted) { mIsMuted = is_muted; mNeedsRefresh = true; } +	bool isVoiceMuted(); +	bool isModerator() const { return mIsModerator; } +	void muteVoice(bool mute_voice);  	void setIsModerator(bool is_moderator) { mIsModerator = is_moderator; mNeedsRefresh = true; }  	void setTimeNow() { mLastActiveTime = LLFrameTimer::getElapsedSeconds(); mNeedsRefresh = true; }  	void setDistance(F64 dist) { mDistToAgent = dist; mNeedsRefresh = true; } diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 73b2c6f88c..74b348cd81 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -527,19 +527,6 @@ S32 LLConversationViewParticipant::arrange(S32* width, S32* height)      return arranged;  } -void LLConversationViewParticipant::refresh() -{ -	// Refresh the participant view from its model data -	LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(getViewModelItem()); -	participant_model->resetRefresh(); -	 -	// *TODO: We should also do something with vmi->isModerator() to echo that state in the UI somewhat -	mSpeakingIndicator->setIsMuted(participant_model->isMuted()); -	 -	// Do the regular upstream refresh -	LLFolderViewItem::refresh(); -} -  void LLConversationViewParticipant::addToFolder(LLFolderViewFolder* folder)  {      // Add the item to the folder (conversation) @@ -580,6 +567,7 @@ BOOL LLConversationViewParticipant::handleMouseDown( S32 x, S32 y, MASK mask )      		LLFloaterIMContainer *im_container = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");      		LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(session_id); +			im_container->setSelectedSession(session_id);  			im_container->flashConversationItemWidget(session_id,false);  			im_container->selectFloater(session_floater);  			im_container->collapseMessagesPane(false); diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index f9b45073f4..76d3d079ea 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -130,7 +130,6 @@ public:      virtual ~LLConversationViewParticipant( void );      bool hasSameValue(const LLUUID& uuid) { return (uuid == mUUID); } -    virtual void refresh();      void addToFolder(LLFolderViewFolder* folder);  	void addToSession(const LLUUID& session_id); diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 59c2f15dd9..4b0d3b361d 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -577,6 +577,12 @@ F32 LLDrawable::updateXform(BOOL undamped)  			mVObjp->dirtySpatialGroup();  		}  	} +	else if (!isRoot() && +			((dist_vec_squared(old_pos, target_pos) > 0.f) +			|| (1.f - dot(old_rot, target_rot)) > 0.f)) +	{ //fix for BUG-840, MAINT-2275, MAINT-1742, MAINT-2247 +			gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE); +	}  	else if (!getVOVolume() && !isAvatar())  	{  		movePartition(); @@ -643,18 +649,9 @@ BOOL LLDrawable::updateMove()  		return FALSE;  	} -	BOOL done; +	makeActive(); -	if (isState(MOVE_UNDAMPED)) -	{ -		done = updateMoveUndamped(); -	} -	else -	{ -		makeActive(); -		done = updateMoveDamped(); -	} -	return done; +	return isState(MOVE_UNDAMPED) ? updateMoveUndamped() : updateMoveDamped();  }  BOOL LLDrawable::updateMoveUndamped() diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index c5edd11c12..413707baae 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -605,7 +605,7 @@ void LLFloaterIMContainer::setVisible(BOOL visible)              setSelectedSession(LLUUID(NULL));  		}  		openNearbyChat(); -        selectConversationPair(getSelectedSession(), false); +        selectConversationPair(getSelectedSession(), false, false);  	}  	nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); @@ -759,11 +759,19 @@ void LLFloaterIMContainer::assignResizeLimits()      S32 number_of_visible_borders = llmin((is_conv_pane_expanded? 2 : 0) + (is_msg_pane_expanded? 2 : 0), 3);      S32 summary_width_of_visible_borders = number_of_visible_borders * LLPANEL_BORDER_WIDTH;  	S32 conv_pane_current_width = is_msg_pane_expanded -			? mConversationsPane->getRect().getWidth() +			? (is_conv_pane_expanded? mConversationsPane->getRect().getWidth() : mConversationsPane->getMinDim())  			: (is_conv_pane_expanded? mConversationsPane->getExpandedMinDim() : mConversationsPane->getMinDim());  	S32 msg_pane_min_width  = is_msg_pane_expanded ? mMessagesPane->getExpandedMinDim() : 0;  	S32 new_min_width = conv_pane_current_width + msg_pane_min_width + summary_width_of_visible_borders; +    if (is_conv_pane_expanded) +    { +    	// Save the conversations pane width. +	    gSavedPerAccountSettings.setS32( +	            "ConversationsListPaneWidth", +                mConversationsPane->getRect().getWidth()); +    } +  	setResizeLimits(new_min_width, getMinHeight());  } @@ -1096,12 +1104,9 @@ void LLFloaterIMContainer::doToSelectedConversation(const std::string& command,          }          else if("chat_history" == command)          { -			const LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(conversationItem->getUUID()); - -			if (NULL != session) +			if (selectedIDS.size() > 0)  			{ -				const LLUUID session_id = session->isOutgoingAdHoc() ? session->generateOutgouigAdHocHash() : session->mSessionID; -				LLFloaterReg::showInstance("preview_conversation", session_id, true); +				LLAvatarActions::viewChatHistory(selectedIDS.front());  			}          }          else @@ -1165,15 +1170,9 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata)  	}  	//Enable Chat history item for ad-hoc and group conversations -	if ("can_chat_history" == item) +	if ("can_chat_history" == item && uuids.size() > 0)  	{ -		if(getCurSelectedViewModelItem()) -		{ -			if (getCurSelectedViewModelItem()->getType() != LLConversationItem::CONV_PARTICIPANT) -			{ -				return isConversationLoggingAllowed(); -			} -		} +		return LLLogChat::isTranscriptExist(uuids.front());  	}  	// If nothing is selected(and selected item is not group chat), everything needs to be disabled @@ -1213,6 +1212,15 @@ bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_v  		return false;  	} +	// If the user agent is selected with others, everything is disabled +	for (uuid_vec_t::const_iterator id = uuids.begin(); id != uuids.end(); ++id) +	{ +		if (gAgent.getID() == *id) +		{ +			return false; +		} +	} +  	// Handle all other options  	if (("can_invite" == item) || ("can_chat_history" == item) || ("can_share" == item) || ("can_pay" == item))  	{ @@ -1339,30 +1347,19 @@ void LLFloaterIMContainer::selectConversation(const LLUUID& session_id)  // Select the conversation *after* (or before if none after) the passed uuid conversation  // Used to change the selection on key hits -void LLFloaterIMContainer::selectNextConversation(const LLUUID& uuid) +void LLFloaterIMContainer::selectNextConversationByID(const LLUUID& uuid)  { -	LLFolderViewItem* new_selection = NULL; -	LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,uuid); -	if (widget) +	bool new_selection = false; +	selectConversation(uuid); +	new_selection = selectNextorPreviousConversation(true); +	if (!new_selection)  	{ -		new_selection = mConversationsRoot->getNextFromChild(widget, FALSE); -		if (!new_selection) -		{ -			new_selection = mConversationsRoot->getPreviousFromChild(widget, FALSE); -		} -	} -	if (new_selection) -	{ -		LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(new_selection->getViewModelItem()); -		if (vmi) -		{ -			selectConversationPair(vmi->getUUID(), true); -		} +		selectNextorPreviousConversation(false);  	}  }  // Synchronous select the conversation item and the conversation floater -BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool select_widget) +BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool select_widget, bool focus_floater/*=true*/)  {      BOOL handled = TRUE;      LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(session_id); @@ -1409,7 +1406,7 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool  		if (!session_floater->hasFocus())  		{  			BOOL is_minimized = session_floater->isMinimized(); -			session_floater->setFocus(TRUE); +			session_floater->setFocus(focus_floater);  			session_floater->setMinimized(is_minimized);  		}  	} @@ -1887,16 +1884,81 @@ bool LLFloaterIMContainer::isScrolledOutOfSight(LLConversationViewSession* conve  	return !mConversationsRoot->getVisibleRect().overlaps(widget_rect);  } +BOOL LLFloaterIMContainer::handleKeyHere(KEY key, MASK mask ) +{ +	if(mask == MASK_ALT) +	{ +		if (KEY_RETURN == key ) +		{ +			expandConversation(); +		} + +		if ((KEY_DOWN == key ) || (KEY_RIGHT == key)) +		{ +			selectNextorPreviousConversation(true); +		} +		if ((KEY_UP == key) || (KEY_LEFT == key)) +		{ +			selectNextorPreviousConversation(false); +		} +	} +	return TRUE; +} + +bool LLFloaterIMContainer::selectNextorPreviousConversation(bool select_next) +{ +	if (mConversationsWidgets.size() > 1) +	{ +		LLFolderViewItem* new_selection = NULL; +		LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,getSelectedSession()); +		if (widget) +		{ +			if(select_next) +			{ +				new_selection = mConversationsRoot->getNextFromChild(widget, FALSE); +			} +			else +			{ +				new_selection = mConversationsRoot->getPreviousFromChild(widget, FALSE); +			} +			if (new_selection) +			{ +				LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(new_selection->getViewModelItem()); +				if (vmi) +				{ +					selectConversationPair(vmi->getUUID(), true); +					LLFloater* floaterp = get_ptr_in_map(mSessions, getSelectedSession()); +					if(floaterp && !floaterp->isTornOff()) +					{ +						setFocus(TRUE); +					} +					return true; +				} +			} +		} +	} +	return false; +} + +void LLFloaterIMContainer::expandConversation() +{ +	LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(get_ptr_in_map(mConversationsWidgets,getSelectedSession())); +	if (widget) +	{ +		widget->setOpen(!widget->isOpen()); +	} +} +  void LLFloaterIMContainer::closeFloater(bool app_quitting/* = false*/)  {  	// Always unminimize before trying to close.  	// Most of the time the user will never see this state.  	setMinimized(FALSE); -	S32 conv_pane_width = mConversationsPane->getRect().getWidth(); - -	// Save the conversations pane width before collapsing it. -	gSavedPerAccountSettings.setS32("ConversationsListPaneWidth", conv_pane_width); +	// Save the conversations pane width. +	gSavedPerAccountSettings.setS32( +			"ConversationsListPaneWidth", +			mConversationsPane->getRect().getWidth());  	LLFloater::closeFloater(app_quitting);  } diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 419239f90b..c84d4978ec 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -69,9 +69,11 @@ public:  	void returnFloaterToHost();      void showConversation(const LLUUID& session_id);      void selectConversation(const LLUUID& session_id); -	void selectNextConversation(const LLUUID& session_id); -    BOOL selectConversationPair(const LLUUID& session_id, bool select_widget); +	void selectNextConversationByID(const LLUUID& session_id); +    BOOL selectConversationPair(const LLUUID& session_id, bool select_widget, bool focus_floater = true);      void clearAllFlashStates(); +    bool selectNextorPreviousConversation(bool select_next); +    void expandConversation();  	/*virtual*/ void tabClose();  	void showStub(bool visible); @@ -109,7 +111,7 @@ public:      void doToParticipants(const std::string& item, uuid_vec_t& selectedIDS);  	void assignResizeLimits(); - +	virtual BOOL handleKeyHere(KEY key, MASK mask );  	/*virtual*/ void closeFloater(bool app_quitting = false);  private: diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index a3b81e037a..dfaf4bbdd6 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -150,7 +150,7 @@ void LLFloaterIMNearbyChat::closeHostedFloater()  		{  			setVisible(FALSE);  		} -		floater_container->selectNextConversation(LLUUID()); +		floater_container->selectNextConversationByID(LLUUID());  	}  } @@ -353,6 +353,28 @@ BOOL LLFloaterIMNearbyChat::handleKeyHere( KEY key, MASK mask )  		sendChat(CHAT_TYPE_SHOUT);  		handled = TRUE;  	} +	else if (KEY_RETURN == key && mask == MASK_SHIFT) +	{ +		// whisper +		sendChat(CHAT_TYPE_WHISPER); +		handled = TRUE; +	} + + +	if((mask == MASK_ALT) && isTornOff()) +	{ +		LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance(); +		if ((KEY_UP == key) || (KEY_LEFT == key)) +		{ +			floater_container->selectNextorPreviousConversation(false); +			handled = TRUE; +		} +		if ((KEY_DOWN == key ) || (KEY_RIGHT == key)) +		{ +			floater_container->selectNextorPreviousConversation(true); +			handled = TRUE; +		} +	}  	return handled;  } diff --git a/indra/newview/llfloaterimnearbychat.h b/indra/newview/llfloaterimnearbychat.h index 2992c12436..4ad37eb0c7 100644 --- a/indra/newview/llfloaterimnearbychat.h +++ b/indra/newview/llfloaterimnearbychat.h @@ -69,6 +69,7 @@ public:  	LLChatEntry* getChatBox() { return mInputEditor; }  	std::string getCurrentChat(); +	S32 getMessageArchiveLength() {return mMessageArchive.size();}  	virtual BOOL handleKeyHere( KEY key, MASK mask ); diff --git a/indra/newview/llfloaterimsession.h b/indra/newview/llfloaterimsession.h index 381b3cf721..cb330bca0f 100644 --- a/indra/newview/llfloaterimsession.h +++ b/indra/newview/llfloaterimsession.h @@ -133,6 +133,7 @@ public:  	static floater_showed_signal_t sIMFloaterShowedSignal;  	bool needsTitleOverwrite() { return mSessionNameUpdatedForTyping && mOtherTyping; } +	S32 getLastChatMessageIndex() {return mLastMessageIndex;}  private:  	/*virtual*/ void refresh(); diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 6dbcdb4474..d3fcfbbc56 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -725,6 +725,27 @@ void LLFloaterIMSessionTab::processChatHistoryStyleUpdate(bool clean_messages/*  	}  } +// static +void LLFloaterIMSessionTab::reloadEmptyFloaters() +{ +	LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel"); +	for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); +		iter != inst_list.end(); ++iter) +	{ +		LLFloaterIMSession* floater = dynamic_cast<LLFloaterIMSession*>(*iter); +		if (floater && floater->getLastChatMessageIndex() == -1) +		{ +			floater->reloadMessages(true); +		} +	} + +	LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); +	if (nearby_chat && nearby_chat->getMessageArchiveLength() == 0) +	{ +		nearby_chat->reloadMessages(true); +	} +} +  void LLFloaterIMSessionTab::updateCallBtnState(bool callIsActive)  {  	LLButton* voiceButton = getChild<LLButton>("voice_call_btn"); @@ -918,3 +939,24 @@ LLConversationItem* LLFloaterIMSessionTab::getCurSelectedViewModelItem()  	return conversationItem;  } + +BOOL LLFloaterIMSessionTab::handleKeyHere(KEY key, MASK mask ) +{ +	if(mask == MASK_ALT) +	{ +		LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance(); +		if (KEY_RETURN == key && !isTornOff()) +		{ +			floater_container->expandConversation(); +		} +		if ((KEY_UP == key) || (KEY_LEFT == key)) +		{ +			floater_container->selectNextorPreviousConversation(false); +		} +		if ((KEY_DOWN == key ) || (KEY_RIGHT == key)) +		{ +			floater_container->selectNextorPreviousConversation(true); +		} +	} +	return TRUE; +} diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index e90fcbb806..d55b021df7 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -54,6 +54,7 @@ public:  	// reload all message with new settings of visual modes  	static void processChatHistoryStyleUpdate(bool clean_messages = false); +	static void reloadEmptyFloaters();  	/**  	 * Returns true if chat is displayed in multi tabbed floater @@ -95,8 +96,8 @@ public:  	void initBtns();  	virtual void updateMessages() {}  	LLConversationItem* getCurSelectedViewModelItem(); -  	void forceReshape(); +	virtual BOOL handleKeyHere( KEY key, MASK mask );  protected: diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 688d453789..3f8c23ba83 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -798,13 +798,28 @@ void LLFloaterPreference::onBtnOK()  		//Conversation transcript and log path changed so reload conversations based on new location  		if(mPriorInstantMessageLogPath.length())  		{ -			std::string dir_name(gSavedPerAccountSettings.getString("InstantMessageLogPath")); -			updateLogLocation(dir_name); +			if(moveTranscriptsAndLog()) +			{ +				//When floaters are empty but have a chat history files, reload chat history into them +				LLFloaterIMSessionTab::reloadEmptyFloaters(); +			} +			//Couldn't move files so restore the old path and show a notification +			else +			{ +				gSavedPerAccountSettings.setString("InstantMessageLogPath", mPriorInstantMessageLogPath); +				LLNotificationsUtil::add("PreferenceChatPathChanged"); +			}  			mPriorInstantMessageLogPath.clear();  		}  		LLUIColorTable::instance().saveUserSettings();  		gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE); +		 +		//Only save once logged in and loaded per account settings +		if(mGotPersonalInfo) +		{ +			gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE); +	}  	}  	else  	{ @@ -1441,9 +1456,9 @@ void LLFloaterPreference::setAllIgnored()  void LLFloaterPreference::onClickLogPath()  { -	std::string proposed_name(gSavedPerAccountSettings.getString("InstantMessageLogPath")); +	std::string proposed_name(gSavedPerAccountSettings.getString("InstantMessageLogPath"));	   	mPriorInstantMessageLogPath.clear(); - +	  	LLDirPicker& picker = LLDirPicker::instance();  	//Launches a directory picker and waits for feedback  	if (!picker.getDir(&proposed_name ) ) @@ -1457,22 +1472,76 @@ void LLFloaterPreference::onClickLogPath()  	//Path changed  	if(proposed_name != dir_name)  	{ -		gSavedPerAccountSettings.setString("InstantMessageLogPath", dir_name); +	gSavedPerAccountSettings.setString("InstantMessageLogPath", dir_name);  		mPriorInstantMessageLogPath = proposed_name; - -		// enable/disable 'Delete transcripts button -		updateDeleteTranscriptsButton(); -	} +	 +	// enable/disable 'Delete transcripts button +	updateDeleteTranscriptsButton(); +}  } -void LLFloaterPreference::updateLogLocation(const std::string& dir_name) +bool LLFloaterPreference::moveTranscriptsAndLog()  { -	gDirUtilp->setChatLogsDir(dir_name); +	std::string instantMessageLogPath(gSavedPerAccountSettings.getString("InstantMessageLogPath")); +	std::string chatLogPath = gDirUtilp->add(instantMessageLogPath, gDirUtilp->getUserName()); + +	bool madeDirectory = false; + +	//Does the directory really exist, if not then make it +	if(!LLFile::isdir(chatLogPath)) +	{ +		//mkdir success is defined as zero +		if(LLFile::mkdir(chatLogPath) != 0) +		{ +			return false; +		} +		madeDirectory = true; +	} +	 +	std::string originalConversationLogDir = LLConversationLog::instance().getFileName(); +	std::string targetConversationLogDir = gDirUtilp->add(chatLogPath, "conversation.log"); +	//Try to move the conversation log +	if(!LLConversationLog::instance().moveLog(originalConversationLogDir, targetConversationLogDir)) +	{ +		//Couldn't move the log and created a new directory so remove the new directory +		if(madeDirectory) +		{ +			LLFile::rmdir(chatLogPath); +		} +		return false; +	} + +	//Attempt to move transcripts +	std::vector<std::string> listOfTranscripts; +	std::vector<std::string> listOfFilesMoved; + +	LLLogChat::getListOfTranscriptFiles(listOfTranscripts); + +	if(!LLLogChat::moveTranscripts(gDirUtilp->getChatLogsDir(),  +									instantMessageLogPath,  +									listOfTranscripts, +									listOfFilesMoved)) +	{ +		//Couldn't move all the transcripts so restore those that moved back to their old location +		LLLogChat::moveTranscripts(instantMessageLogPath,  +			gDirUtilp->getChatLogsDir(),  +			listOfFilesMoved); + +		//Move the conversation log back +		LLConversationLog::instance().moveLog(targetConversationLogDir, originalConversationLogDir); + +		if(madeDirectory) +		{ +			LLFile::rmdir(chatLogPath); +		} + +		return false; +	} + +	gDirUtilp->setChatLogsDir(instantMessageLogPath);  	gDirUtilp->updatePerAccountChatLogsDir(); -	LLFile::mkdir(gDirUtilp->getPerAccountChatLogsDir()); -	// refresh IM floaters with new logs from files from new selected directory -	LLFloaterIMSessionTab::processChatHistoryStyleUpdate(true); +	return true;  }  void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im_via_email) diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 31c1e2d9e5..22e80a21cb 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -143,7 +143,7 @@ public:  	void resetAllIgnored();  	void setAllIgnored();  	void onClickLogPath(); -	void updateLogLocation(const std::string& dir_name); +	bool moveTranscriptsAndLog();  	void enableHistory();  	void setPersonalInfo(const std::string& visibility, bool im_via_email);  	void refreshEnabledState(); diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index d69bd89f13..8f3f5145a9 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -273,7 +273,7 @@ void on_new_message(const LLSD& msg)  		}      } -    else if("openconversations" == action && !session_floater_is_open) +    else if("openconversations" == action)      {          //User is not focused on conversation containing the message          if(session_floater_not_focused) @@ -291,7 +291,8 @@ void on_new_message(const LLSD& msg)              //useMostItrusiveIMNotification will be called to notify user a message exists              if(session_id.notNull()                   && participant_id.notNull() -                && gAgent.isDoNotDisturb()) +                && gAgent.isDoNotDisturb() +				&& !session_floater_is_open)              {                  LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg));  			} diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 09f816a4e6..448100c5d6 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -502,6 +502,81 @@ boost::signals2::connection LLLogChat::setSaveHistorySignal(const save_history_s  }  //static +bool LLLogChat::moveTranscripts(const std::string originDirectory,  +								const std::string targetDirectory,  +								std::vector<std::string>& listOfFilesToMove, +								std::vector<std::string>& listOfFilesMoved) +{ +	std::string newFullPath; +	bool movedAllTranscripts = true; +	std::string backupFileName; +	unsigned backupFileCount; + +	BOOST_FOREACH(const std::string& fullpath, listOfFilesToMove) +	{ +		backupFileCount = 0; +		newFullPath = targetDirectory + fullpath.substr(originDirectory.length(), std::string::npos); + +		//The target directory contains that file already, so lets store it +		if(LLFile::isfile(newFullPath)) +		{ +			backupFileName = newFullPath + ".backup"; + +			//If needed store backup file as .backup1 etc. +			while(LLFile::isfile(backupFileName)) +			{ +				++backupFileCount; +				backupFileName = newFullPath + ".backup" + boost::lexical_cast<std::string>(backupFileCount); +			} + +			//Rename the file to its backup name so it is not overwritten +			LLFile::rename(newFullPath, backupFileName); +		} + +		S32 retry_count = 0; +		while (retry_count < 5) +		{ +			//success is zero +			if (LLFile::rename(fullpath, newFullPath) != 0) +			{ +				retry_count++; +				S32 result = errno; +				LL_WARNS("LLLogChat::moveTranscripts") << "Problem renaming " << fullpath << " - errorcode: " +					<< result << " attempt " << retry_count << LL_ENDL; + +				ms_sleep(100); +			} +			else +			{ +				listOfFilesMoved.push_back(newFullPath); + +				if (retry_count) +				{ +					LL_WARNS("LLLogChat::moveTranscripts") << "Successfully renamed " << fullpath << LL_ENDL; +				} +				break; +			}			 +		} +	} + +	if(listOfFilesMoved.size() != listOfFilesToMove.size()) +	{ +		movedAllTranscripts = false; +	}		 + +	return movedAllTranscripts; +} + +//static +bool LLLogChat::moveTranscripts(const std::string currentDirectory,  +	const std::string newDirectory,  +	std::vector<std::string>& listOfFilesToMove) +{ +	std::vector<std::string> listOfFilesMoved; +	return moveTranscripts(currentDirectory, newDirectory, listOfFilesToMove, listOfFilesMoved); +} + +//static  void LLLogChat::deleteTranscripts()  {  	std::vector<std::string> list_of_transcriptions; diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h index b981d9ce04..784786a565 100644 --- a/indra/newview/lllogchat.h +++ b/indra/newview/lllogchat.h @@ -56,6 +56,14 @@ public:  	typedef boost::signals2::signal<void ()> save_history_signal_t;  	static boost::signals2::connection setSaveHistorySignal(const save_history_signal_t::slot_type& cb); +	static bool moveTranscripts(const std::string currentDirectory,  +									const std::string newDirectory,  +									std::vector<std::string>& listOfFilesToMove, +									std::vector<std::string>& listOfFilesMoved); +	static bool moveTranscripts(const std::string currentDirectory,  +		const std::string newDirectory,  +		std::vector<std::string>& listOfFilesToMove); +  	static void deleteTranscripts();  	static bool isTranscriptExist(const LLUUID& avatar_id); diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index f6e3c0cac0..6c26073d5b 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -284,12 +284,12 @@ void LLOutputMonitorCtrl::setSpeakerId(const LLUUID& speaker_id, const LLUUID& s  	{  		if (speaker_id == gAgentID)  		{ -			setIsMuted(false); +			mIsMuted = false;  		}  		else  		{  			// check only blocking on voice. EXT-3542 -			setIsMuted(LLMuteList::getInstance()->isMuted(mSpeakerId, LLMute::flagVoiceChat)); +			mIsMuted = LLMuteList::getInstance()->isMuted(mSpeakerId, LLMute::flagVoiceChat);  			LLMuteList::getInstance()->addObserver(this);  		}  	} @@ -298,7 +298,7 @@ void LLOutputMonitorCtrl::setSpeakerId(const LLUUID& speaker_id, const LLUUID& s  void LLOutputMonitorCtrl::onChange()  {  	// check only blocking on voice. EXT-3542 -	setIsMuted(LLMuteList::getInstance()->isMuted(mSpeakerId, LLMute::flagVoiceChat)); +	mIsMuted = LLMuteList::getInstance()->isMuted(mSpeakerId, LLMute::flagVoiceChat);  }  // virtual diff --git a/indra/newview/lloutputmonitorctrl.h b/indra/newview/lloutputmonitorctrl.h index af2fd45823..a346909027 100644 --- a/indra/newview/lloutputmonitorctrl.h +++ b/indra/newview/lloutputmonitorctrl.h @@ -73,9 +73,6 @@ public:  	void			setPower(F32 val);  	F32				getPower(F32 val) const { return mPower; } -	bool			getIsMuted() const { return mIsMuted; } -	void			setIsMuted(bool val) { mIsMuted = val; } -  	// For the current user, need to know the PTT state to show  	// correct button image.  	void			setIsAgentControl(bool val) { mIsAgentControl = val; } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index e6e93d81bc..e44a2cc4df 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2515,7 +2515,9 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)  			{  				// let Control-Up and Control-Down through for chat line history,  				if (!(key == KEY_UP && mask == MASK_CONTROL) -					&& !(key == KEY_DOWN && mask == MASK_CONTROL)) +					&& !(key == KEY_DOWN && mask == MASK_CONTROL) +					&& !(key == KEY_UP && mask == MASK_ALT) +					&& !(key == KEY_DOWN && mask == MASK_ALT))  				{  					switch(key)  					{ @@ -2607,7 +2609,10 @@ BOOL LLViewerWindow::handleUnicodeChar(llwchar uni_char, MASK mask)  	if ((uni_char == 13 && mask != MASK_CONTROL)  		|| (uni_char == 3 && mask == MASK_NONE))  	{ -		return gViewerKeyboard.handleKey(KEY_RETURN, mask, gKeyboard->getKeyRepeated(KEY_RETURN)); +		if (mask != MASK_ALT) +		{ +			return gViewerKeyboard.handleKey(KEY_RETURN, mask, gKeyboard->getKeyRepeated(KEY_RETURN)); +		}  	}  	// let menus handle navigation (jump) keys diff --git a/indra/newview/skins/default/xui/en/menu_url_agent.xml b/indra/newview/skins/default/xui/en/menu_url_agent.xml index 73f0fa7979..88ae441bd3 100644 --- a/indra/newview/skins/default/xui/en/menu_url_agent.xml +++ b/indra/newview/skins/default/xui/en/menu_url_agent.xml @@ -3,6 +3,13 @@   layout="topleft"   name="Url Popup">      <menu_item_call +     label="Send IM" +     layout="topleft" +     name="show_agent"> +        <menu_item_call.on_click +         function="Url.SendIM" />         +    </menu_item_call> +    <menu_item_call       label="Show Resident Profile"       layout="topleft"       name="show_agent"> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 3ae9b206a4..88c02fc84e 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -9708,14 +9708,6 @@ No room to sit here, try another spot.    <notification     icon="alertmodal.tga" -   name="AutopilotCanceled" -   type="notify"> -   <tag>fail</tag> -Autopilot canceled -  </notification> - -  <notification -   icon="alertmodal.tga"     name="ClaimObjectFailedNoPermission"     type="notify">     <tag>fail</tag> @@ -10028,4 +10020,15 @@ Cannot create large prims that intersect other players.  Please re-try when othe       yestext="OK"/>    </notification> +  <notification +   icon="alert.tga" +   name="PreferenceChatPathChanged" +   type="alert"> +   Unable to move files. Restored previous path. +    <usetemplate +     ignoretext="Unable to move files. Restored previous path." +     name="okignore" +     yestext="OK"/> +  </notification> +    </notifications> | 
