diff options
Diffstat (limited to 'indra')
162 files changed, 3508 insertions, 1458 deletions
| diff --git a/indra/cmake/BuildVersion.cmake b/indra/cmake/BuildVersion.cmake index b9ec8f5266..af2063ce6d 100755 --- a/indra/cmake/BuildVersion.cmake +++ b/indra/cmake/BuildVersion.cmake @@ -18,7 +18,7 @@ if (NOT DEFINED VIEWER_SHORT_VERSION) # will be true in indra/, false in indra/n             find_program(MERCURIAL hg)             if (DEFINED MERCURIAL)                execute_process( -                 COMMAND ${MERCURIAL} log -r tip --template "{p1rev}" +                 COMMAND ${MERCURIAL} log -r tip --template "{rev}"                   OUTPUT_VARIABLE VIEWER_VERSION_REVISION                   OUTPUT_STRIP_TRAILING_WHITESPACE                   ) diff --git a/indra/edit-me-to-trigger-new-build.txt b/indra/edit-me-to-trigger-new-build.txt index e003ed7788..774e8c0676 100755 --- a/indra/edit-me-to-trigger-new-build.txt +++ b/indra/edit-me-to-trigger-new-build.txt @@ -3,3 +3,4 @@ Wed Nov  7 00:25:19 UTC 2012 + diff --git a/indra/lib/python/indra/util/llmanifest.py b/indra/lib/python/indra/util/llmanifest.py index 9cb830a2db..54049b5545 100755 --- a/indra/lib/python/indra/util/llmanifest.py +++ b/indra/lib/python/indra/util/llmanifest.py @@ -392,11 +392,21 @@ class LLManifest(object):              raise ManifestError, "Should be something at path " + path          self.created_paths.append(path) -    def put_in_file(self, contents, dst): +    def put_in_file(self, contents, dst, src=None):          # write contents as dst -        f = open(self.dst_path_of(dst), "wb") -        f.write(contents) -        f.close() +        dst_path = self.dst_path_of(dst) +        f = open(dst_path, "wb") +        try: +            f.write(contents) +        finally: +            f.close() + +        # Why would we create a file in the destination tree if not to include +        # it in the installer? The default src=None (plus the fact that the +        # src param is last) is to preserve backwards compatibility. +        if src: +            self.file_list.append([src, dst_path]) +        return dst_path      def replace_in(self, src, dst=None, searchdict={}):          if dst == None: diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp index f188865eb0..3e68ef068e 100755 --- a/indra/llcommon/tests/llprocess_test.cpp +++ b/indra/llcommon/tests/llprocess_test.cpp @@ -608,9 +608,6 @@ namespace tut      void object::test<5>()      {          set_test_name("exit(2)"); -#if LL_WINDOWS -		skip("MAINT-2302: This frequently (though not always) fails on Windows."); -#endif          PythonProcessLauncher py(get_test_name(),                                   "import sys\n"                                   "sys.exit(2)\n"); @@ -622,10 +619,7 @@ namespace tut      template<> template<>      void object::test<6>()      { -        set_test_name("syntax_error:"); -#if LL_WINDOWS -		skip("MAINT-2302: This frequently (though not always) fails on Windows."); -#endif +        set_test_name("syntax_error");          PythonProcessLauncher py(get_test_name(),                                   "syntax_error:\n");          py.mParams.files.add(LLProcess::FileParam()); // inherit stdin @@ -647,9 +641,6 @@ namespace tut      void object::test<7>()      {          set_test_name("explicit kill()"); -#if LL_WINDOWS -		skip("MAINT-2302: This frequently (though not always) fails on Windows."); -#endif          PythonProcessLauncher py(get_test_name(),                                   "from __future__ import with_statement\n"                                   "import sys, time\n" @@ -694,9 +685,6 @@ namespace tut      void object::test<8>()      {          set_test_name("implicit kill()"); -#if LL_WINDOWS -		skip("MAINT-2302: This frequently (though not always) fails on Windows."); -#endif          NamedTempFile out("out", "not started");          LLProcess::handle phandle(0);          { diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 4ccb019106..50ac511d18 100755 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -648,7 +648,7 @@ void LLButton::draw()      //  Cancel sticking of color, if the button is pressed,  	//  or when a flashing of the previously selected button is ended  	if (mFlashingTimer -		&& ((selected && !mFlashingTimer->isFlashingInProgress()) || pressed)) +		&& ((selected && !mFlashingTimer->isFlashingInProgress() && !mForceFlashing) || pressed))  	{  		mFlashing = false;  	} @@ -975,8 +975,9 @@ void LLButton::setToggleState(BOOL b)  	}  } -void LLButton::setFlashing(bool b)	 +void LLButton::setFlashing(bool b, bool force_flashing/* = false */)  {  +	mForceFlashing = force_flashing;  	if (mFlashingTimer)  	{  		mFlashing = b;  diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index 060db59a8a..7b4719866d 100755 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -201,7 +201,7 @@ public:  	void			setToggleState(BOOL b);  	void			setHighlight(bool b); -	void			setFlashing( bool b ); +	void			setFlashing( bool b, bool force_flashing = false );  	BOOL			getFlashing() const		{ return mFlashing; }      LLFlashTimer*   getFlashTimer() {return mFlashingTimer;} @@ -378,7 +378,7 @@ protected:  	LLFrameTimer				mFrameTimer;  	LLFlashTimer *				mFlashingTimer; - +	bool                        mForceFlashing; // Stick flashing color even if button is pressed  	bool						mHandleRightMouse;  }; diff --git a/indra/llui/llchatentry.cpp b/indra/llui/llchatentry.cpp index 6a1b48a08a..c04b70eb64 100755 --- a/indra/llui/llchatentry.cpp +++ b/indra/llui/llchatentry.cpp @@ -62,9 +62,9 @@ void LLChatEntry::draw()  {  	if(mIsExpandable)  	{ +		reflow();  		expandText();  	} -  	LLTextEditor::draw();  } @@ -158,19 +158,21 @@ void LLChatEntry::onValueChange(S32 start, S32 end)      resetLabel();  } -bool LLChatEntry::useLabel() +bool LLChatEntry::useLabel() const  {      return !getLength() && !mLabel.empty();  }  void LLChatEntry::onFocusReceived()  { - +	LLUICtrl::onFocusReceived(); +	updateAllowingLanguageInput();  }  void LLChatEntry::onFocusLost()  { - +	LLTextEditor::focusLostHelper(); +	LLUICtrl::onFocusLost();  }  BOOL LLChatEntry::handleSpecialKey(const KEY key, const MASK mask) diff --git a/indra/llui/llchatentry.h b/indra/llui/llchatentry.h index 49c8d21450..e67f39b21b 100755 --- a/indra/llui/llchatentry.h +++ b/indra/llui/llchatentry.h @@ -56,14 +56,14 @@ protected:  	LLChatEntry(const Params& p);      /*virtual*/ void    beforeValueChange();      /*virtual*/ void    onValueChange(S32 start, S32 end); -    /*virtual*/ bool    useLabel(); +    /*virtual*/ bool    useLabel() const;  public:  	virtual void	draw();  	virtual	void	onCommit(); -    /*virtual*/ void	onFocusReceived(); -    /*virtual*/ void	onFocusLost(); +	/*virtual*/ void	onFocusReceived(); +	/*virtual*/ void	onFocusLost();  	void enableSingleLineMode(bool single_line_mode);  	boost::signals2::connection setTextExpandedCallback(const commit_signal_t::slot_type& cb); diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 913de49d63..d44b1ad51a 100755 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -507,22 +507,11 @@ LLFloater::~LLFloater()  {  	LLFloaterReg::removeInstance(mInstanceName, mKey); -//	delete mNotificationContext; -//	mNotificationContext = NULL; - -	//// am I not hosted by another floater? -	//if (mHostHandle.isDead()) -	//{ -	//	LLFloaterView* parent = (LLFloaterView*) getParent(); - -	//	if( parent ) -	//	{ -	//		parent->removeChild( this ); -	//	} -	//} - -	// Just in case we might still have focus here, release it. -	releaseFocus(); +	if( gFocusMgr.childHasKeyboardFocus(this)) +	{ +		// Just in case we might still have focus here, release it. +		releaseFocus(); +	}  	// This is important so that floaters with persistent rects (i.e., those  	// created with rect control rather than an LLRect) are restored in their @@ -1490,6 +1479,7 @@ void LLFloater::moveResizeHandlesToFront()  	}  } +/*virtual*/  BOOL LLFloater::isFrontmost()  {  	LLFloaterView* floater_view = getParentByType<LLFloaterView>(); @@ -1508,7 +1498,7 @@ void LLFloater::addDependentFloater(LLFloater* floaterp, BOOL reposition)  		floaterp->setRect(gFloaterView->findNeighboringPosition(this, floaterp));  		floaterp->setSnapTarget(getHandle());  	} -	gFloaterView->adjustToFitScreen(floaterp, FALSE); +	gFloaterView->adjustToFitScreen(floaterp, FALSE, TRUE);  	if (floaterp->isFrontmost())  	{  		// make sure to bring self and sibling floaters to front @@ -2754,7 +2744,7 @@ void LLFloaterView::refresh()  const S32 FLOATER_MIN_VISIBLE_PIXELS = 16; -void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_outside) +void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_outside, BOOL snap_in_toolbars/* = false*/)  {  	if (floater->getParent() != this)  	{ @@ -2807,7 +2797,7 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out  	}  	// move window fully onscreen -	if (floater->translateIntoRect( getSnapRect(), allow_partial_outside ? FLOATER_MIN_VISIBLE_PIXELS : S32_MAX )) +	if (floater->translateIntoRect( snap_in_toolbars ? getSnapRect() : gFloaterView->getRect(), allow_partial_outside ? FLOATER_MIN_VISIBLE_PIXELS : S32_MAX ))  	{  		floater->clearSnapTarget();  	} @@ -3277,6 +3267,11 @@ bool LLFloater::isShown() const      return ! isMinimized() && isInVisibleChain();  } +bool LLFloater::isDetachedAndNotMinimized() +{ +	return !getHost() && !isMinimized(); +} +  /* static */  bool LLFloater::isShown(const LLFloater* floater)  { diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 09fe2219c0..b6ff04e000 100755 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -238,6 +238,7 @@ public:  	void			center();  	LLMultiFloater* getHost(); +	bool isDetachedAndNotMinimized();  	void			applyTitle();  	std::string		getCurrentTitle() const; @@ -261,7 +262,7 @@ public:  	static bool     isVisible(const LLFloater* floater);  	static bool     isMinimized(const LLFloater* floater);  	BOOL			isFirstLook() { return mFirstLook; } // EXT-2653: This function is necessary to prevent overlapping for secondary showed toasts -	BOOL			isFrontmost(); +	virtual BOOL	isFrontmost();  	BOOL			isDependent()					{ return !mDependeeHandle.isDead(); }  	void			setCanMinimize(BOOL can_minimize);  	void			setCanClose(BOOL can_close); @@ -529,7 +530,7 @@ public:  	LLRect			findNeighboringPosition( LLFloater* reference_floater, LLFloater* neighbor );  	// Given a child of gFloaterView, make sure this view can fit entirely onscreen. -	void			adjustToFitScreen(LLFloater* floater, BOOL allow_partial_outside); +	void			adjustToFitScreen(LLFloater* floater, BOOL allow_partial_outside, BOOL snap_in_toolbars = false);  	void			setMinimizePositionVerticalOffset(S32 offset) { mMinimizePositionVOffset = offset; }  	void			getMinimizePosition( S32 *left, S32 *bottom); diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp index 1cdddf0d5b..b1b75776a7 100755 --- a/indra/llui/llfloaterreg.cpp +++ b/indra/llui/llfloaterreg.cpp @@ -356,8 +356,8 @@ std::string LLFloaterReg::declareRectControl(const std::string& name)  {  	std::string controlname = getRectControlName(name);  	LLFloater::getControlGroup()->declareRect(controlname, LLRect(), -												 llformat("Window Size for %s", name.c_str()), -												 TRUE); +											  llformat("Window Size for %s", name.c_str()), +											  LLControlVariable::PERSIST_NONDFT);  	return controlname;  } @@ -367,7 +367,7 @@ std::string LLFloaterReg::declarePosXControl(const std::string& name)  	LLFloater::getControlGroup()->declareF32(controlname,   											10.f,  											llformat("Window X Position for %s", name.c_str()), -											TRUE); +											LLControlVariable::PERSIST_NONDFT);  	return controlname;  } @@ -377,7 +377,7 @@ std::string LLFloaterReg::declarePosYControl(const std::string& name)  	LLFloater::getControlGroup()->declareF32(controlname,  											10.f,  											llformat("Window Y Position for %s", name.c_str()), -											TRUE); +											LLControlVariable::PERSIST_NONDFT);  	return controlname;  } @@ -404,7 +404,7 @@ std::string LLFloaterReg::declareVisibilityControl(const std::string& name)  	std::string controlname = getVisibilityControlName(name);  	LLFloater::getControlGroup()->declareBOOL(controlname, FALSE,  												 llformat("Window Visibility for %s", name.c_str()), -												 TRUE); +												 LLControlVariable::PERSIST_NONDFT);  	return controlname;  } @@ -414,7 +414,7 @@ std::string LLFloaterReg::declareDockStateControl(const std::string& name)  	std::string controlname = getDockStateControlName(name);  	LLFloater::getControlGroup()->declareBOOL(controlname, TRUE,  												 llformat("Window Docking state for %s", name.c_str()), -												 TRUE); +												 LLControlVariable::PERSIST_NONDFT);  	return controlname;  } diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 8aa1eb7cd5..cf449217f5 100755 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -323,9 +323,11 @@ static LLFastTimer::DeclareTimer FTM_FILTER("Filter Folder View");  void LLFolderView::filter( LLFolderViewFilter& filter )  { +    // Entry point of inventory filtering (CHUI-849)  	LLFastTimer t2(FTM_FILTER); -	filter.setFilterCount(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsPerFrame"), 1, 5000)); +    filter.resetTime(llclamp(LLUI::sSettingGroups["config"]->getS32(mParentPanel->getVisible() ? "FilterItemsMaxTimePerFrameVisible" : "FilterItemsMaxTimePerFrameUnvisible"), 1, 100)); +    // Note: we filter the model, not the view  	getViewModelItem()->filter(filter);  } @@ -661,7 +663,7 @@ void LLFolderView::draw()  		// get preferable text height...  		S32 pixel_height = mStatusTextBox->getTextPixelHeight(); -		bool height_changed = local_rect.getHeight() != pixel_height; +		bool height_changed = (local_rect.getHeight() < pixel_height);  		if (height_changed)  		{  			// ... if it does not match current height, lets rearrange current view. @@ -1601,15 +1603,17 @@ void LLFolderView::update()  	{  		mNeedsAutoSelect = TRUE;  	} -	// filter to determine visibility before arranging +     +	// Filter to determine visibility before arranging  	filter(getFolderViewModel()->getFilter()); -	// Clear the modified setting on the filter only if the filter count is non-zero after running the filter process -	// Note: if the filter count is zero, then the filter most likely halted before completing the entire set of items -	if (getFolderViewModel()->getFilter().isModified() && (getFolderViewModel()->getFilter().getFilterCount() > 0)) +     +	// Clear the modified setting on the filter only if the filter finished after running the filter process +	// Note: if the filter count has timed out, that means the filter halted before completing the entire set of items +    if (getFolderViewModel()->getFilter().isModified() && (!getFolderViewModel()->getFilter().isTimedOut()))  	{  		getFolderViewModel()->getFilter().clearModified();  	} - +      	// automatically show matching items, and select first one if we had a selection  	if (mNeedsAutoSelect)  	{ @@ -1649,11 +1653,13 @@ void LLFolderView::update()    BOOL is_visible = isInVisibleChain(); -  //Puts folders/items in proper positions -  if ( is_visible ) +  // Puts folders/items in proper positions +  // arrange() takes the model filter flag into account and call sort() if necessary (CHUI-849) +  // It also handles the open/close folder animation +  if (is_visible)    {      sanitizeSelection(); -    if( needsArrange() ) +    if (needsArrange())      {        S32 height = 0;        S32 width = 0; diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index fdb4108afb..6c147ccc12 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -274,6 +274,7 @@ void LLFolderViewItem::refresh()  	}  	mLabelWidthDirty = true; +    // Dirty the filter flag of the model from the view (CHUI-849)  	vmi.dirtyFilter();  } @@ -943,11 +944,17 @@ void LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder)  static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange"); -// Finds width and height of this object and its children. Also -// makes sure that this view and its children are the right size. +// Make everything right and in the right place ready for drawing (CHUI-849) +// * Sort everything correctly if necessary +// * Turn widgets visible/invisible according to their model filtering state +// * Takes animation state into account for opening/closing of folders (this makes widgets visible/invisible) +// * Reposition visible widgets so that they line up correctly with no gap +// * Compute the width and height of the current folder and its children +// * Makes sure that this view and its children are the right size  S32 LLFolderViewFolder::arrange( S32* width, S32* height )  { -	// sort before laying out contents +	// Sort before laying out contents +    // Note that we sort from the root (CHUI-849)  	getRoot()->getFolderViewModel()->sort(this);  	LLFastTimer t2(FTM_ARRANGE); @@ -1613,16 +1620,13 @@ void LLFolderViewFolder::addFolder(LLFolderViewFolder* folder)  }  void LLFolderViewFolder::requestArrange() -{  -	if ( mLastArrangeGeneration != -1) -	{ -		mLastArrangeGeneration = -1;  -		// flag all items up to root -		if (mParentFolder) -		{ -			mParentFolder->requestArrange(); -		} -	} +{ +    mLastArrangeGeneration = -1; +    // flag all items up to root +    if (mParentFolder) +    { +        mParentFolder->requestArrange(); +    }  }  void LLFolderViewFolder::toggleOpen() diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index ca31931e19..a9b0201236 100755 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -316,7 +316,6 @@ protected:  	F32			mAutoOpenCountdown;  	S32			mLastArrangeGeneration;  	S32			mLastCalculatedWidth; -	S32			mMostFilteredDescendantGeneration;  	bool		mNeedsSort;  public: diff --git a/indra/llui/llfolderviewmodel.cpp b/indra/llui/llfolderviewmodel.cpp index 3593804554..3363dc5316 100755 --- a/indra/llui/llfolderviewmodel.cpp +++ b/indra/llui/llfolderviewmodel.cpp @@ -48,7 +48,7 @@ std::string LLFolderViewModelCommon::getStatusText()  void LLFolderViewModelCommon::filter()  { -	getFilter().setFilterCount(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsPerFrame"), 1, 5000)); +    getFilter().resetTime(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsMaxTimePerFrameVisible"), 1, 100));  	mFolderView->getViewModelItem()->filter(getFilter());  } diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index 1b61212c0e..b1bcc8bbb4 100755 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -87,12 +87,11 @@ public:  	virtual void 				setModified(EFilterModified behavior = FILTER_RESTART) = 0;  	// +-------------------------------------------------------------------+ -	// + Count +	// + Time  	// +-------------------------------------------------------------------+ -	virtual void 				setFilterCount(S32 count) = 0; -	virtual S32 				getFilterCount() const = 0; -	virtual void 				decrementFilterCount() = 0; - +	virtual void 				resetTime(S32 timeout) = 0; +    virtual bool                isTimedOut() = 0; +      	// +-------------------------------------------------------------------+  	// + Default  	// +-------------------------------------------------------------------+ @@ -308,26 +307,28 @@ public:  	virtual bool potentiallyVisible()  	{  		return passedFilter() // we've passed the filter -			|| getLastFilterGeneration() < mRootViewModel.getFilter().getFirstSuccessGeneration() // or we don't know yet +			|| (getLastFilterGeneration() < mRootViewModel.getFilter().getFirstSuccessGeneration()) // or we don't know yet  			|| descendantsPassedFilter();  	}  	virtual bool passedFilter(S32 filter_generation = -1)   	{  -		if (filter_generation < 0)  +		if (filter_generation < 0) +        {  			filter_generation = mRootViewModel.getFilter().getFirstSuccessGeneration(); - -		bool passed_folder_filter = mPassedFolderFilter && mLastFolderFilterGeneration >= filter_generation; -		bool passed_filter = mPassedFilter && mLastFilterGeneration >= filter_generation; -		return passed_folder_filter -				&& (descendantsPassedFilter(filter_generation) -					|| passed_filter); +        } +		bool passed_folder_filter = mPassedFolderFilter && (mLastFolderFilterGeneration >= filter_generation); +		bool passed_filter = mPassedFilter && (mLastFilterGeneration >= filter_generation); +		return passed_folder_filter && (passed_filter || descendantsPassedFilter(filter_generation));  	}  	virtual bool descendantsPassedFilter(S32 filter_generation = -1)  	{  -		if (filter_generation < 0) filter_generation = mRootViewModel.getFilter().getFirstSuccessGeneration(); -		return mMostFilteredDescendantGeneration >= filter_generation;  +		if (filter_generation < 0) +        { +            filter_generation = mRootViewModel.getFilter().getFirstSuccessGeneration(); +        } +		return mMostFilteredDescendantGeneration >= filter_generation;  	} diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index e33ac1d5c2..c89c0203b4 100755 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -214,8 +214,15 @@ LLLayoutStack::Params::Params()  	open_time_constant("open_time_constant", 0.02f),  	close_time_constant("close_time_constant", 0.03f),  	resize_bar_overlap("resize_bar_overlap", 1), -	border_size("border_size", LLCachedControl<S32>(*LLUI::sSettingGroups["config"], "UIResizeBarHeight", 0)) -{} +	border_size("border_size", LLCachedControl<S32>(*LLUI::sSettingGroups["config"], "UIResizeBarHeight", 0)), +	show_drag_handle("show_drag_handle", false), +	drag_handle_first_indent("drag_handle_first_indent", 0), +	drag_handle_second_indent("drag_handle_second_indent", 0), +	drag_handle_thickness("drag_handle_thickness", 5), +	drag_handle_shift("drag_handle_shift", 2) +{ +	addSynonym(border_size, "drag_handle_gap"); +}  LLLayoutStack::LLLayoutStack(const LLLayoutStack::Params& p)   :	LLView(p), @@ -227,8 +234,14 @@ LLLayoutStack::LLLayoutStack(const LLLayoutStack::Params& p)  	mClip(p.clip),  	mOpenTimeConstant(p.open_time_constant),  	mCloseTimeConstant(p.close_time_constant), -	mResizeBarOverlap(p.resize_bar_overlap) -{} +	mResizeBarOverlap(p.resize_bar_overlap), +	mShowDragHandle(p.show_drag_handle), +	mDragHandleFirstIndent(p.drag_handle_first_indent), +	mDragHandleSecondIndent(p.drag_handle_second_indent), +	mDragHandleThickness(p.drag_handle_thickness), +	mDragHandleShift(p.drag_handle_shift) +{ +}  LLLayoutStack::~LLLayoutStack()  { @@ -262,6 +275,26 @@ void LLLayoutStack::draw()  			drawChild(panelp, 0, 0, !clip_rect.isEmpty());  		}  	} + +	const LLView::child_list_t * child_listp = getChildList(); +	BOOST_FOREACH(LLView * childp, * child_listp) +	{ +		LLResizeBar * resize_barp = dynamic_cast<LLResizeBar*>(childp); +		if (resize_barp && resize_barp->isShowDragHandle() && resize_barp->getVisible() && resize_barp->getRect().isValid()) +		{ +			LLRect screen_rect = resize_barp->calcScreenRect(); +			if (LLUI::getRootView()->getLocalRect().overlaps(screen_rect) && LLUI::sDirtyRect.overlaps(screen_rect)) +			{ +				LLUI::pushMatrix(); +				{ +					const LLRect& rb_rect(resize_barp->getRect()); +					LLUI::translate(rb_rect.mLeft, rb_rect.mBottom); +					resize_barp->draw(); +				} +				LLUI::popMatrix(); +			} +		} +	}  }  void LLLayoutStack::removeChild(LLView* view) @@ -390,7 +423,6 @@ void LLLayoutStack::updateLayout()  	BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)  	{  		F32 panel_dim = llmax(panelp->getExpandedMinDim(), panelp->mTargetDim); -		F32 panel_visible_dim = panelp->getVisibleDim();  		LLRect panel_rect;  		if (mOrientation == HORIZONTAL) @@ -407,27 +439,61 @@ void LLLayoutStack::updateLayout()  										getRect().getWidth(),  										llround(panel_dim));  		} -		panelp->setIgnoreReshape(true); -		panelp->setShape(panel_rect); -		panelp->setIgnoreReshape(false);  		LLRect resize_bar_rect(panel_rect); - +		LLResizeBar * resize_barp = panelp->getResizeBar(); +		bool show_drag_handle = resize_barp->isShowDragHandle();  		F32 panel_spacing = (F32)mPanelSpacing * panelp->getVisibleAmount(); +		F32 panel_visible_dim = panelp->getVisibleDim(); +		S32 panel_spacing_round = (S32)(llround(panel_spacing)); +  		if (mOrientation == HORIZONTAL)  		{ -			resize_bar_rect.mLeft = panel_rect.mRight - mResizeBarOverlap; -			resize_bar_rect.mRight = panel_rect.mRight + (S32)(llround(panel_spacing)) + mResizeBarOverlap; -  			cur_pos += panel_visible_dim + panel_spacing; + +			if (show_drag_handle && panel_spacing_round > mDragHandleThickness) +			{ +				resize_bar_rect.mLeft = panel_rect.mRight + mDragHandleShift; +				resize_bar_rect.mRight = resize_bar_rect.mLeft + mDragHandleThickness; +			} +			else +			{ +				resize_bar_rect.mLeft = panel_rect.mRight - mResizeBarOverlap; +				resize_bar_rect.mRight = panel_rect.mRight + panel_spacing_round + mResizeBarOverlap; +			} + +			if (show_drag_handle) +			{ +				resize_bar_rect.mBottom += mDragHandleSecondIndent; +				resize_bar_rect.mTop -= mDragHandleFirstIndent; +			} +  		}  		else //VERTICAL  		{ -			resize_bar_rect.mTop = panel_rect.mBottom + mResizeBarOverlap; -			resize_bar_rect.mBottom = panel_rect.mBottom - (S32)(llround(panel_spacing)) - mResizeBarOverlap; -  			cur_pos -= panel_visible_dim + panel_spacing; + +			if (show_drag_handle && panel_spacing_round > mDragHandleThickness) +			{ +				resize_bar_rect.mTop = panel_rect.mBottom - mDragHandleShift; +				resize_bar_rect.mBottom = resize_bar_rect.mTop - mDragHandleThickness; +			} +			else +			{ +				resize_bar_rect.mTop = panel_rect.mBottom + mResizeBarOverlap; +				resize_bar_rect.mBottom = panel_rect.mBottom - panel_spacing_round - mResizeBarOverlap; +			} + +			if (show_drag_handle) +			{ +				resize_bar_rect.mLeft += mDragHandleFirstIndent; +				resize_bar_rect.mRight -= mDragHandleSecondIndent; +			}  		} + +		panelp->setIgnoreReshape(true); +		panelp->setShape(panel_rect); +		panelp->setIgnoreReshape(false);  		panelp->mResizeBar->setShape(resize_bar_rect);  	} @@ -475,14 +541,13 @@ void LLLayoutStack::createResizeBar(LLLayoutPanel* panelp)  	{  		if (lp->mResizeBar == NULL)  		{ -			LLResizeBar::Side side = (mOrientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM; -  			LLResizeBar::Params resize_params;  			resize_params.name("resize");  			resize_params.resizing_view(lp);  			resize_params.min_size(lp->getRelevantMinDim()); -			resize_params.side(side); +			resize_params.side((mOrientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM);  			resize_params.snapping_enabled(false); +			resize_params.show_drag_handle(mShowDragHandle);  			LLResizeBar* resize_bar = LLUICtrlFactory::create<LLResizeBar>(resize_params);  			lp->mResizeBar = resize_bar;  			LLView::addChild(resize_bar, 0); @@ -864,3 +929,4 @@ void LLLayoutStack::updateResizeBarLimits()  		previous_visible_panelp = visible_panelp;  	}  } + diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index 02c664f1a0..b570974bd6 100755 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -62,6 +62,11 @@ public:  		Optional<F32>			open_time_constant,  								close_time_constant;  		Optional<S32>			resize_bar_overlap; +		Optional<bool>			show_drag_handle; +		Optional<S32>			drag_handle_first_indent; +		Optional<S32>			drag_handle_second_indent; +		Optional<S32>			drag_handle_thickness; +		Optional<S32>			drag_handle_shift;  		Params();  	}; @@ -126,6 +131,11 @@ private:  	F32  mCloseTimeConstant;  	bool mNeedsLayout;  	S32  mResizeBarOverlap; +	bool mShowDragHandle; +	S32  mDragHandleFirstIndent; +	S32  mDragHandleSecondIndent; +	S32  mDragHandleThickness; +	S32  mDragHandleShift;  }; // end class LLLayoutStack diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index f7bf39c897..f854e1785d 100755 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -3146,6 +3146,13 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y)  	const S32 CURSOR_HEIGHT = 22;		// Approximate "normal" cursor size  	const S32 CURSOR_WIDTH = 12; +	if (menu->getChildList()->empty()) +	{ +		return; +	} + +	menu->setVisible( TRUE ); +  	//Do not show menu if all menu items are disabled  	BOOL item_enabled = false;  	for (LLView::child_list_t::const_iterator itor = menu->getChildList()->begin(); @@ -3156,8 +3163,9 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y)  		item_enabled = item_enabled || menu_item->getEnabled();  	} -	if(menu->getChildList()->empty() || !item_enabled) +	if(!item_enabled)  	{ +		menu->setVisible( FALSE );  		return;  	} @@ -3173,8 +3181,6 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y)  		menu->mFirstVisibleItem = NULL;  	} -	menu->setVisible( TRUE ); -  	// Fix menu rect if needed.  	menu->needsArrange();  	menu->arrangeAndClear(); diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 743d34c57b..26ede21572 100755 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -214,7 +214,7 @@ LLNotificationForm::LLNotificationForm(const std::string& name, const LLNotifica  		}  		else  		{ -			LLUI::sSettingGroups["ignores"]->declareBOOL(name, show_notification, "Show notification with this name", TRUE); +			LLUI::sSettingGroups["ignores"]->declareBOOL(name, show_notification, "Show notification with this name", LLControlVariable::PERSIST_NONDFT);  			mIgnoreSetting = LLUI::sSettingGroups["ignores"]->getControl(name);  		}  	} diff --git a/indra/llui/llresizebar.cpp b/indra/llui/llresizebar.cpp index 15e56cbfe5..e67b22c977 100755 --- a/indra/llui/llresizebar.cpp +++ b/indra/llui/llresizebar.cpp @@ -28,14 +28,53 @@  #include "llresizebar.h" +#include "lllocalcliprect.h"  #include "llmath.h"  #include "llui.h"  #include "llmenugl.h"  #include "llfocusmgr.h"  #include "llwindow.h" +class LLImagePanel : public LLPanel +{ +public: +	struct Params :	public LLInitParam::Block<Params, LLPanel::Params> +	{ +		Optional<bool> horizontal; +		Params() : horizontal("horizontal", false) {} +	}; +	LLImagePanel(const Params& p) : LLPanel(p), mHorizontal(p.horizontal) {} +	virtual ~LLImagePanel() {} + +	void draw() +	{ +		const LLRect& parent_rect = getParent()->getRect(); +		const LLRect& rect = getRect(); +		LLRect clip_rect( -rect.mLeft, parent_rect.getHeight() - rect.mBottom - 2 +						 , parent_rect.getWidth() - rect.mLeft - (mHorizontal ? 2 : 0), -rect.mBottom); +		LLLocalClipRect clip(clip_rect); +		LLPanel::draw(); +	} + +private: +	bool mHorizontal; +}; + +static LLDefaultChildRegistry::Register<LLImagePanel> t1("resize_bar_image_panel"); + +LLResizeBar::Params::Params() +:	max_size("max_size", S32_MAX), +	snapping_enabled("snapping_enabled", true), +	resizing_view("resizing_view"), +	side("side"), +	allow_double_click_snapping("allow_double_click_snapping", true), +	show_drag_handle("show_drag_handle", false) +{ +	name = "resize_bar"; +} +  LLResizeBar::LLResizeBar(const LLResizeBar::Params& p) -:	LLView(p), +:	LLPanel(p),  	mDragLastScreenX( 0 ),  	mDragLastScreenY( 0 ),  	mLastMouseScreenX( 0 ), @@ -46,7 +85,9 @@ LLResizeBar::LLResizeBar(const LLResizeBar::Params& p)  	mSnappingEnabled(p.snapping_enabled),  	mAllowDoubleClickSnapping(p.allow_double_click_snapping),  	mResizingView(p.resizing_view), -	mResizeListener(NULL) +	mResizeListener(NULL), +	mShowDragHandle(p.show_drag_handle), +	mImagePanel(NULL)  {  	setFollowsNone();  	// set up some generically good follow code. @@ -75,8 +116,37 @@ LLResizeBar::LLResizeBar(const LLResizeBar::Params& p)  	default:  		break;  	} + +	if (mShowDragHandle) +	{ +		LLViewBorder::Params border_params; +		border_params.border_thickness = 1; +		border_params.highlight_light_color = LLUIColorTable::instance().getColor("ResizebarBorderLight"); +		border_params.shadow_dark_color = LLUIColorTable::instance().getColor("ResizebarBorderDark"); + +		addBorder(border_params); +		setBorderVisible(TRUE); + +		LLImagePanel::Params image_panel; +		mDragHandleImage = LLUI::getUIImage(LLResizeBar::RIGHT == mSide ? "Vertical Drag Handle" : "Horizontal Drag Handle"); +		image_panel.bg_alpha_image = mDragHandleImage; +		image_panel.background_visible = true; +		image_panel.horizontal = (LLResizeBar::BOTTOM == mSide); +		mImagePanel = LLUICtrlFactory::create<LLImagePanel>(image_panel); +		setImagePanel(mImagePanel); +	}  } +BOOL LLResizeBar::postBuild() +{ +	if (mShowDragHandle) +	{ +		setBackgroundVisible(TRUE); +		setTransparentColor(LLUIColorTable::instance().getColor("ResizebarBody")); +	} + +	return LLPanel::postBuild(); +}  BOOL LLResizeBar::handleMouseDown(S32 x, S32 y, MASK mask)  { @@ -342,3 +412,39 @@ BOOL LLResizeBar::handleDoubleClick(S32 x, S32 y, MASK mask)  	return TRUE;  } +void LLResizeBar::setImagePanel(LLPanel * panelp) +{ +	const LLView::child_list_t * children = getChildList(); +	if (getChildCount() == 2) +	{ +		LLPanel * image_panelp = dynamic_cast<LLPanel*>(children->back()); +		if (image_panelp) +		{ +			removeChild(image_panelp); +			delete image_panelp; +		} +	} + +	addChild(panelp); +	sendChildToBack(panelp); +} + +LLPanel * LLResizeBar::getImagePanel() const +{ +	return getChildCount() > 0 ? (LLPanel *)getChildList()->back() : NULL; +} + +void LLResizeBar::draw() +{ +	if (mShowDragHandle) +	{ +		S32 image_width = mDragHandleImage->getTextureWidth(); +		S32 image_height = mDragHandleImage->getTextureHeight(); +		const LLRect& panel_rect = getRect(); +		S32 image_left = (panel_rect.getWidth() - image_width) / 2 - 1; +		S32 image_bottom = (panel_rect.getHeight() - image_height) / 2; +		mImagePanel->setRect(LLRect(image_left, image_bottom + image_height, image_left + image_width, image_bottom)); +	} + +	LLPanel::draw(); +} diff --git a/indra/llui/llresizebar.h b/indra/llui/llresizebar.h index 8190a95a71..bcf8ea0b40 100755 --- a/indra/llui/llresizebar.h +++ b/indra/llui/llresizebar.h @@ -27,15 +27,14 @@  #ifndef LL_RESIZEBAR_H  #define LL_RESIZEBAR_H -#include "llview.h" -#include "llcoord.h" +#include "llpanel.h" -class LLResizeBar : public LLView +class LLResizeBar : public LLPanel  {  public:  	enum Side { LEFT, TOP, RIGHT, BOTTOM }; -	struct Params : public LLInitParam::Block<Params, LLView::Params> +	struct Params : public LLInitParam::Block<Params, LLPanel::Params>  	{  		Mandatory<LLView*> resizing_view;  		Mandatory<Side>	side; @@ -44,24 +43,19 @@ public:  		Optional<S32>	max_size;  		Optional<bool>	snapping_enabled;  		Optional<bool>	allow_double_click_snapping; +		Optional<bool>	show_drag_handle; -		Params() -		:	max_size("max_size", S32_MAX), -			snapping_enabled("snapping_enabled", true), -			resizing_view("resizing_view"), -			side("side"), -			allow_double_click_snapping("allow_double_click_snapping", true) -		{ -			name = "resize_bar"; -		} +		Params();  	};  protected:  	LLResizeBar(const LLResizeBar::Params& p);  	friend class LLUICtrlFactory; + +	/*virtual*/ BOOL postBuild();  public: -//	virtual void	draw();  No appearance +	virtual void	draw();  	virtual BOOL	handleHover(S32 x, S32 y, MASK mask);  	virtual BOOL	handleMouseDown(S32 x, S32 y, MASK mask);  	virtual BOOL	handleMouseUp(S32 x, S32 y, MASK mask); @@ -72,20 +66,26 @@ public:  	void			setAllowDoubleClickSnapping(BOOL allow) { mAllowDoubleClickSnapping = allow; }  	bool			canResize() { return getEnabled() && mMaxSize > mMinSize; }  	void            setResizeListener(boost::function<void(void*)> listener) {mResizeListener = listener;} +	BOOL			isShowDragHandle() const { return mShowDragHandle; } +	void			setImagePanel(LLPanel * panelp); +	LLPanel *		getImagePanel() const;  private: -	S32				mDragLastScreenX; -	S32				mDragLastScreenY; -	S32				mLastMouseScreenX; -	S32				mLastMouseScreenY; -	LLCoordGL		mLastMouseDir; -	S32				mMinSize; -	S32				mMaxSize; -	const Side		mSide; -	BOOL			mSnappingEnabled; -	BOOL			mAllowDoubleClickSnapping; -	LLView*			mResizingView; -	boost::function<void(void*)>  mResizeListener; +	S32								mDragLastScreenX; +	S32								mDragLastScreenY; +	S32								mLastMouseScreenX; +	S32								mLastMouseScreenY; +	LLCoordGL						mLastMouseDir; +	S32								mMinSize; +	S32								mMaxSize; +	const Side						mSide; +	BOOL							mSnappingEnabled; +	BOOL							mAllowDoubleClickSnapping; +	BOOL							mShowDragHandle; +	LLView*							mResizingView; +	boost::function<void(void*)>	mResizeListener; +	LLPointer<LLUIImage>			mDragHandleImage; +	LLPanel *						mImagePanel;  };  #endif  // LL_RESIZEBAR_H diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 4adfd42edd..6e03f604a2 100755 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -1183,10 +1183,10 @@ LLScrollListItem* LLScrollListCtrl::addSeparator(EAddPosition pos)  // Selects first enabled item of the given name.  // Returns false if item not found.  // Calls getItemByLabel in order to combine functionality -BOOL LLScrollListCtrl::selectItemByLabel(const std::string& label, BOOL case_sensitive) +BOOL LLScrollListCtrl::selectItemByLabel(const std::string& label, BOOL case_sensitive, S32 column/* = 0*/)  {  	deselectAllItems(TRUE); 	// ensure that no stale items are selected, even if we don't find a match -	LLScrollListItem* item = getItemByLabel(label, case_sensitive); +	LLScrollListItem* item = getItemByLabel(label, case_sensitive, column);  	bool found = NULL != item;  	if(found) diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index 7bc558f742..c61e281a31 100755 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -241,7 +241,7 @@ public:  	// one of which can be selected at a time.  	virtual LLScrollListItem* addSimpleElement(const std::string& value, EAddPosition pos = ADD_BOTTOM, const LLSD& id = LLSD()); -	BOOL			selectItemByLabel( const std::string& item, BOOL case_sensitive = TRUE );		// FALSE if item not found +	BOOL			selectItemByLabel( const std::string& item, BOOL case_sensitive = TRUE, S32 column = 0 );		// FALSE if item not found  	BOOL			selectItemByPrefix(const std::string& target, BOOL case_sensitive = TRUE);  	BOOL			selectItemByPrefix(const LLWString& target, BOOL case_sensitive = TRUE);  	LLScrollListItem*  getItemByLabel( const std::string& item, BOOL case_sensitive = TRUE, S32 column = 0 ); diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index a45c4ced2e..3c284b3f03 100755 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -180,6 +180,7 @@ LLTextBase::Params::Params()  LLTextBase::LLTextBase(const LLTextBase::Params &p)   :	LLUICtrl(p, LLTextViewModelPtr(new LLTextViewModel)),  	mURLClickSignal(NULL), +	mIsFriendSignal(NULL),  	mMaxTextByteLength( p.max_text_length ),  	mFont(p.font),  	mFontShadow(p.font_shadow), @@ -653,6 +654,10 @@ void LLTextBase::drawText()  			mSpellCheckEnd = end;  		}  	} +	else +	{ +		mMisspellRanges.clear(); +	}  	LLTextSegmentPtr cur_segment = *seg_iter; @@ -1850,7 +1855,17 @@ LLTextBase::segment_set_t::iterator LLTextBase::getSegIterContaining(S32 index)  	static LLPointer<LLIndexSegment> index_segment = new LLIndexSegment(); -	if (index > getLength()) { return mSegments.end(); } +	S32 text_len = 0; +	if (!useLabel()) +	{ +		text_len = getLength(); +	} +	else +	{ +		text_len = mLabel.getWString().length(); +	} + +	if (index > text_len) { return mSegments.end(); }  	// when there are no segments, we return the end iterator, which must be checked by caller  	if (mSegments.size() <= 1) { return mSegments.begin(); } @@ -1866,7 +1881,17 @@ LLTextBase::segment_set_t::const_iterator LLTextBase::getSegIterContaining(S32 i  {  	static LLPointer<LLIndexSegment> index_segment = new LLIndexSegment(); -	if (index > getLength()) { return mSegments.end(); } +	S32 text_len = 0; +	if (!useLabel()) +	{ +		text_len = getLength(); +	} +	else +	{ +		text_len = mLabel.getWString().length(); +	} + +	if (index > text_len) { return mSegments.end(); }  	// when there are no segments, we return the end iterator, which must be checked by caller  	if (mSegments.size() <= 1) { return mSegments.begin(); } @@ -1916,9 +1941,12 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url)  	registrar.add("Url.OpenInternal", boost::bind(&LLUrlAction::openURLInternal, url));  	registrar.add("Url.OpenExternal", boost::bind(&LLUrlAction::openURLExternal, url));  	registrar.add("Url.Execute", boost::bind(&LLUrlAction::executeSLURL, url)); +	registrar.add("Url.Block", boost::bind(&LLUrlAction::blockObject, url));  	registrar.add("Url.Teleport", boost::bind(&LLUrlAction::teleportToLocation, url));  	registrar.add("Url.ShowProfile", boost::bind(&LLUrlAction::showProfile, url));  	registrar.add("Url.AddFriend", boost::bind(&LLUrlAction::addFriend, url)); +	registrar.add("Url.RemoveFriend", boost::bind(&LLUrlAction::removeFriend, 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)); @@ -1927,6 +1955,19 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url)  	delete mPopupMenu;  	mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(xui_file, LLMenuGL::sMenuContainer,  																		 LLMenuHolderGL::child_registry_t::instance());	 +	if (mIsFriendSignal) +	{ +		bool isFriend = *(*mIsFriendSignal)(LLUUID(LLUrlAction::getUserID(url))); +		LLView* addFriendButton = mPopupMenu->getChild<LLView>("add_friend"); +		LLView* removeFriendButton = mPopupMenu->getChild<LLView>("remove_friend"); + +		if (addFriendButton && removeFriendButton) +		{ +			addFriendButton->setEnabled(!isFriend); +			removeFriendButton->setEnabled(isFriend); +		} +	} +	  	if (mPopupMenu)  	{  		mPopupMenu->show(x, y); @@ -2096,7 +2137,7 @@ void LLTextBase::resetLabel()  	}  } -bool LLTextBase::useLabel() +bool LLTextBase::useLabel() const  {      return !getLength() && !mLabel.empty() && !hasFocus();  } @@ -2602,21 +2643,18 @@ void LLTextBase::setCursorAtLocalPos( S32 local_x, S32 local_y, bool round, bool  void LLTextBase::changeLine( S32 delta )  {  	S32 line = getLineNumFromDocIndex(mCursorPos); +	S32 max_line_nb = getLineCount() - 1; +	max_line_nb = (max_line_nb < 0 ? 0 : max_line_nb); +     +	S32 new_line = llclamp(line + delta, 0, max_line_nb); -	S32 new_line = line; -	if( (delta < 0) && (line > 0 ) ) -	{ -		new_line = line - 1; -	} -	else if( (delta > 0) && (line < (getLineCount() - 1)) ) -	{ -		new_line = line + 1; -	} - -	LLRect visible_region = getVisibleDocumentRect(); - -	S32 new_cursor_pos = getDocIndexFromLocalCoord(mDesiredXPixel, mLineInfoList[new_line].mRect.mBottom + mVisibleTextRect.mBottom - visible_region.mBottom, TRUE); -	setCursorPos(new_cursor_pos, true); +    if (new_line != line) +    { +        LLRect visible_region = getVisibleDocumentRect(); +        S32 new_cursor_pos = getDocIndexFromLocalCoord(mDesiredXPixel, +                                                       mLineInfoList[new_line].mRect.mBottom + mVisibleTextRect.mBottom - visible_region.mBottom, TRUE); +        setCursorPos(new_cursor_pos, true); +    }  }  bool LLTextBase::scrolledToStart() @@ -2910,6 +2948,15 @@ boost::signals2::connection LLTextBase::setURLClickedCallback(const commit_signa  	return mURLClickSignal->connect(cb);  } +boost::signals2::connection LLTextBase::setIsFriendCallback(const is_friend_signal_t::slot_type& cb) +{ +	if (!mIsFriendSignal) +	{ +		mIsFriendSignal = new is_friend_signal_t(); +	} +	return mIsFriendSignal->connect(cb); +} +  //  // LLTextSegment  // @@ -3203,7 +3250,7 @@ S32	LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin  		: LLFontGL::ONLY_WORD_BOUNDARIES; -	LLWString offsetString(text.c_str() + segment_offset + mStart); +	S32 offsetLength = text.length() - (segment_offset + mStart);  	if(getLength() < segment_offset + mStart)  	{  @@ -3211,13 +3258,13 @@ S32	LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin  						<< segment_offset << "\tmStart:\t" << mStart << "\tsegments\t" << mEditor.mSegments.size() << "\tmax_chars\t" << max_chars << llendl;  	} -	if(offsetString.length() + 1 < max_chars) +	if( (offsetLength + 1) < max_chars)  	{ -		llinfos << "offsetString.length() + 1 < max_chars\t max_chars:\t" << max_chars << "\toffsetString.length():\t" << offsetString.length() << " getLength() : " +		llinfos << "offsetString.length() + 1 < max_chars\t max_chars:\t" << max_chars << "\toffsetLength:\t" << offsetLength << " getLength() : "  			<< getLength() << "\tsegment_offset:\t" << segment_offset << "\tmStart:\t" << mStart << "\tsegments\t" << mEditor.mSegments.size() << llendl;  	} -	S32 num_chars = mStyle->getFont()->maxDrawableChars(offsetString.c_str(),  +	S32 num_chars = mStyle->getFont()->maxDrawableChars( text.c_str() + (segment_offset + mStart),  												(F32)num_pixels,  												max_chars,   												word_wrap_style); diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 20a73387b5..a74e97cac8 100755 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -258,6 +258,8 @@ public:  	friend class LLNormalTextSegment;  	friend class LLUICtrlFactory; +	typedef boost::signals2::signal<bool (const LLUUID& user_id)> is_friend_signal_t; +  	struct LineSpacingParams : public LLInitParam::ChoiceBlock<LineSpacingParams>  	{  		Alternative<F32>	multiple; @@ -434,6 +436,7 @@ public:  	virtual void			appendImageSegment(const LLStyle::Params& style_params);  	virtual void			appendWidget(const LLInlineViewSegment::Params& params, const std::string& text, bool allow_undo);  	boost::signals2::connection setURLClickedCallback(const commit_signal_t::slot_type& cb); +	boost::signals2::connection setIsFriendCallback(const is_friend_signal_t::slot_type& cb);  	void					setWordWrap(bool wrap);  	LLScrollContainer*		getScrollContainer() const { return mScroller; } @@ -507,7 +510,7 @@ protected:  	void							initFromParams(const Params& p);      virtual void					beforeValueChange();  	virtual void					onValueChange(S32 start, S32 end); -    virtual bool                    useLabel(); +    virtual bool                    useLabel() const;  	// draw methods  	void							drawSelectionBackground(); // draws the black box behind the selected text @@ -648,6 +651,9 @@ protected:  	// Fired when a URL link is clicked  	commit_signal_t*			mURLClickSignal; +	// Used to check if user with given ID is avatar's friend +	is_friend_signal_t*         mIsFriendSignal; +  	LLUIString					mLabel;	// text label that is visible when no user text provided  }; diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 834f213097..0c16e06109 100755 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -1125,7 +1125,8 @@ void LLTextEditor::addChar(llwchar wc)  	}  } -void LLTextEditor::addLineBreakChar() + +void LLTextEditor::addLineBreakChar(BOOL group_together)  {  	if( !getEnabled() )  	{ @@ -1143,7 +1144,7 @@ void LLTextEditor::addLineBreakChar()  	LLStyleConstSP sp(new LLStyle(LLStyle::Params()));  	LLTextSegmentPtr segment = new LLLineBreakTextSegment(sp, mCursorPos); -	S32 pos = execute(new TextCmdAddChar(mCursorPos, FALSE, '\n', segment)); +	S32 pos = execute(new TextCmdAddChar(mCursorPos, group_together, '\n', segment));  	setCursorPos(mCursorPos + pos);  } @@ -1484,21 +1485,28 @@ void LLTextEditor::pasteTextWithLinebreaks(LLWString & clean_string)  	std::basic_string<llwchar>::size_type start = 0;  	std::basic_string<llwchar>::size_type pos = clean_string.find('\n',start); -	while(pos!=-1) +	while((pos != -1) && (pos != clean_string.length() -1))  	{  		if(pos!=start)  		{  			std::basic_string<llwchar> str = std::basic_string<llwchar>(clean_string,start,pos-start); -			setCursorPos(mCursorPos + insert(mCursorPos, str, FALSE, LLTextSegmentPtr())); +			setCursorPos(mCursorPos + insert(mCursorPos, str, TRUE, LLTextSegmentPtr()));  		} -		addLineBreakChar(); -		 +		addLineBreakChar(TRUE);			// Add a line break and group with the next addition. +  		start = pos+1;  		pos = clean_string.find('\n',start);  	} -	std::basic_string<llwchar> str = std::basic_string<llwchar>(clean_string,start,clean_string.length()-start); -	setCursorPos(mCursorPos + insert(mCursorPos, str, FALSE, LLTextSegmentPtr())); +	if (pos != start) +	{ +		std::basic_string<llwchar> str = std::basic_string<llwchar>(clean_string,start,clean_string.length()-start); +		setCursorPos(mCursorPos + insert(mCursorPos, str, FALSE, LLTextSegmentPtr())); +	} +	else +	{ +		addLineBreakChar(FALSE);		// Add a line break and end the grouping. +	}  }  // copy selection to primary @@ -1964,8 +1972,7 @@ void LLTextEditor::onFocusReceived()  	updateAllowingLanguageInput();  } -// virtual, from LLView -void LLTextEditor::onFocusLost() +void LLTextEditor::focusLostHelper()  {  	updateAllowingLanguageInput(); @@ -1982,7 +1989,11 @@ void LLTextEditor::onFocusLost()  	// Make sure cursor is shown again  	getWindow()->showCursorFromMouseMove(); +} +void LLTextEditor::onFocusLost() +{ +	focusLostHelper();  	LLTextBase::onFocusLost();  } @@ -2128,12 +2139,17 @@ void LLTextEditor::drawPreeditMarker()  					continue;  				} -				S32 preedit_left = mVisibleTextRect.mLeft; +				line_info& line = mLineInfoList[cur_line]; +				LLRect text_rect(line.mRect); +				text_rect.mRight = mDocumentView->getRect().getWidth(); // clamp right edge to document extents +				text_rect.translate(mDocumentView->getRect().mLeft, mDocumentView->getRect().mBottom); // adjust by scroll position + +				S32 preedit_left = text_rect.mLeft;  				if (left > line_start)  				{  					preedit_left += mFont->getWidth(text, line_start, left - line_start);  				} -				S32 preedit_right = mVisibleTextRect.mLeft; +				S32 preedit_right = text_rect.mLeft;  				if (right < line_end)  				{  					preedit_right += mFont->getWidth(text, line_start, right - line_start); @@ -2146,18 +2162,18 @@ void LLTextEditor::drawPreeditMarker()  				if (mPreeditStandouts[i])  				{  					gl_rect_2d(preedit_left + preedit_standout_gap, -							line_y + preedit_standout_position, -							preedit_right - preedit_standout_gap - 1, -							line_y + preedit_standout_position - preedit_standout_thickness, -							(mCursorColor.get() * preedit_standout_brightness + mWriteableBgColor.get() * (1 - preedit_standout_brightness)).setAlpha(1.0f)); +							   text_rect.mBottom + mFont->getDescenderHeight() - 1, +							   preedit_right - preedit_standout_gap - 1, +							   text_rect.mBottom + mFont->getDescenderHeight() - 1 - preedit_standout_thickness, +							   (mCursorColor.get() * preedit_standout_brightness + mWriteableBgColor.get() * (1 - preedit_standout_brightness)).setAlpha(1.0f));  				}  				else  				{  					gl_rect_2d(preedit_left + preedit_marker_gap, -							line_y + preedit_marker_position, -							preedit_right - preedit_marker_gap - 1, -							line_y + preedit_marker_position - preedit_marker_thickness, -							(mCursorColor.get() * preedit_marker_brightness + mWriteableBgColor.get() * (1 - preedit_marker_brightness)).setAlpha(1.0f)); +							   text_rect.mBottom + mFont->getDescenderHeight() - 1, +							   preedit_right - preedit_marker_gap - 1, +							   text_rect.mBottom + mFont->getDescenderHeight() - 1 - preedit_marker_thickness, +							   (mCursorColor.get() * preedit_marker_brightness + mWriteableBgColor.get() * (1 - preedit_marker_brightness)).setAlpha(1.0f));  				}  			}  		} @@ -2240,12 +2256,13 @@ void LLTextEditor::draw()  		LLRect clip_rect(mVisibleTextRect);  		clip_rect.stretch(1);  		LLLocalClipRect clip(clip_rect); -		drawPreeditMarker();  	}  	LLTextBase::draw();  	drawLineNumbers(); +    drawPreeditMarker(); +  	//RN: the decision was made to always show the orange border for keyboard focus but do not put an insertion caret  	// when in readonly mode  	mBorder->setKeyboardFocusHighlight( hasFocus() );// && !mReadOnly); @@ -2695,14 +2712,20 @@ BOOL LLTextEditor::hasPreeditString() const  void LLTextEditor::resetPreedit()  { +    if (hasSelection()) +    { +		if (hasPreeditString()) +        { +            llwarns << "Preedit and selection!" << llendl; +            deselect(); +        } +        else +        { +            deleteSelection(TRUE); +        } +    }  	if (hasPreeditString())  	{ -		if (hasSelection()) -		{ -			llwarns << "Preedit and selection!" << llendl; -			deselect(); -		} -  		setCursorPos(mPreeditPositions.front());  		removeStringNoUndo(mCursorPos, mPreeditPositions.back() - mCursorPos);  		insertStringNoUndo(mCursorPos, mPreeditOverwrittenWString); @@ -2750,7 +2773,10 @@ void LLTextEditor::updatePreedit(const LLWString &preedit_string,  	{  		mPreeditOverwrittenWString.clear();  	} -	insertStringNoUndo(insert_preedit_at, mPreeditWString); +     +	segment_vec_t segments; +	//pass empty segments to let "insertStringNoUndo" make new LLNormalTextSegment and insert it, if needed. +	insertStringNoUndo(insert_preedit_at, mPreeditWString, &segments);   	mPreeditStandouts = preedit_standouts; diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index 969e072704..32b543ec0e 100755 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -248,13 +248,14 @@ protected:  	// Undoable operations  	void			addChar(llwchar c); // at mCursorPos  	S32				addChar(S32 pos, llwchar wc); -	void			addLineBreakChar(); +	void			addLineBreakChar(BOOL group_together = FALSE);  	S32				overwriteChar(S32 pos, llwchar wc);  	void			removeChar();  	S32 			removeChar(S32 pos);  	S32				insert(S32 pos, const LLWString &wstr, bool group_with_next_op, LLTextSegmentPtr segment);  	S32				remove(S32 pos, S32 length, bool group_with_next_op); +	void			focusLostHelper();  	void			updateAllowingLanguageInput();  	BOOL			hasPreeditString() const; diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp index 3d9f5cbbc2..928e82cb8c 100755 --- a/indra/llui/lltoolbar.cpp +++ b/indra/llui/lltoolbar.cpp @@ -381,7 +381,7 @@ bool LLToolBar::stopCommandInProgress(const LLCommandId& commandId)  	return (command_button != NULL);  } -bool LLToolBar::flashCommand(const LLCommandId& commandId, bool flash) +bool LLToolBar::flashCommand(const LLCommandId& commandId, bool flash, bool force_flashing/* = false */)  {  	LLButton * command_button = NULL; @@ -391,7 +391,7 @@ bool LLToolBar::flashCommand(const LLCommandId& commandId, bool flash)  		if (it != mButtonMap.end())  		{  			command_button = it->second; -			command_button->setFlashing(flash ? TRUE : FALSE); +			command_button->setFlashing((BOOL)(flash),(BOOL)(force_flashing));  		}  	} diff --git a/indra/llui/lltoolbar.h b/indra/llui/lltoolbar.h index 31424a36d4..743951a41f 100755 --- a/indra/llui/lltoolbar.h +++ b/indra/llui/lltoolbar.h @@ -192,7 +192,7 @@ public:  	bool hasCommand(const LLCommandId& commandId) const;	// is this command bound to a button in this toolbar  	bool enableCommand(const LLCommandId& commandId, bool enabled);	// enable/disable button bound to the specified command, if it exists in this toolbar  	bool stopCommandInProgress(const LLCommandId& commandId);	// stop command if it is currently active -	bool flashCommand(const LLCommandId& commandId, bool flash); // flash button associated with given command, if in this toolbar +	bool flashCommand(const LLCommandId& commandId, bool flash, bool force_flashing = false); // flash button associated with given command, if in this toolbar  	void setStartDragCallback(tool_startdrag_callback_t cb)   { mStartDragItemCallback  = cb; } // connects drag and drop behavior to external logic  	void setHandleDragCallback(tool_handledrag_callback_t cb) { mHandleDragItemCallback = cb; } diff --git a/indra/llui/llurlaction.cpp b/indra/llui/llurlaction.cpp index f51aeaec13..23e574cb74 100755 --- a/indra/llui/llurlaction.cpp +++ b/indra/llui/llurlaction.cpp @@ -170,6 +170,30 @@ std::string LLUrlAction::getUserID(std::string url)  	return id_str;  } +std::string LLUrlAction::getObjectId(std::string url) +{ +	LLURI uri(url); +	LLSD path_array = uri.pathArray(); +	std::string id_str; +	if (path_array.size() >= 3) +	{ +		id_str = path_array.get(2).asString(); +	} +	return id_str; +} + +std::string LLUrlAction::getObjectName(std::string url) +{ +	LLURI uri(url); +	LLSD query_map = uri.queryMap(); +	std::string name; +	if (query_map.has("name")) +	{ +		name = query_map["name"].asString(); +	} +	return name; +} +  void LLUrlAction::sendIM(std::string url)  {  	std::string id_str = getUserID(url); @@ -188,3 +212,21 @@ void LLUrlAction::addFriend(std::string url)  	}  } +void LLUrlAction::removeFriend(std::string url) +{ +	std::string id_str = getUserID(url); +	if (LLUUID::validate(id_str)) +	{ +		executeSLURL("secondlife:///app/agent/" + id_str + "/removefriend"); +	} +} + +void LLUrlAction::blockObject(std::string url) +{ +	std::string object_id = getObjectId(url); +	std::string object_name = getObjectName(url); +	if (LLUUID::validate(object_id)) +	{ +		executeSLURL("secondlife:///app/agent/" + object_id + "/block/" + object_name); +	} +} diff --git a/indra/llui/llurlaction.h b/indra/llui/llurlaction.h index e31cd71a20..e731376b95 100755 --- a/indra/llui/llurlaction.h +++ b/indra/llui/llurlaction.h @@ -77,8 +77,12 @@ 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 std::string getUserID(std::string url); +	static std::string getObjectName(std::string url); +	static std::string getObjectId(std::string url);  	static void sendIM(std::string url);  	static void addFriend(std::string url); +	static void removeFriend(std::string url); +	static void blockObject(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/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 99ee688888..b1cc502c4b 100755 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -504,6 +504,10 @@ std::string localize_slapp_label(const std::string& url, const std::string& full  	{  		return LLTrans::getString("SLappAgentRequestFriend") + " " + full_name;  	} +	if (LLStringUtil::endsWith(url, "/removefriend")) +	{ +		return LLTrans::getString("SLappAgentRemoveFriend") + " " + full_name; +	}  	return full_name;  } diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h index cc10ed5bbd..e02bf552aa 100755 --- a/indra/llvfs/lldir.h +++ b/indra/llvfs/lldir.h @@ -32,7 +32,7 @@  #define MAX_PATH MAXPATHLEN  #endif -// these numbers *may* get serialized (really??), so we need to be explicit +// these numbers are read from settings_files.xml, so we need to be explicit  typedef enum ELLPath  {  	LL_PATH_NONE = 0, diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 43c0090993..30f5526500 100755 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -159,9 +159,8 @@ LLWinImm LLWinImm::sTheInstance;  LLWinImm::LLWinImm() : mHImmDll(NULL)  {  	// Check system metrics  -	if ( !GetSystemMetrics( SM_DBCSENABLED ) ) +	if ( !GetSystemMetrics( SM_IMMENABLED ) )  		return; -	  	mHImmDll = LoadLibraryA("Imm32");  	if (mHImmDll != NULL) @@ -3500,19 +3499,11 @@ void LLWindowWin32::updateLanguageTextInputArea()  void LLWindowWin32::interruptLanguageTextInput()  { -	if (mPreeditor) +	if (mPreeditor && LLWinImm::isAvailable())  	{ -		if (LLWinImm::isAvailable()) -		{ -			HIMC himc = LLWinImm::getContext(mWindowHandle); -			LLWinImm::notifyIME(himc, NI_COMPOSITIONSTR, CPS_COMPLETE, 0); -			LLWinImm::releaseContext(mWindowHandle, himc); -		} - -		// Win32 document says there will be no composition string -		// after NI_COMPOSITIONSTR returns.  The following call to -		// resetPreedit should be a NOP unless IME goes mad... -		mPreeditor->resetPreedit(); +		HIMC himc = LLWinImm::getContext(mWindowHandle); +		LLWinImm::notifyIME(himc, NI_COMPOSITIONSTR, CPS_COMPLETE, 0); +		LLWinImm::releaseContext(mWindowHandle, himc);  	}  } diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp index 666c03e9ff..16f2290787 100755 --- a/indra/llxml/llcontrol.cpp +++ b/indra/llxml/llcontrol.cpp @@ -132,14 +132,14 @@ bool LLControlVariable::llsd_compare(const LLSD& a, const LLSD & b)  LLControlVariable::LLControlVariable(const std::string& name, eControlType type,  							 LLSD initial, const std::string& comment, -							 bool persist, bool hidefromsettingseditor) +							 ePersist persist, bool hidefromsettingseditor)  	: mName(name),  	  mComment(comment),  	  mType(type),  	  mPersist(persist),  	  mHideFromSettingsEditor(hidefromsettingseditor)  { -	if (mPersist && mComment.empty()) +	if ((persist != PERSIST_NO) && mComment.empty())  	{  		llerrs << "Must supply a comment for control " << mName << llendl;  	} @@ -260,7 +260,7 @@ void LLControlVariable::setDefaultValue(const LLSD& value)  	}  } -void LLControlVariable::setPersist(bool state) +void LLControlVariable::setPersist(ePersist state)  {  	mPersist = state;  } @@ -292,10 +292,29 @@ void LLControlVariable::resetToDefault(bool fire_signal)  	}  } -bool LLControlVariable::isSaveValueDefault() -{  -    return (mValues.size() ==  1)  -        || ((mValues.size() > 1) && llsd_compare(mValues[1], mValues[0])); +bool LLControlVariable::shouldSave(bool nondefault_only) +{ +	// This method is used to decide whether we should save a given +	// variable. Two of the three values of mPersist are easy. +	if (mPersist == PERSIST_NO) +		return false; + +	if (mPersist == PERSIST_ALWAYS) +		return true; + +	// PERSIST_NONDFT +	// If caller doesn't need us to filter, just save. +	if (! nondefault_only) +		return true; + +	// PERSIST_NONDFT: caller only wants us to save this variable if its value +	// differs from default. +	if (isDefault())                // never been altered +		return false; + +	// We've set at least one other value: compare it to default. Save only if +	// they differ. +	return ! llsd_compare(getSaveValue(), getDefault());  }  LLSD LLControlVariable::getSaveValue() const @@ -355,12 +374,12 @@ std::string LLControlGroup::typeEnumToString(eControlType typeenum)  	return mTypeString[typeenum];  } -BOOL LLControlGroup::declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, BOOL persist, BOOL hidefromsettingseditor) +LLControlVariable* LLControlGroup::declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, LLControlVariable::ePersist persist, BOOL hidefromsettingseditor)  {  	LLControlVariable* existing_control = getControl(name);  	if (existing_control)   	{ -		if (persist && existing_control->isType(type)) +		if ((persist != LLControlVariable::PERSIST_NO) && existing_control->isType(type))  		{  			if (!existing_control->llsd_compare(existing_control->getDefault(), initial_val))  			{ @@ -374,66 +393,66 @@ BOOL LLControlGroup::declareControl(const std::string& name, eControlType type,  		{  			llwarns << "Control named " << name << " already exists, ignoring new declaration." << llendl;  		} - 		return TRUE; + 		return existing_control;  	}  	// if not, create the control and add it to the name table  	LLControlVariable* control = new LLControlVariable(name, type, initial_val, comment, persist, hidefromsettingseditor);  	mNameTable[name] = control;	 -	return TRUE; +	return control;  } -BOOL LLControlGroup::declareU32(const std::string& name, const U32 initial_val, const std::string& comment, BOOL persist) +LLControlVariable* LLControlGroup::declareU32(const std::string& name, const U32 initial_val, const std::string& comment, LLControlVariable::ePersist persist)  {  	return declareControl(name, TYPE_U32, (LLSD::Integer) initial_val, comment, persist);  } -BOOL LLControlGroup::declareS32(const std::string& name, const S32 initial_val, const std::string& comment, BOOL persist) +LLControlVariable* LLControlGroup::declareS32(const std::string& name, const S32 initial_val, const std::string& comment, LLControlVariable::ePersist persist)  {  	return declareControl(name, TYPE_S32, initial_val, comment, persist);  } -BOOL LLControlGroup::declareF32(const std::string& name, const F32 initial_val, const std::string& comment, BOOL persist) +LLControlVariable* LLControlGroup::declareF32(const std::string& name, const F32 initial_val, const std::string& comment, LLControlVariable::ePersist persist)  {  	return declareControl(name, TYPE_F32, initial_val, comment, persist);  } -BOOL LLControlGroup::declareBOOL(const std::string& name, const BOOL initial_val, const std::string& comment, BOOL persist) +LLControlVariable* LLControlGroup::declareBOOL(const std::string& name, const BOOL initial_val, const std::string& comment, LLControlVariable::ePersist persist)  {  	return declareControl(name, TYPE_BOOLEAN, initial_val, comment, persist);  } -BOOL LLControlGroup::declareString(const std::string& name, const std::string& initial_val, const std::string& comment, BOOL persist) +LLControlVariable* LLControlGroup::declareString(const std::string& name, const std::string& initial_val, const std::string& comment, LLControlVariable::ePersist persist)  {  	return declareControl(name, TYPE_STRING, initial_val, comment, persist);  } -BOOL LLControlGroup::declareVec3(const std::string& name, const LLVector3 &initial_val, const std::string& comment, BOOL persist) +LLControlVariable* LLControlGroup::declareVec3(const std::string& name, const LLVector3 &initial_val, const std::string& comment, LLControlVariable::ePersist persist)  {  	return declareControl(name, TYPE_VEC3, initial_val.getValue(), comment, persist);  } -BOOL LLControlGroup::declareVec3d(const std::string& name, const LLVector3d &initial_val, const std::string& comment, BOOL persist) +LLControlVariable* LLControlGroup::declareVec3d(const std::string& name, const LLVector3d &initial_val, const std::string& comment, LLControlVariable::ePersist persist)  {  	return declareControl(name, TYPE_VEC3D, initial_val.getValue(), comment, persist);  } -BOOL LLControlGroup::declareRect(const std::string& name, const LLRect &initial_val, const std::string& comment, BOOL persist) +LLControlVariable* LLControlGroup::declareRect(const std::string& name, const LLRect &initial_val, const std::string& comment, LLControlVariable::ePersist persist)  {  	return declareControl(name, TYPE_RECT, initial_val.getValue(), comment, persist);  } -BOOL LLControlGroup::declareColor4(const std::string& name, const LLColor4 &initial_val, const std::string& comment, BOOL persist ) +LLControlVariable* LLControlGroup::declareColor4(const std::string& name, const LLColor4 &initial_val, const std::string& comment, LLControlVariable::ePersist persist )  {  	return declareControl(name, TYPE_COL4, initial_val.getValue(), comment, persist);  } -BOOL LLControlGroup::declareColor3(const std::string& name, const LLColor3 &initial_val, const std::string& comment, BOOL persist ) +LLControlVariable* LLControlGroup::declareColor3(const std::string& name, const LLColor3 &initial_val, const std::string& comment, LLControlVariable::ePersist persist )  {  	return declareControl(name, TYPE_COL3, initial_val.getValue(), comment, persist);  } -BOOL LLControlGroup::declareLLSD(const std::string& name, const LLSD &initial_val, const std::string& comment, BOOL persist ) +LLControlVariable* LLControlGroup::declareLLSD(const std::string& name, const LLSD &initial_val, const std::string& comment, LLControlVariable::ePersist persist )  {  	return declareControl(name, TYPE_LLSD, initial_val, comment, persist);  } @@ -664,11 +683,11 @@ U32 LLControlGroup::loadFromFileLegacy(const std::string& filename, BOOL require  			switch(declare_as)  			{  			case TYPE_COL4: -				declareColor4(name, LLColor4::white, LLStringUtil::null, NO_PERSIST); +				declareColor4(name, LLColor4::white, LLStringUtil::null, LLControlVariable::PERSIST_NO);  				break;  			case TYPE_STRING:  			default: -				declareString(name, LLStringUtil::null, LLStringUtil::null, NO_PERSIST); +				declareString(name, LLStringUtil::null, LLStringUtil::null, LLControlVariable::PERSIST_NO);  				break;  			}  		} @@ -805,21 +824,12 @@ U32 LLControlGroup::saveToFile(const std::string& filename, BOOL nondefault_only  		{  			llwarns << "Tried to save invalid control: " << iter->first << llendl;  		} - -		if( control && control->isPersisted() ) +		else if( control->shouldSave(nondefault_only) )  		{ -			if (!(nondefault_only && (control->isSaveValueDefault()))) -			{ -				settings[iter->first]["Type"] = typeEnumToString(control->type()); -				settings[iter->first]["Comment"] = control->getComment(); -				settings[iter->first]["Value"] = control->getSaveValue(); -				++num_saved; -			} -			else -			{ -				// Debug spam -				// llinfos << "Skipping " << control->getName() << llendl; -			} +			settings[iter->first]["Type"] = typeEnumToString(control->type()); +			settings[iter->first]["Comment"] = control->getComment(); +			settings[iter->first]["Value"] = control->getSaveValue(); +			++num_saved;  		}  	}  	llofstream file; @@ -862,13 +872,14 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v  	for(LLSD::map_const_iterator itr = settings.beginMap(); itr != settings.endMap(); ++itr)  	{ -		bool persist = true; +		LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT;  		std::string const & name = itr->first;  		LLSD const & control_map = itr->second;  		if(control_map.has("Persist"))   		{ -			persist = control_map["Persist"].asInteger(); +			persist = control_map["Persist"].asInteger()? +					  LLControlVariable::PERSIST_NONDFT : LLControlVariable::PERSIST_NO;  		}  		// Sometimes we want to use the settings system to provide cheap persistence, but we @@ -887,6 +898,8 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v  		LLControlVariable* existing_control = getControl(name);  		if(existing_control)  		{ +			// set_default_values is true when we're loading the initial, +			// immutable files from app_settings, e.g. settings.xml.  			if(set_default_values)  			{  				// Override all previously set properties of this control. @@ -908,6 +921,9 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v  			}  			else if(existing_control->isPersisted())  			{ +				// save_values is specifically false for (e.g.) +				// SessionSettingsFile and UserSessionSettingsFile -- in other +				// words, for a file that's supposed to be transient.  				existing_control->setValue(control_map["Value"], save_values);  			}  			// *NOTE: If not persisted and not setting defaults,  @@ -915,6 +931,39 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v  		}  		else  		{ +			// We've never seen this control before. Either we're loading up +			// the initial set of default settings files (set_default_values) +			// -- or we're loading user settings last saved by a viewer that +			// supports a superset of the variables we know. +			// CHOP-962: if we're loading an unrecognized user setting, make +			// sure we save it later. If you try an experimental viewer, tweak +			// a new setting, briefly revert to an old viewer, then return to +			// the new one, we don't want the old viewer to discard the +			// setting you changed. +			if (! set_default_values) +			{ +				// Using PERSIST_ALWAYS insists that saveToFile() (which calls +				// LLControlVariable::shouldSave()) must save this control +				// variable regardless of its value. We can safely set this +				// LLControlVariable persistent because the 'persistent' flag +				// is not itself persisted! +				persist = LLControlVariable::PERSIST_ALWAYS; +				// We want to mention unrecognized user settings variables +				// (e.g. from a newer version of the viewer) in the log. But +				// we also arrive here for Boolean variables generated by +				// the notifications subsystem when the user checks "Don't +				// show me this again." These aren't declared in settings.xml; +				// they're actually named for the notification they suppress. +				// We don't want to mention those. Apologies, this is a bit of +				// a hack: we happen to know that user settings go into an +				// LLControlGroup whose name is "Global". +				if (getKey() == "Global") +				{ +					LL_INFOS("LLControlGroup") << "preserving unrecognized " << getKey() +											   << " settings variable " << name << LL_ENDL; +				} +			} +  			declareControl(name,   						   typeStringToEnum(control_map["Type"].asString()),   						   control_map["Value"],  @@ -923,7 +972,7 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v  						   hidefromsettingseditor  						   );  		} -		 +  		++validitems;  	} diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h index ee7d1d50b7..e1f9be80dd 100755 --- a/indra/llxml/llcontrol.h +++ b/indra/llxml/llcontrol.h @@ -72,8 +72,6 @@ class LLVector3d;  class LLColor4;  class LLColor3; -const BOOL NO_PERSIST = FALSE; -  typedef enum e_control_type  {  	TYPE_U32 = 0, @@ -100,21 +98,28 @@ public:  	typedef boost::signals2::signal<bool(LLControlVariable* control, const LLSD&), boost_boolean_combiner> validate_signal_t;  	typedef boost::signals2::signal<void(LLControlVariable* control, const LLSD&, const LLSD&)> commit_signal_t; +	enum ePersist +	{ +		PERSIST_NO,                 // don't save this var +		PERSIST_NONDFT,             // save this var if differs from default +		PERSIST_ALWAYS              // save this var even if has default value +	}; +  private:  	std::string		mName;  	std::string		mComment;  	eControlType	mType; -	bool			mPersist; +	ePersist		mPersist;  	bool			mHideFromSettingsEditor;  	std::vector<LLSD> mValues; -	 +  	commit_signal_t mCommitSignal;  	validate_signal_t mValidateSignal;  public:  	LLControlVariable(const std::string& name, eControlType type,  					  LLSD initial, const std::string& comment, -					  bool persist = true, bool hidefromsettingseditor = false); +					  ePersist persist = PERSIST_NONDFT, bool hidefromsettingseditor = false);  	virtual ~LLControlVariable(); @@ -131,8 +136,8 @@ public:  	validate_signal_t* getValidateSignal() { return &mValidateSignal; }  	bool isDefault() { return (mValues.size() == 1); } -	bool isSaveValueDefault(); -	bool isPersisted() { return mPersist; } +	bool shouldSave(bool nondefault_only); +	bool isPersisted() { return mPersist != PERSIST_NO; }  	bool isHiddenFromSettingsEditor() { return mHideFromSettingsEditor; }  	LLSD get()			const	{ return getValue(); }  	LLSD getValue()		const	{ return mValues.back(); } @@ -142,7 +147,7 @@ public:  	void set(const LLSD& val)	{ setValue(val); }  	void setValue(const LLSD& value, bool saved_value = TRUE);  	void setDefaultValue(const LLSD& value); -	void setPersist(bool state); +	void setPersist(ePersist);  	void setHiddenFromSettingsEditor(bool hide);  	void setComment(const std::string& comment); @@ -207,19 +212,19 @@ public:  		virtual void apply(const std::string& name, LLControlVariable* control) = 0;  	};  	void applyToAll(ApplyFunctor* func); -	 -	BOOL declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, BOOL persist, BOOL hidefromsettingseditor = FALSE); -	BOOL declareU32(const std::string& name, U32 initial_val, const std::string& comment, BOOL persist = TRUE); -	BOOL declareS32(const std::string& name, S32 initial_val, const std::string& comment, BOOL persist = TRUE); -	BOOL declareF32(const std::string& name, F32 initial_val, const std::string& comment, BOOL persist = TRUE); -	BOOL declareBOOL(const std::string& name, BOOL initial_val, const std::string& comment, BOOL persist = TRUE); -	BOOL declareString(const std::string& name, const std::string &initial_val, const std::string& comment, BOOL persist = TRUE); -	BOOL declareVec3(const std::string& name, const LLVector3 &initial_val,const std::string& comment,  BOOL persist = TRUE); -	BOOL declareVec3d(const std::string& name, const LLVector3d &initial_val, const std::string& comment, BOOL persist = TRUE); -	BOOL declareRect(const std::string& name, const LLRect &initial_val, const std::string& comment, BOOL persist = TRUE); -	BOOL declareColor4(const std::string& name, const LLColor4 &initial_val, const std::string& comment, BOOL persist = TRUE); -	BOOL declareColor3(const std::string& name, const LLColor3 &initial_val, const std::string& comment, BOOL persist = TRUE); -	BOOL declareLLSD(const std::string& name, const LLSD &initial_val, const std::string& comment, BOOL persist = TRUE); + +	LLControlVariable* declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, LLControlVariable::ePersist persist, BOOL hidefromsettingseditor = FALSE); +	LLControlVariable* declareU32(const std::string& name, U32 initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT); +	LLControlVariable* declareS32(const std::string& name, S32 initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT); +	LLControlVariable* declareF32(const std::string& name, F32 initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT); +	LLControlVariable* declareBOOL(const std::string& name, BOOL initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT); +	LLControlVariable* declareString(const std::string& name, const std::string &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT); +	LLControlVariable* declareVec3(const std::string& name, const LLVector3 &initial_val,const std::string& comment,  LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT); +	LLControlVariable* declareVec3d(const std::string& name, const LLVector3d &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT); +	LLControlVariable* declareRect(const std::string& name, const LLRect &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT); +	LLControlVariable* declareColor4(const std::string& name, const LLColor4 &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT); +	LLControlVariable* declareColor3(const std::string& name, const LLColor3 &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT); +	LLControlVariable* declareLLSD(const std::string& name, const LLSD &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);  	std::string getString(const std::string& name);  	std::string getText(const std::string& name); @@ -368,7 +373,7 @@ private:  		init_value = convert_to_llsd(default_value);  		if(type < TYPE_COUNT)  		{ -			group.declareControl(name, type, init_value, comment, FALSE); +			group.declareControl(name, type, init_value, comment, LLControlVariable::PERSIST_NO);  			return true;  		}  		return false; diff --git a/indra/llxml/tests/llcontrol_test.cpp b/indra/llxml/tests/llcontrol_test.cpp index ede81956ec..c273773c9b 100755 --- a/indra/llxml/tests/llcontrol_test.cpp +++ b/indra/llxml/tests/llcontrol_test.cpp @@ -128,7 +128,11 @@ namespace tut  	template<> template<>  	void control_group_t::test<3>()  	{ -		int results = mCG->loadFromFile(mTestConfigFile.c_str()); +		// Pass default_values = true. This tells loadFromFile() we're loading +		// a default settings file that declares variables, rather than a user +		// settings file. When loadFromFile() encounters an unrecognized user +		// settings variable, it forcibly preserves it (CHOP-962). +		int results = mCG->loadFromFile(mTestConfigFile.c_str(), true);  		LLControlVariable* control = mCG->getControl("TestSetting");  		LLSD new_value = 13;  		control->setValue(new_value, FALSE); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 89add3e21f..e2ae7a5a9a 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -229,6 +229,7 @@ set(viewer_SOURCE_FILES      llfloaterfonttest.cpp      llfloatergesture.cpp      llfloatergodtools.cpp +    llfloatergotoline.cpp      llfloatergroupinvite.cpp      llfloatergroups.cpp      llfloaterhandler.cpp @@ -812,6 +813,7 @@ set(viewer_HEADER_FILES      llfloaterfonttest.h      llfloatergesture.h      llfloatergodtools.h +    llfloatergotoline.h      llfloatergroupinvite.h      llfloatergroups.h      llfloaterhandler.h diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index 0f44168a4d..d15b8b06fa 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -3.6.4 +3.6.5 diff --git a/indra/newview/app_settings/cmd_line.xml b/indra/newview/app_settings/cmd_line.xml index a6e93edc79..789a07fbe2 100755 --- a/indra/newview/app_settings/cmd_line.xml +++ b/indra/newview/app_settings/cmd_line.xml @@ -22,7 +22,8 @@      <map>        <key>count</key>        <integer>1</integer> -      <!-- Special case. Not mapped to a setting. --> +      <key>map-to</key> +      <string>CmdLineChannel</string>      </map>      <key>console</key> @@ -96,6 +97,8 @@  0 - low, 1 - medium, 2 - high, 3 - ultra</string>        <key>count</key>        <integer>1</integer> +      <key>map-to</key> +      <string>RenderQualityPerformance</string>      </map>      <key>grid</key> @@ -108,6 +111,16 @@        <string>CmdLineGridChoice</string>      </map> +    <key>update-service</key> +    <map> +      <key>desc</key> +      <string>Override the url base for the update query.</string> +      <key>count</key> +      <integer>1</integer> +      <key>map-to</key> +      <string>CmdLineUpdateService</string> +    </map> +      <key>help</key>      <map>        <key>desc</key> @@ -378,7 +391,8 @@        <boolean>true</boolean>        <key>last_option</key>        <boolean>true</boolean> -      <!-- Special case. Not mapped to a setting. --> +      <key>map-to</key> +      <string>CmdLineLoginLocation</string>      </map>      <key>url</key> @@ -389,7 +403,8 @@        <integer>1</integer>        <key>last_option</key>        <boolean>true</boolean> -      <!-- Special case. Not mapped to a setting. --> +      <key>map-to</key> +      <string>CmdLineLoginLocation</string>      </map>      <key>usersessionsettings</key> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 284bc85798..0b5c4d962f 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -126,6 +126,17 @@        <key>Value</key>        <integer>1</integer>      </map> +    <key>AnalyzePerformance</key> +    <map> +      <key>Comment</key> +      <string>Request performance analysis for a particular viewer run</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>0</integer> +    </map>      <key>AnimateTextures</key>      <map>        <key>Comment</key> @@ -1738,6 +1749,17 @@        <key>Value</key>        <integer>0</integer>      </map> +    <key>CmdLineChannel</key> +    <map> +      <key>Comment</key> +      <string>Command line specified channel name</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string /> +    </map>      <key>CmdLineDisableVoice</key>      <map>        <key>Comment</key> @@ -1760,6 +1782,17 @@        <key>Value</key>        <string />      </map> +    <key>CmdLineUpdateService</key> +    <map> +      <key>Comment</key> +      <string>Override the url base for the update query.</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string /> +    </map>      <key>CmdLineHelperURI</key>      <map>        <key>Comment</key> @@ -1784,6 +1817,17 @@          <string />        </array>      </map> +    <key>CmdLineLoginLocation</key> +    <map> +      <key>Comment</key> +      <string>Startup destination requested on command line</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string/> +    </map>      <key>ConnectAsGod</key>      <map>        <key>Comment</key> @@ -1916,6 +1960,17 @@        <key>Value</key>        <integer>262144</integer>      </map> +    <key>CrashOnStartup</key> +    <map> +      <key>Comment</key> +      <string>User-requested crash on viewer startup</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>0</integer> +    </map>      <key>CreateToolCopyCenters</key>      <map>        <key>Comment</key> @@ -2158,6 +2213,17 @@        <key>Value</key>        <integer>0</integer>      </map> +    <key>DebugSession</key> +    <map> +      <key>Comment</key> +      <string>Request debugging for a particular viewer session</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>0</integer> +    </map>      <key>DebugShowColor</key>      <map>        <key>Comment</key> @@ -2972,6 +3038,17 @@        <key>Value</key>        <integer>0</integer>      </map> +    <key>DisableCrashLogger</key> +    <map> +      <key>Comment</key> +      <string>Do not send crash report to Linden server</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>0</integer> +    </map>      <key>DisableMouseWarp</key>      <map>        <key>Comment</key> @@ -3489,16 +3566,27 @@          <key>Value</key>              <real>10.0</real>          </map> -    <key>FilterItemsPerFrame</key> +    <key>FilterItemsMaxTimePerFrameVisible</key>      <map> -      <key>Comment</key> -      <string>Maximum number of inventory items to match against search filter every frame (lower to increase framerate while searching, higher to improve search speed)</string> -      <key>Persist</key> -      <integer>1</integer> -      <key>Type</key> -      <string>S32</string> -      <key>Value</key> -      <integer>500</integer> +        <key>Comment</key> +        <string>Max time devoted to items filtering per frame for visible inventory listings (in milliseconds)</string> +        <key>Persist</key> +        <integer>1</integer> +        <key>Type</key> +        <string>S32</string> +        <key>Value</key> +        <integer>10</integer> +    </map> +    <key>FilterItemsMaxTimePerFrameUnvisible</key> +    <map> +        <key>Comment</key> +        <string>Max time devoted to items filtering per frame for non visible inventory listings (in milliseconds)</string> +        <key>Persist</key> +        <integer>1</integer> +        <key>Type</key> +        <string>S32</string> +        <key>Value</key> +        <integer>1</integer>      </map>      <key>FindLandArea</key>      <map> @@ -5227,6 +5315,28 @@        <key>Value</key>        <integer>0</integer>      </map> +    <key>LogMetrics</key> +    <map> +      <key>Comment</key> +      <string>Log viewer metrics</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string/> +    </map> +    <key>LogPerformance</key> +    <map> +      <key>Comment</key> +      <string>Log performance analysis for a particular viewer run</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>0</integer> +    </map>      <key>LogTextureNetworkTraffic</key>      <map>        <key>Comment</key> @@ -6404,6 +6514,17 @@        <key>Value</key>        <integer>0</integer>      </map> +    <key>NoQuickTime</key> +    <map> +      <key>Comment</key> +      <string>Disable QuickTime for a particular viewer run</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>0</integer> +    </map>      <key>NoVerifySSLCert</key>      <map>        <key>Comment</key> @@ -6440,7 +6561,10 @@      <key>NotificationConferenceIMOptions</key>      <map>        <key>Comment</key> -      <string>Specifies how the UI responds to Conference IM Notifications.</string> +      <string> +        Specifies how the UI responds to Conference IM Notifications. +        Allowed values: [openconversations,toast,flash,noaction] +      </string>        <key>Persist</key>        <integer>1</integer>        <key>Type</key> @@ -6451,7 +6575,10 @@      <key>NotificationFriendIMOptions</key>      <map>        <key>Comment</key> -      <string>Specifies how the UI responds to Friend IM Notifications.</string> +      <string> +        Specifies how the UI responds to Friend IM Notifications. +        Allowed values: [openconversations,toast,flash,noaction] +      </string>        <key>Persist</key>        <integer>1</integer>        <key>Type</key> @@ -6462,7 +6589,10 @@      <key>NotificationGroupChatOptions</key>      <map>        <key>Comment</key> -      <string>Specifies how the UI responds to Group Chat Notifications.</string> +      <string> +        Specifies how the UI responds to Group Chat Notifications. +        Allowed values: [openconversations,toast,flash,noaction] +      </string>        <key>Persist</key>        <integer>1</integer>        <key>Type</key> @@ -6473,7 +6603,10 @@      <key>NotificationNearbyChatOptions</key>      <map>        <key>Comment</key> -      <string>Specifies how the UI responds to Nearby Chat Notifications.</string> +      <string> +        Specifies how the UI responds to Nearby Chat Notifications. +        Allowed values: [openconversations,toast,flash,noaction] +      </string>        <key>Persist</key>        <integer>1</integer>        <key>Type</key> @@ -6484,7 +6617,24 @@      <key>NotificationNonFriendIMOptions</key>      <map>        <key>Comment</key> -      <string>Specifies how the UI responds to Non Friend IM Notifications.</string> +      <string> +        Specifies how the UI responds to Non Friend IM Notifications. +        Allowed values: [openconversations,toast,flash,noaction] +      </string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>toast</string> +    </map>   +    <key>NotificationObjectIMOptions</key> +    <map> +      <key>Comment</key> +      <string> +        Specifies how the UI responds to Object IM Notifications. +        Allowed values: [openconversations,toast,flash,noaction] +      </string>        <key>Persist</key>        <integer>1</integer>        <key>Type</key> @@ -6997,6 +7147,17 @@        <key>Value</key>        <real>90.0</real>      </map> +    <key>PlayChatAnim</key> +    <map> +      <key>Comment</key> +      <string>Your avatar plays the chat animation whenever you say, shout or whisper something in nearby chat</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>1</integer> +    </map>      <key>PlayTypingAnim</key>      <map>        <key>Comment</key> @@ -7030,6 +7191,72 @@        <key>Value</key>        <integer>0</integer>      </map>   +    <key>PlaySoundFriendIM</key> +    <map> +      <key>Comment</key> +      <string>Plays a sound when friend's IM received.</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>0</integer> +    </map> +    <key>PlaySoundNonFriendIM</key> +    <map> +      <key>Comment</key> +      <string>Plays a sound when non-friend's IM received.</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>0</integer> +    </map> +    <key>PlaySoundConferenceIM</key> +    <map> +      <key>Comment</key> +      <string>Plays a sound when conference IM received.</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>0</integer> +    </map> +    <key>PlaySoundGroupChatIM</key> +    <map> +      <key>Comment</key> +      <string>Plays a sound when group chat IM received.</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>0</integer> +    </map> +    <key>PlaySoundNearbyChatIM</key> +    <map> +      <key>Comment</key> +      <string>Plays a sound when nearby chat IM received.</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>0</integer> +    </map> +    <key>PlaySoundObjectIM</key> +    <map> +      <key>Comment</key> +      <string>Plays a sound when IM fom an object received.</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>0</integer> +    </map>      <key>PlaySoundNewConversation</key>      <map>        <key>Comment</key> @@ -9664,6 +9891,17 @@        <key>Value</key>        <integer>1</integer>      </map> +    <key>ReplaySession</key> +    <map> +      <key>Comment</key> +      <string>Request replay of previously-recorded pilot file</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>0</integer> +    </map>      <key>RotateRight</key>      <map>        <key>Comment</key> @@ -12891,12 +13129,13 @@      <key>UserLoginInfo</key>      <map>        <key>Comment</key> -      <string>Users loging data.</string> +      <string>User login data.</string>        <key>Persist</key>        <integer>1</integer>        <key>Type</key>        <string>LLSD</string>        <key>Value</key> +      <string/>      </map>      <key>VFSOldSize</key>      <map> diff --git a/indra/newview/app_settings/settings_files.xml b/indra/newview/app_settings/settings_files.xml index bfc09286e3..4a9e522a96 100755 --- a/indra/newview/app_settings/settings_files.xml +++ b/indra/newview/app_settings/settings_files.xml @@ -4,6 +4,9 @@      <file name="Global"            file_name="settings.xml"            required="true"/> +    <file name="Global" +          file_name="settings_install.xml" +          required="false"/>      <file name="PerAccount"            file_name="settings_per_account.xml"            required="true"/> diff --git a/indra/newview/app_settings/settings_minimal.xml b/indra/newview/app_settings/settings_minimal.xml index 01a70f2671..e660c1a33b 100755 --- a/indra/newview/app_settings/settings_minimal.xml +++ b/indra/newview/app_settings/settings_minimal.xml @@ -1 +1,4 @@ -<llsd/>
\ No newline at end of file +<?xml version="1.0"?> +<llsd> +  <undef/> +</llsd> diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index 590f41283b..636caf5ef3 100755 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -109,18 +109,7 @@              <string>Boolean</string>          <key>Value</key>              <integer>0</integer> -    </map> -    <key>DisplayDestinationsOnInitialRun</key> -        <map> -        <key>Comment</key> -          <string>Display the destinations guide when a user first launches Second Life.</string> -        <key>Persist</key> -          <integer>1</integer> -        <key>Type</key> -          <string>Boolean</string> -        <key>Value</key> -          <integer>1</integer> -        </map> +    </map>          <key>LastInventoryInboxActivity</key>          <map>          <key>Comment</key> diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh index d8440eebf1..c23401d5a6 100755 --- a/indra/newview/linux_tools/wrapper.sh +++ b/indra/newview/linux_tools/wrapper.sh @@ -121,37 +121,21 @@ export SAVED_LD_LIBRARY_PATH="${LD_LIBRARY_PATH}"  export LD_LIBRARY_PATH="$PWD/lib:${LD_LIBRARY_PATH}" -# Have to deal specially with gridargs.dat; typical contents look like: -# --channel "Second Life Test"  --settings settings_test.xml -# Simply embedding $(<etc/gridargs.dat) into a command line treats each of -# Second, Life and Developer as separate args -- no good. We need bash to -# process quotes using eval. -# First, check if we have been instructed to skip reading in gridargs.dat: -skip_gridargs=false -argnum=0 +# Copy "$@" to ARGS array specifically to delete the --skip-gridargs switch. +# The gridargs.dat file is no more, but we still want to avoid breaking +# scripts that invoke this one with --skip-gridargs. +ARGS=()  for ARG in "$@"; do -    if [ "--skip-gridargs" == "$ARG" ]; then -        skip_gridargs=true -    else -        ARGS[$argnum]="$ARG" -        argnum=$(($argnum+1)) +    if [ "--skip-gridargs" != "$ARG" ]; then +        ARGS[${#ARGS[*]}]="$ARG"      fi  done -# Second, read it without scanning, then scan that string. Break quoted words -# into a bash array. Note that if gridargs.dat is empty, or contains only -# whitespace, the resulting gridargs array will be empty -- zero entries -- -# therefore "${gridargs[@]}" entirely vanishes from the command line below, -# just as we want. -if ! $skip_gridargs ; then -    eval gridargs=("$(<etc/gridargs.dat)") -fi -  # Run the program.  # Don't quote $LL_WRAPPER because, if empty, it should simply vanish from the -# command line. But DO quote "$@": preserve separate args as individually -# quoted. Similar remarks about the contents of gridargs. -$LL_WRAPPER bin/do-not-directly-run-secondlife-bin "${gridargs[@]}" "${ARGS[@]}" +# command line. But DO quote "${ARGS[@]}": preserve separate args as +# individually quoted. +$LL_WRAPPER bin/do-not-directly-run-secondlife-bin "${ARGS[@]}"  LL_RUN_ERR=$?  # Handle any resulting errors diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 3e94c5edf7..f4ce3c9118 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -46,6 +46,7 @@  #include "llenvmanager.h"  #include "llfirstuse.h"  #include "llfloatercamera.h" +#include "llfloaterimcontainer.h"  #include "llfloaterreg.h"  #include "llfloatertools.h"  #include "llgroupactions.h" @@ -91,6 +92,7 @@  #include "llworld.h"  #include "llworldmap.h"  #include "stringize.h" +#include "boost/foreach.hpp"  using namespace LLAvatarAppearanceDefines; @@ -433,7 +435,7 @@ void LLAgent::init()  {  	mMoveTimer.start(); -	gSavedSettings.declareBOOL("SlowMotionAnimation", FALSE, "Declared in code", FALSE); +	gSavedSettings.declareBOOL("SlowMotionAnimation", FALSE, "Declared in code", LLControlVariable::PERSIST_NO);  	gSavedSettings.getControl("SlowMotionAnimation")->getSignal()->connect(boost::bind(&handleSlowMotionAnimation, _2));  	// *Note: this is where LLViewerCamera::getInstance() used to be constructed. @@ -2037,7 +2039,16 @@ void LLAgent::endAnimationUpdateUI()  			{  				skip_list.insert(LLFloaterReg::findInstance("mini_map"));  			} -		 + +			LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); +			LLFloaterIMContainer::floater_list_t conversations; +			im_box->getDetachedConversationFloaters(conversations); +			BOOST_FOREACH(LLFloater* conversation, conversations) +			{ +				llinfos << "skip_list.insert(session_floater): " << conversation->getTitle() << llendl; +				skip_list.insert(conversation); +			} +  			gFloaterView->popVisibleAll(skip_list);  #endif  			mViewsPushed = FALSE; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index d22376c3b2..338558c937 100755 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -672,7 +672,6 @@ LLAppViewer::LLAppViewer() :  	mSecondInstance(false),  	mSavedFinalSnapshot(false),  	mSavePerAccountSettings(false),		// don't save settings on logout unless login succeeded. -	mForceGraphicsDetail(false),  	mQuitRequested(false),  	mLogoutRequestSent(false),  	mYieldTime(-1), @@ -2312,17 +2311,24 @@ void LLAppViewer::loadColorSettings()  	LLUIColorTable::instance().loadFromSettings();  } +namespace +{ +    void handleCommandLineError(LLControlGroupCLP& clp) +    { +		llwarns << "Error parsing command line options. Command Line options ignored."  << llendl; + +		llinfos << "Command line usage:\n" << clp << llendl; + +		OSMessageBox(STRINGIZE(LLTrans::getString("MBCmdLineError") << clp.getErrorMessage()), +					 LLStringUtil::null, +					 OSMB_OK); +    } +} // anonymous namespace +  bool LLAppViewer::initConfiguration()  {	  	//Load settings files list  	std::string settings_file_list = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "settings_files.xml"); -	//LLControlGroup settings_control("SettingsFiles"); -	//llinfos << "Loading settings file list " << settings_file_list << llendl; -	//if (0 == settings_control.loadFromFile(settings_file_list)) -	//{ - //       llerrs << "Cannot load default configuration file " << settings_file_list << llendl; -	//} -  	LLXMLNodePtr root;  	BOOL success  = LLXMLNode::parseFile(settings_file_list, root, NULL);  	if (!success) @@ -2379,9 +2385,7 @@ bool LLAppViewer::initConfiguration()  	{  		c->setValue(true, false);  	} -#endif -#ifndef	LL_RELEASE_FOR_DOWNLOAD  	gSavedSettings.setBOOL("QAMode", TRUE );  	gSavedSettings.setS32("WatchdogEnabled", 0);  #endif @@ -2417,13 +2421,7 @@ bool LLAppViewer::initConfiguration()  	if(!initParseCommandLine(clp))  	{ -		llwarns	<< "Error parsing command line options.	Command	Line options ignored."  << llendl; -		 -		llinfos	<< "Command	line usage:\n" << clp << llendl; - -		std::ostringstream msg; -		msg << LLTrans::getString("MBCmdLineError") << clp.getErrorMessage(); -		OSMessageBox(msg.str(),LLStringUtil::null,OSMB_OK); +		handleCommandLineError(clp);  		return false;  	} @@ -2470,12 +2468,16 @@ bool LLAppViewer::initConfiguration()  	loadSettingsFromDirectory("UserSession");  	// - apply command line settings  -	clp.notify();  +	if (! clp.notify()) +	{ +		handleCommandLineError(clp); +		return false; +	}  	// Register the core crash option as soon as we can  	// if we want gdb post-mortem on cores we need to be up and running  	// ASAP or we might miss init issue etc. -	if(clp.hasOption("disablecrashlogger")) +	if(gSavedSettings.getBOOL("DisableCrashLogger"))  	{  		llwarns << "Crashes will be handled by system, stack trace logs and crash logger are both disabled" << llendl;  		LLAppViewer::instance()->disableCrashlogger(); @@ -2552,91 +2554,52 @@ bool LLAppViewer::initConfiguration()  	LLViewerEventRecorder::instance().setEventLoggingOn();      } -    if(clp.hasOption("channel")) -    { -		LLVersionInfo::resetChannel(clp.getOption("channel")[0]); +	std::string CmdLineChannel(gSavedSettings.getString("CmdLineChannel")); +	if(! CmdLineChannel.empty()) +	{ +		LLVersionInfo::resetChannel(CmdLineChannel);  	}  	// If we have specified crash on startup, set the global so we'll trigger the crash at the right time -	if(clp.hasOption("crashonstartup")) -	{ -		gCrashOnStartup = TRUE; -	} +	gCrashOnStartup = gSavedSettings.getBOOL("CrashOnStartup"); -	if (clp.hasOption("logperformance")) +	if (gSavedSettings.getBOOL("LogPerformance"))  	{  		LLFastTimer::sLog = TRUE;  		LLFastTimer::sLogName = std::string("performance");		  	} -	 -	if (clp.hasOption("logmetrics")) - 	{ - 		LLFastTimer::sMetricLog = TRUE ; -		// '--logmetrics' can be specified with a named test metric argument so the data gathering is done only on that test -		// In the absence of argument, every metric is gathered (makes for a rather slow run and hard to decipher report...) -		std::string test_name = clp.getOption("logmetrics")[0]; + +	std::string test_name(gSavedSettings.getString("LogMetrics")); +	if (! test_name.empty()) +	{ +		LLFastTimer::sMetricLog = TRUE ; +		// '--logmetrics' is specified with a named test metric argument so the data gathering is done only on that test +		// In the absence of argument, every metric would be gathered (makes for a rather slow run and hard to decipher report...)  		llinfos << "'--logmetrics' argument : " << test_name << llendl; -		if (test_name == "") -		{ -			llwarns << "No '--logmetrics' argument given, will output all metrics to " << DEFAULT_METRIC_NAME << llendl; -			LLFastTimer::sLogName = DEFAULT_METRIC_NAME; -		} -		else -		{ -			LLFastTimer::sLogName = test_name; -		} +		LLFastTimer::sLogName = test_name;   	}  	if (clp.hasOption("graphicslevel"))  	{ -		const LLCommandLineParser::token_vector_t& value = clp.getOption("graphicslevel"); -        if(value.size() != 1) -        { -			llwarns << "Usage: -graphicslevel <0-3>" << llendl; -        } -        else -        { -			std::string detail = value.front(); -			mForceGraphicsDetail = TRUE; -			 -			switch (detail.c_str()[0]) -			{ -				case '0':  -					gSavedSettings.setU32("RenderQualityPerformance", 0);		 -					break; -				case '1':  -					gSavedSettings.setU32("RenderQualityPerformance", 1);		 -					break; -				case '2':  -					gSavedSettings.setU32("RenderQualityPerformance", 2);		 -					break; -				case '3':  -					gSavedSettings.setU32("RenderQualityPerformance", 3);		 -					break; -				default: -					mForceGraphicsDetail = FALSE; -					llwarns << "Usage: -graphicslevel <0-3>" << llendl; -					break; -			} -        } -	} - -	if (clp.hasOption("analyzeperformance")) -	{ -		LLFastTimerView::sAnalyzePerformance = TRUE; +		// User explicitly requested --graphicslevel on the command line. We +		// expect this switch has already set RenderQualityPerformance. Check +		// that value for validity. +		U32 graphicslevel = gSavedSettings.getU32("RenderQualityPerformance"); +		if (LLFeatureManager::instance().isValidGraphicsLevel(graphicslevel)) +		{ +			// graphicslevel is valid: save it and engage it later. Capture +			// the requested value separately from the settings variable +			// because, if this is the first run, LLViewerWindow's constructor +			// will call LLFeatureManager::applyRecommendedSettings(), which +			// overwrites this settings variable! +			mForceGraphicsLevel = graphicslevel; +		}  	} -	if (clp.hasOption("replaysession")) -	{ -		gAgentPilot.setReplaySession(TRUE); -	} +	LLFastTimerView::sAnalyzePerformance = gSavedSettings.getBOOL("AnalyzePerformance"); +	gAgentPilot.setReplaySession(gSavedSettings.getBOOL("ReplaySession")); -	if (clp.hasOption("nonotifications")) -	{ -		gSavedSettings.getControl("IgnoreAllNotifications")->setValue(true, false); -	} -	 -	if (clp.hasOption("debugsession")) +	if (gSavedSettings.getBOOL("DebugSession"))  	{  		gDebugSession = TRUE;  		gDebugGL = TRUE; @@ -2661,20 +2624,16 @@ bool LLAppViewer::initConfiguration()      // What can happen is that someone can use IE (or potentially       // other browsers) and do the rough equivalent of command       // injection and steal passwords. Phoenix. SL-55321 -    if(clp.hasOption("url")) -    { -		LLStartUp::setStartSLURL(LLSLURL(clp.getOption("url")[0])); -		if(LLStartUp::getStartSLURL().getType() == LLSLURL::LOCATION)  -		{   -			LLGridManager::getInstance()->setGridChoice(LLStartUp::getStartSLURL().getGrid()); -			 -		}   -    } -    else if(clp.hasOption("slurl")) -    { -		LLSLURL start_slurl(clp.getOption("slurl")[0]); +	std::string CmdLineLoginLocation(gSavedSettings.getString("CmdLineLoginLocation")); +	if(! CmdLineLoginLocation.empty()) +	{ +		LLSLURL start_slurl(CmdLineLoginLocation);  		LLStartUp::setStartSLURL(start_slurl); -    } +		if(start_slurl.getType() == LLSLURL::LOCATION)  +		{   +			LLGridManager::getInstance()->setGridChoice(start_slurl.getGrid()); +		} +	}  	const LLControlVariable* skinfolder = gSavedSettings.getControl("SkinCurrent");  	if(skinfolder && LLStringUtil::null != skinfolder->getValue().asString()) @@ -2817,9 +2776,8 @@ bool LLAppViewer::initConfiguration()  		LL_DEBUGS("AppInit")<<"set start from NextLoginLocation: "<<nextLoginLocation<<LL_ENDL;  		LLStartUp::setStartSLURL(LLSLURL(nextLoginLocation));  	} -	else if (   (   clp.hasOption("login") || clp.hasOption("autologin")) -			 && !clp.hasOption("url") -			 && !clp.hasOption("slurl")) +	else if ((clp.hasOption("login") || clp.hasOption("autologin")) +			 && gSavedSettings.getString("CmdLineLoginLocation").empty())  	{  		// If automatic login from command line with --login switch  		// init StartSLURL location. @@ -3055,13 +3013,19 @@ namespace {  void LLAppViewer::initUpdater()  {  	// Initialize the updater service. -	// Generate URL to the udpater service  	// Get Channel  	// Get Version -	std::string url = gSavedSettings.getString("UpdaterServiceURL"); + +	/***************************************************************** +	 * Previously, the url was derived from the settings  +	 *    UpdaterServiceURL +	 *    UpdaterServicePath +	 * it is now obtained from the grid manager.  The settings above +	 * are no longer used. +	 *****************************************************************/  	std::string channel = LLVersionInfo::getChannel();  	std::string version = LLVersionInfo::getVersion(); -	std::string service_path = gSavedSettings.getString("UpdaterServicePath"); +  	U32 check_period = gSavedSettings.getU32("UpdaterServiceCheckPeriod");  	bool willing_to_test;  	LL_DEBUGS("UpdaterService") << "channel " << channel << LL_ENDL; @@ -3086,9 +3050,7 @@ void LLAppViewer::initUpdater()  	}  	mUpdater->setAppExitCallback(boost::bind(&LLAppViewer::forceQuit, this)); -	mUpdater->initialize(url,  -						 service_path,  -						 channel,  +	mUpdater->initialize(channel,   						 version,  						 gPlatform,  						 getOSInfo().getOSVersionString(), @@ -3193,11 +3155,12 @@ bool LLAppViewer::initWindow()  	// Initialize GL stuff  	// -	if (mForceGraphicsDetail) +	if (mForceGraphicsLevel)  	{ -		LLFeatureManager::getInstance()->setGraphicsLevel(gSavedSettings.getU32("RenderQualityPerformance"), false); +		LLFeatureManager::getInstance()->setGraphicsLevel(*mForceGraphicsLevel, false); +		gSavedSettings.setU32("RenderQualityPerformance", *mForceGraphicsLevel);  	} -			 +  	// Set this flag in case we crash while initializing GL  	gSavedSettings.setBOOL("RenderInitError", TRUE);  	gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE ); diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index cd91ae8b2b..3af360b529 100755 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -32,6 +32,7 @@  #include "llsys.h"			// for LLOSInfo  #include "lltimer.h"  #include "llappcorehttp.h" +#include <boost/optional.hpp>  class LLCommandLineParser;  class LLFrameTimer; @@ -258,7 +259,7 @@ private:  	bool mSavedFinalSnapshot;  	bool mSavePerAccountSettings;		// only save per account settings if login succeeded -	bool mForceGraphicsDetail; +	boost::optional<U32> mForceGraphicsLevel;      bool mQuitRequested;				// User wants to quit, may have modified documents open.      bool mLogoutRequestSent;			// Disconnect message sent to simulator, no longer safe to send messages to the sim. diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index 4d340cafa9..c7b437598c 100755 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -148,28 +148,13 @@ bool LLAppViewerMacOSX::initParseCommandLine(LLCommandLineParser& clp)  	// The next two lines add the support for parsing the mac -psn_XXX arg.  	clp.addOptionDesc("psn", NULL, 1, "MacOSX process serial number");  	clp.setCustomParser(parse_psn); -	 -    // First read in the args from arguments txt. -    const char* filename = "arguments.txt"; -	llifstream ifs(filename, llifstream::binary); -	if (!ifs.is_open()) -	{ -		llwarns << "Unable to open file" << filename << llendl; -		return false; -	} -	 -	if(clp.parseCommandLineFile(ifs) == false) -	{ -		return false; -	} -	// Then parse the user's command line, so that any --url arg can appear last -	// Succesive calls to clp.parse... will NOT override earlier options.  +	// parse the user's command line  	if(clp.parseCommandLine(gArgC, gArgV) == false)  	{  		return false;  	} -    	 +  	// Get the user's preferred language string based on the Mac OS localization mechanism.  	// To add a new localization:  		// go to the "Resources" section of the project diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp index 43757d0174..8b2d9e639f 100755 --- a/indra/newview/llchannelmanager.cpp +++ b/indra/newview/llchannelmanager.cpp @@ -139,8 +139,6 @@ void LLChannelManager::onLoginCompleted()  	}  	LLPersistentNotificationStorage::getInstance()->loadNotifications(); - -	LLDoNotDisturbNotificationStorage::getInstance()->initialize();  	LLDoNotDisturbNotificationStorage::getInstance()->loadNotifications();  } diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp index 7d0331757b..b3bc0ba966 100755 --- a/indra/newview/llchatbar.cpp +++ b/indra/newview/llchatbar.cpp @@ -381,7 +381,7 @@ void LLChatBar::sendChat( EChatType type )  			if (!utf8_revised_text.empty())  			{  				// Chat with animation -				sendChatFromViewer(utf8_revised_text, type, TRUE); +				sendChatFromViewer(utf8_revised_text, type, gSavedSettings.getBOOL("PlayChatAnim"));  			}  		}  	} diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 0f138873ac..af3c6eff11 100755 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -628,6 +628,7 @@ LLChatHistory::LLChatHistory(const LLChatHistory::Params& p)  	editor_params.enabled = false; // read only  	editor_params.show_context_menu = "true";  	mEditor = LLUICtrlFactory::create<LLTextEditor>(editor_params, this); +	mEditor->setIsFriendCallback(LLAvatarActions::isFriend);  }  LLSD LLChatHistory::getValue() const diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index a1a9463d43..fd4f17b694 100755 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -323,12 +323,11 @@ BOOL	LLFloaterIMNearbyChatToastPanel::handleMouseUp	(S32 x, S32 y, MASK mask)  			return TRUE;  		else  		{ -			(LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"))->showHistory(); +			LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat")->showHistory();  			return FALSE;  		}  	} - -	(LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"))->showHistory(); +	LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat")->showHistory();  	return LLPanel::handleMouseUp(x,y,mask);  } diff --git a/indra/newview/llcommandlineparser.cpp b/indra/newview/llcommandlineparser.cpp index 17d403bbe1..a6384ded12 100755 --- a/indra/newview/llcommandlineparser.cpp +++ b/indra/newview/llcommandlineparser.cpp @@ -38,16 +38,23 @@  #endif  #include <boost/program_options.hpp> +#include <boost/lexical_cast.hpp>  #include <boost/bind.hpp> -#include<boost/tokenizer.hpp> +#include <boost/tokenizer.hpp> +#include <boost/assign/list_of.hpp>  #if _MSC_VER  #   pragma warning(pop)  #endif  #include "llsdserialize.h" +#include "llerror.h" +#include "stringize.h" +#include <string> +#include <set>  #include <iostream>  #include <sstream> +#include <typeinfo>  #include "llcontrol.h" @@ -63,10 +70,22 @@ namespace po = boost::program_options;  // This could be good or bad, and probably won't matter for most use cases.  namespace   { +    // List of command-line switches that can't map-to settings variables. +    // Going forward, we want every new command-line switch to map-to some +    // settings variable. This list is used to validate that. +    const std::set<std::string> unmapped_options = boost::assign::list_of +        ("help") +        ("set") +        ("setdefault") +        ("settings") +        ("sessionsettings") +        ("usersessionsettings") +    ; +      po::options_description gOptionsDesc;      po::positional_options_description gPositionalOptions;  	po::variables_map gVariableMap; -     +      const LLCommandLineParser::token_vector_t gEmptyValue;      void read_file_into_string(std::string& str, const std::basic_istream < char >& file) @@ -384,9 +403,19 @@ bool LLCommandLineParser::parseCommandLineFile(const std::basic_istream < char >      return parseCommandLineString(args);  } -void LLCommandLineParser::notify() +bool LLCommandLineParser::notify()  { -    po::notify(gVariableMap);     +    try +    { +        po::notify(gVariableMap); +        return true; +    } +    catch (const LLCLPError& e) +    { +        llwarns << "Caught Error: " << e.what() << llendl; +        mErrorMsg = e.what(); +        return false; +    }  }  void LLCommandLineParser::printOptions() const @@ -428,43 +457,129 @@ const LLCommandLineParser::token_vector_t& LLCommandLineParser::getOption(const  //----------------------------------------------------------------------------  // LLControlGroupCLP defintions  //---------------------------------------------------------------------------- +namespace { +LLCommandLineParser::token_vector_t::value_type +onevalue(const std::string& option, +         const LLCommandLineParser::token_vector_t& value) +{ +    if (value.empty()) +    { +        // What does it mean when the user specifies a command-line switch +        // that requires a value, but omits the value? Complain. +        throw LLCLPError(STRINGIZE("No value specified for --" << option << "!")); +    } +    else if (value.size() > 1) +    { +        llwarns << "Ignoring extra tokens specified for --" +                << option << "." << llendl;  +    } +    return value[0]; +} + +void badvalue(const std::string& option, +              const std::string& varname, +              const std::string& type, +              const std::string& value) +{ +    // If the user passes an unusable value for a command-line switch, it +    // seems like a really bad idea to just ignore it, even with a log +    // warning. +    throw LLCLPError(STRINGIZE("Invalid value specified by command-line switch '" << option +                               << "' for variable '" << varname << "' of type " << type +                               << ": '" << value << "'")); +} + +template <typename T> +T convertTo(const std::string& option, +            const std::string& varname, +            const LLCommandLineParser::token_vector_t::value_type& value) +{ +    try +    { +        return boost::lexical_cast<T>(value); +    } +    catch (const boost::bad_lexical_cast&) +    { +        badvalue(option, varname, typeid(T).name(), value); +        // bogus return; compiler unaware that badvalue() won't return +        return T(); +    } +} +  void setControlValueCB(const LLCommandLineParser::token_vector_t& value,  -                       const std::string& opt_name,  -                       LLControlGroup* ctrlGroup) +                       const std::string& option,  +                       LLControlVariable* ctrl)  { -    // *FIX: Do sematic conversion here. +    // *FIX: Do semantic conversion here.      // LLSD (ImplString) Is no good for doing string to type conversion for...      // booleans      // compound types      // ?... -    LLControlVariable* ctrl = ctrlGroup->getControl(opt_name);      if(NULL != ctrl)      {          switch(ctrl->type())          {          case TYPE_BOOLEAN: -            if(value.size() > 1) +            if (value.empty())              { -                llwarns << "Ignoring extra tokens." << llendl;  +                // Boolean-valued command-line switches are unusual. If you +                // simply specify the switch without an explicit value, we can +                // infer you mean 'true'. +                ctrl->setValue(LLSD(true), false);              } -               -            if(value.size() > 0) +            else              { +                // Only call onevalue() AFTER handling value.empty() case! +                std::string token(onevalue(option, value)); +                              // There's a token. check the string for true/false/1/0 etc.                  BOOL result = false; -                BOOL gotSet = LLStringUtil::convertToBOOL(value[0], result); -                if(gotSet) +                BOOL gotSet = LLStringUtil::convertToBOOL(token, result); +                if (gotSet)                  {                      ctrl->setValue(LLSD(result), false);                  } +                else +                { +                    badvalue(option, ctrl->getName(), "bool", token); +                } +            } +            break; + +        case TYPE_U32: +        { +            std::string token(onevalue(option, value)); +            // To my surprise, for an unsigned target, lexical_cast() doesn't +            // complain about an input string such as "-17". In that case, you +            // get a very large positive result. So for U32, make sure there's +            // no minus sign! +            if (token.find('-') == std::string::npos) +            { +                ctrl->setValue(LLSD::Integer(convertTo<U32>(option, ctrl->getName(), token)), +                               false);              }              else              { -                ctrl->setValue(LLSD(true), false); +                badvalue(option, ctrl->getName(), "unsigned", token);              }              break; +        } + +        case TYPE_S32: +            ctrl->setValue(convertTo<S32>(option, ctrl->getName(), +                                          onevalue(option, value)), false); +            break; + +        case TYPE_F32: +            ctrl->setValue(convertTo<F32>(option, ctrl->getName(), +                                          onevalue(option, value)), false); +            break; +        // It appears that no one has yet tried to define a command-line +        // switch mapped to a settings variable of TYPE_VEC3, TYPE_VEC3D, +        // TYPE_RECT, TYPE_COL4, TYPE_COL3. Such types would certainly seem to +        // call for a bit of special handling here...          default:              {                  // For the default types, let llsd do the conversion. @@ -481,16 +596,9 @@ void setControlValueCB(const LLCommandLineParser::token_vector_t& value,                      ctrl->setValue(llsdArray, false);                  } -                else if(value.size() > 0) +                else                  { -					if(value.size() > 1) -					{ -						llwarns << "Ignoring extra tokens mapped to the setting: " << opt_name << "." << llendl;  -					} - -                    LLSD llsdValue; -                    llsdValue.assign(LLSD::String(value[0])); -                    ctrl->setValue(llsdValue, false); +                    ctrl->setValue(onevalue(option, value), false);                  }              }              break; @@ -498,12 +606,14 @@ void setControlValueCB(const LLCommandLineParser::token_vector_t& value,      }      else      { -        llwarns << "Command Line option mapping '"  -            << opt_name  -            << "' not found! Ignoring."  -            << llendl; +        // This isn't anything a user can affect -- it's a misconfiguration on +        // the part of the coder. Rub the coder's nose in the problem right +        // away so even preliminary testing will surface it. +        llerrs << "Command Line option --" << option +               << " maps to unknown setting!" << llendl;      }  } +} // anonymous namespace  void LLControlGroupCLP::configure(const std::string& config_filename, LLControlGroup* controlGroup)  { @@ -561,11 +671,37 @@ void LLControlGroupCLP::configure(const std::string& config_filename, LLControlG              }              boost::function1<void, const token_vector_t&> callback; -            if(option_params.has("map-to") && (NULL != controlGroup)) +            if (! option_params.has("map-to")) +            { +                // If this option isn't mapped to a settings variable, is it +                // one of the ones for which that's unreasonable, or did +                // someone carelessly add a new option? (Make all these +                // configuration errors fatal so a maintainer will catch them +                // right away.) +                std::set<std::string>::const_iterator found = unmapped_options.find(long_name); +                if (found == unmapped_options.end()) +                { +                    llerrs << "New command-line option " << long_name +                           << " should map-to a variable in settings.xml" << llendl; +                } +            } +            else                    // option specifies map-to              {                  std::string controlName = option_params["map-to"].asString(); -                callback = boost::bind(setControlValueCB, _1,  -                                       controlName, controlGroup); +                if (! controlGroup) +                { +                    llerrs << "Must pass gSavedSettings to LLControlGroupCLP::configure() for " +                           << long_name << " (map-to " << controlName << ")" << llendl; +                } + +                LLControlVariable* ctrl = controlGroup->getControl(controlName); +                if (! ctrl) +                { +                    llerrs << "Option " << long_name << " specifies map-to " << controlName +                           << " which does not exist" << llendl; +                } + +                callback = boost::bind(setControlValueCB, _1, long_name, ctrl);              }              this->addOptionDesc( diff --git a/indra/newview/llcommandlineparser.h b/indra/newview/llcommandlineparser.h index 44f2a26843..71388b8217 100755 --- a/indra/newview/llcommandlineparser.h +++ b/indra/newview/llcommandlineparser.h @@ -86,7 +86,7 @@ public:  	 *   	 * Use this to handle the results of parsing.   	 */ -	void notify(); +	bool notify();  	/** @brief Print a description of the configured options.  	 * diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index b0aaa21ec9..affa24f78c 100755 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -364,7 +364,10 @@ void LLConversationItemSession::buildContextMenu(LLMenuGL& menu, U32 flags)      lldebugs << "LLConversationItemParticipant::buildContextMenu()" << llendl;      menuentry_vec_t items;      menuentry_vec_t disabled_items; - +    if((flags & ITEM_IN_MULTI_SELECTION) && (this->getType() != CONV_SESSION_NEARBY)) +    { +    	items.push_back(std::string("close_selected_conversations")); +    }      if(this->getType() == CONV_SESSION_1_ON_1)      {          items.push_back(std::string("close_conversation")); @@ -387,6 +390,10 @@ void LLConversationItemSession::buildContextMenu(LLMenuGL& menu, U32 flags)          addVoiceOptions(items);          items.push_back(std::string("chat_history"));      } +    else if(this->getType() == CONV_SESSION_NEARBY) +    { +        items.push_back(std::string("chat_history")); +    }      hide_context_entries(menu, items, disabled_items);  } diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 8766585049..d8cdcdfc97 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -252,11 +252,10 @@ public:  	const std::string& 	getName() const { return mEmpty; }  	const std::string& 	getFilterText() { return mEmpty; }  	void 				setModified(EFilterModified behavior = FILTER_RESTART) { } -		 -	void 				setFilterCount(S32 count) { } -	S32 				getFilterCount() const { return 0; } -	void 				decrementFilterCount() { } -		 + +  	void 				resetTime(S32 timeout) { } +    bool                isTimedOut() { return false; } +     	bool 				isDefault() const { return true; }  	bool 				isNotDefault() const { return false; }  	void 				markDefault() { } diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index b6c53e5e30..9faa12b2ee 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -118,9 +118,19 @@ void LLConversationViewSession::setFlashState(bool flash_state)  	mFlashTimer->stopFlashing();  } +void LLConversationViewSession::setHighlightState(bool hihglight_state) +{ +	mFlashStateOn = hihglight_state; +	mFlashStarted = true; +	mFlashTimer->stopFlashing(); +} +  void LLConversationViewSession::startFlashing()  { -	if (isInVisibleChain() && mFlashStateOn && !mFlashStarted) +	LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); + +	// Need to start flashing only when "Conversations" is opened or brought on top +	if (isInVisibleChain() && !im_box->isMinimized() && mFlashStateOn && !mFlashStarted)  	{  		mFlashStarted = true;  		mFlashTimer->startFlashing(); @@ -263,6 +273,29 @@ BOOL LLConversationViewSession::handleMouseDown( S32 x, S32 y, MASK mask )  	return result;  } +BOOL LLConversationViewSession::handleMouseUp( S32 x, S32 y, MASK mask ) +{ +	BOOL result = LLFolderViewFolder::handleMouseUp(x, y, mask); + +	LLFloater* volume_floater = LLFloaterReg::findInstance("floater_voice_volume"); +	LLFloater* chat_volume_floater = LLFloaterReg::findInstance("chat_voice"); +	if (result  +		&& getRoot() +		&& !(volume_floater && volume_floater->isShown() && volume_floater->hasFocus()) +		&& !(chat_volume_floater && chat_volume_floater->isShown() && chat_volume_floater->hasFocus())) +	{ +		LLConversationItem* item = dynamic_cast<LLConversationItem *>(getViewModelItem()); +		LLUUID session_id = item? item->getUUID() : LLUUID(); +		LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(session_id); +		if(!session_floater->hasFocus()) +		{ +			session_floater->setFocus(true); +		} +    } + +	return result; +} +  BOOL LLConversationViewSession::handleRightMouseDown( S32 x, S32 y, MASK mask )  {      BOOL result = LLFolderViewFolder::handleRightMouseDown(x, y, mask); @@ -340,16 +373,20 @@ void LLConversationViewSession::setVisibleIfDetached(BOOL visible)  {  	// Do this only if the conversation floater has been torn off (i.e. no multi floater host) and is not minimized  	// Note: minimized dockable floaters are brought to front hence unminimized when made visible and we don't want that here -	LLFolderViewModelItem* item = mViewModelItem; -	LLUUID session_uuid = dynamic_cast<LLConversationItem*>(item)->getUUID(); -	LLFloater* session_floater = LLFloaterIMSessionTab::getConversation(session_uuid); -	 -	if (session_floater && !session_floater->getHost() && !session_floater->isMinimized()) +	LLFloater* session_floater = getSessionFloater(); +	if (session_floater && session_floater->isDetachedAndNotMinimized())  	{  		session_floater->setVisible(visible);  	}  } +LLFloater* LLConversationViewSession::getSessionFloater() +{ +	LLFolderViewModelItem* item = mViewModelItem; +	LLUUID session_uuid = dynamic_cast<LLConversationItem*>(item)->getUUID(); +	return LLFloaterIMSessionTab::getConversation(session_uuid); +} +  LLConversationViewParticipant* LLConversationViewSession::findParticipant(const LLUUID& participant_id)  {  	// This is *not* a general tree parsing algorithm. We search only in the mItems list diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 3eb2e63792..5a74974302 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -69,6 +69,7 @@ public:  	/*virtual*/ void draw();  	/*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask );  	/*virtual*/ BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); +	/*virtual*/ BOOL handleMouseUp( S32 x, S32 y, MASK mask );  	/*virtual*/ S32 arrange(S32* width, S32* height); @@ -86,6 +87,9 @@ public:  	virtual void refresh();  	/*virtual*/ void setFlashState(bool flash_state); +	void setHighlightState(bool hihglight_state); + +	LLFloater* getSessionFloater();  private: diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index 82affcf068..495cd01349 100755 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -70,7 +70,7 @@ BOOL LLDoNotDisturbNotificationStorageTimer::tick()  LLDoNotDisturbNotificationStorage::LLDoNotDisturbNotificationStorage()  	: LLSingleton<LLDoNotDisturbNotificationStorage>() -	, LLNotificationStorage(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "dnd_notifications.xml")) +	, LLNotificationStorage("")      , mDirty(false)  {      nameToPayloadParameterMap[toastName] = "SESSION_ID"; @@ -83,6 +83,7 @@ LLDoNotDisturbNotificationStorage::~LLDoNotDisturbNotificationStorage()  void LLDoNotDisturbNotificationStorage::initialize()  { +	setFileName(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "dnd_notifications.xml"));  	getCommunicationChannel()->connectFailedFilter(boost::bind(&LLDoNotDisturbNotificationStorage::onChannelChanged, this, _1));  } @@ -115,7 +116,8 @@ void LLDoNotDisturbNotificationStorage::saveNotifications()  	{  		LLNotificationPtr notificationPtr = historyIter->second; -		if (!notificationPtr->isRespondedTo() && !notificationPtr->isCancelled() && !notificationPtr->isExpired()) +		if (!notificationPtr->isRespondedTo() && !notificationPtr->isCancelled() && +			!notificationPtr->isExpired() && !notificationPtr->isPersistent())  		{  			data.append(notificationPtr->asLLSD(true));  		} @@ -210,12 +212,8 @@ void LLDoNotDisturbNotificationStorage::loadNotifications()  	} -    if(imToastExists) -    { -        LLFloaterReg::showInstance("im_container"); -    } - -	if(group_ad_hoc_toast_exists) +    bool isConversationLoggingAllowed = gSavedPerAccountSettings.getS32("KeepConversationLogTranscripts") > 0; +	if(group_ad_hoc_toast_exists && isConversationLoggingAllowed)  	{  		LLFloaterReg::showInstance("conversation");  	} @@ -266,11 +264,6 @@ void LLDoNotDisturbNotificationStorage::updateNotifications()          }      } -    if(imToastExists) -    {    -        LLFloaterReg::showInstance("im_container"); -    } -      if(imToastExists || offerExists)      {          make_ui_sound("UISndNewIncomingIMSession"); diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index 6d90667194..b35ef3a961 100755 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -400,6 +400,8 @@ LLFavoritesBarCtrl::LLFavoritesBarCtrl(const LLFavoritesBarCtrl::Params& p)  	mMoreTextBox->setClickedCallback(boost::bind(&LLFavoritesBarCtrl::showDropDownMenu, this));  	addChild(mMoreTextBox); +	mDropDownItemsCount = 0; +  	LLTextBox::Params label_param(p.label);  	mBarLabel = LLUICtrlFactory::create<LLTextBox> (label_param);  	addChild(mBarLabel); @@ -820,11 +822,13 @@ void LLFavoritesBarCtrl::updateButtons()  		}  		// Update overflow menu  		LLToggleableMenu* overflow_menu = static_cast <LLToggleableMenu*> (mOverflowMenuHandle.get()); -		if (overflow_menu && overflow_menu->getVisible()) +		if (overflow_menu && overflow_menu->getVisible() && (overflow_menu->getItemCount() != mDropDownItemsCount))  		{  			overflow_menu->setVisible(FALSE);  			if (mUpdateDropDownItems) +			{  				showDropDownMenu(); +			}  		}  	}  	else @@ -940,6 +944,7 @@ void LLFavoritesBarCtrl::showDropDownMenu()  		menu->updateParent(LLMenuGL::sMenuContainer);  		menu->setButtonRect(mMoreTextBox->getRect(), this);  		positionAndShowMenu(menu); +		mDropDownItemsCount = menu->getItemCount();  	}  } diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h index f06e9b9b64..211d3c4ce3 100755 --- a/indra/newview/llfavoritesbar.h +++ b/indra/newview/llfavoritesbar.h @@ -101,6 +101,7 @@ protected:  	LLUUID mFavoriteFolderId;  	const LLFontGL *mFont;  	S32 mFirstDropDownItem; +	S32 mDropDownItemsCount;  	bool mUpdateDropDownItems;  	bool mRestoreOverflowMenu; diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp index ddb9d3bc43..9d292ce7bb 100755 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -30,6 +30,7 @@  #include <fstream>  #include <boost/regex.hpp> +#include <boost/assign/list_of.hpp>  #include "llfeaturemanager.h"  #include "lldir.h" @@ -52,6 +53,8 @@  #include "llboost.h"  #include "llweb.h"  #include "llviewershadermgr.h" +#include "llstring.h" +#include "stringize.h"  #if LL_WINDOWS  #include "lldxhardware.h" @@ -187,6 +190,55 @@ void LLFeatureList::dump()  	LL_DEBUGS("RenderInit") << LL_ENDL;  } +static const std::vector<std::string> sGraphicsLevelNames = boost::assign::list_of +	("Low") +	("LowMid") +	("Mid") +	("MidHigh") +	("High") +	("HighUltra") +	("Ultra") +; + +U32 LLFeatureManager::getMaxGraphicsLevel() const +{ +	return sGraphicsLevelNames.size() - 1; +} + +bool LLFeatureManager::isValidGraphicsLevel(U32 level) const +{ +	return (level <= getMaxGraphicsLevel()); +} + +std::string LLFeatureManager::getNameForGraphicsLevel(U32 level) const +{ +	if (isValidGraphicsLevel(level)) +	{ +		return sGraphicsLevelNames[level]; +	} +	return STRINGIZE("Invalid graphics level " << level << ", valid are 0 .. " +					 << getMaxGraphicsLevel()); +} + +S32 LLFeatureManager::getGraphicsLevelForName(const std::string& name) const +{ +	const std::string FixedFunction("FixedFunction"); +	std::string rname(name); +	if (LLStringUtil::endsWith(rname, FixedFunction)) +	{ +		// chop off any "FixedFunction" suffix +		rname = rname.substr(0, rname.length() - FixedFunction.length()); +	} +	for (S32 i(0), iend(getMaxGraphicsLevel()); i <= iend; ++i) +	{ +		if (sGraphicsLevelNames[i] == rname) +		{ +			return i; +		} +	} +	return -1; +} +  LLFeatureList *LLFeatureManager::findMask(const std::string& name)  {  	if (mMaskList.count(name)) @@ -620,7 +672,7 @@ void LLFeatureManager::applyRecommendedSettings()  {  	// apply saved settings  	// cap the level at 2 (high) -	S32 level = llmax(GPU_CLASS_0, llmin(mGPUClass, GPU_CLASS_5)); +	U32 level = llmax(GPU_CLASS_0, llmin(mGPUClass, GPU_CLASS_5));  	llinfos << "Applying Recommended Features" << llendl; @@ -696,62 +748,33 @@ void LLFeatureManager::applyFeatures(bool skipFeatures)  	}  } -void LLFeatureManager::setGraphicsLevel(S32 level, bool skipFeatures) +void LLFeatureManager::setGraphicsLevel(U32 level, bool skipFeatures)  {  	LLViewerShaderMgr::sSkipReload = true;  	applyBaseMasks(); -	 -	switch (level) + +	// if we're passed an invalid level, default to "Low" +	std::string features(isValidGraphicsLevel(level)? getNameForGraphicsLevel(level) : "Low"); +	if (features == "Low")  	{ -		case 0:  #if LL_DARWIN -			// This Mac-specific change is to insure that we force 'Basic Shaders' for all Mac -			// systems which support them instead of falling back to fixed-function unnecessarily -			// MAINT-2157 -			// -			if (gGLManager.mGLVersion < 2.1f) -			{ -				maskFeatures("LowFixedFunction");			 -			} -			else -			{ //same as low, but with "Basic Shaders" enabled -				maskFeatures("Low"); -			} +		// This Mac-specific change is to insure that we force 'Basic Shaders' for all Mac +		// systems which support them instead of falling back to fixed-function unnecessarily +		// MAINT-2157 +		if (gGLManager.mGLVersion < 2.1f)  #else -			if (gGLManager.mGLVersion < 3.f || gGLManager.mIsIntel) -			{ //only use fixed function by default if GL version < 3.0 or this is an intel graphics chip -				maskFeatures("LowFixedFunction");			 -			} -			else -			{ //same as low, but with "Basic Shaders" enabled -				maskFeatures("Low"); -			} +		// only use fixed function by default if GL version < 3.0 or this is an intel graphics chip +		if (gGLManager.mGLVersion < 3.f || gGLManager.mIsIntel)  #endif -			break; -		case 1: -			maskFeatures("LowMid"); -			break; -		case 2: -			maskFeatures("Mid"); -			break; -		case 3: -			maskFeatures("MidHigh"); -			break; -		case 4: -			maskFeatures("High"); -			break; -		case 5: -			maskFeatures("HighUltra"); -			break; -		case 6: -			maskFeatures("Ultra"); -			break; -		default: -			maskFeatures("Low"); -			break; +		{ +            // same as Low, but with "Basic Shaders" disabled +			features = "LowFixedFunction"; +		}  	} +	maskFeatures(features); +  	applyFeatures(skipFeatures);  	LLViewerShaderMgr::sSkipReload = false; diff --git a/indra/newview/llfeaturemanager.h b/indra/newview/llfeaturemanager.h index ad72c16743..3b8d251236 100755 --- a/indra/newview/llfeaturemanager.h +++ b/indra/newview/llfeaturemanager.h @@ -134,8 +134,18 @@ public:  	// skipFeatures forces skipping of mostly hardware settings  	// that we don't want to change when we change graphics  	// settings -	void setGraphicsLevel(S32 level, bool skipFeatures); -	 +	void setGraphicsLevel(U32 level, bool skipFeatures); + +	// What 'level' values are valid to pass to setGraphicsLevel()? +	// 0 is the low end... +	U32 getMaxGraphicsLevel() const; +	bool isValidGraphicsLevel(U32 level) const; + +	// setGraphicsLevel() levels have names. +	std::string getNameForGraphicsLevel(U32 level) const; +	// returns -1 for unrecognized name (hence S32 rather than U32) +	S32 getGraphicsLevelForName(const std::string& name) const; +  	void applyBaseMasks();  	void applyRecommendedSettings(); diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index 83fb887d81..fea8e34729 100755 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -33,8 +33,10 @@  // Viewer includes  #include "llagent.h" +#include "llagentui.h"  #include "llappviewer.h"   #include "llsecondlifeurls.h" +#include "llslurl.h"  #include "llvoiceclient.h"  #include "lluictrlfactory.h"  #include "llviewertexteditor.h" @@ -250,12 +252,16 @@ LLSD LLFloaterAbout::getInfo()  	LLViewerRegion* region = gAgent.getRegion();  	if (region)  	{ -		const LLVector3d &pos = gAgent.getPositionGlobal(); +		LLVector3d pos = gAgent.getPositionGlobal();  		info["POSITION"] = ll_sd_from_vector3d(pos); +		info["POSITION_LOCAL"] = ll_sd_from_vector3(gAgent.getPosAgentFromGlobal(pos));  		info["REGION"] = gAgent.getRegion()->getName();  		info["HOSTNAME"] = gAgent.getRegion()->getHost().getHostName();  		info["HOSTIP"] = gAgent.getRegion()->getHost().getString();  		info["SERVER_VERSION"] = gLastVersionChannel; +		LLSLURL slurl; +		LLAgentUI::buildSLURL(slurl); +		info["SLURL"] = slurl.getSLURLString();  	}  	// CPU @@ -307,12 +313,12 @@ LLSD LLFloaterAbout::getInfo()  static std::string get_viewer_release_notes_url()  {  	// return a URL to the release notes for this viewer, such as: -	// http://wiki.secondlife.com/wiki/Release_Notes/Second Life Beta Viewer/2.1.0 +	// http://wiki.secondlife.com/wiki/Release_Notes/Second Life Beta Viewer/2.1.0.123456  	std::string url = LLTrans::getString("RELEASE_NOTES_BASE_URL");  	if (! LLStringUtil::endsWith(url, "/"))  		url += "/";  	url += LLVersionInfo::getChannel() + "/"; -	url += LLVersionInfo::getShortVersion(); +	url += LLVersionInfo::getVersion();  	return LLWeb::escapeURL(url);  } diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index 113aa9a8f2..c0afb72cff 100755 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -513,6 +513,7 @@ void LLFloaterAvatarPicker::find()  			url += "/";  		}  		url += "?page_size=100&names="; +		std::replace(text.begin(), text.end(), '.', ' ');  		url += LLURI::escape(text);  		llinfos << "avatar picker " << url << llendl;  		LLHTTPClient::get(url, new LLAvatarPickerResponder(mQueryID, getKey().asString())); @@ -748,7 +749,12 @@ void LLFloaterAvatarPicker::processResponse(const LLUUID& query_id, const LLSD&  		{  			getChildView("ok_btn")->setEnabled(true);  			search_results->setEnabled(true); -			search_results->selectFirstItem(); +			search_results->sortByColumnIndex(1, TRUE); +			std::string text = getChild<LLUICtrl>("Edit")->getValue().asString(); +			if (!search_results->selectItemByLabel(text, TRUE, 1)) +			{ +				search_results->selectFirstItem(); +			}			  			onList();  			search_results->setFocus(TRUE);  		} diff --git a/indra/newview/llfloaterbulkpermission.cpp b/indra/newview/llfloaterbulkpermission.cpp index 39b6e465f3..76f62a7880 100755 --- a/indra/newview/llfloaterbulkpermission.cpp +++ b/indra/newview/llfloaterbulkpermission.cpp @@ -57,6 +57,7 @@ LLFloaterBulkPermission::LLFloaterBulkPermission(const LLSD& seed)  	mDone(FALSE)  {  	mID.generate(); +	mCommitCallbackRegistrar.add("BulkPermission.Ok",		boost::bind(&LLFloaterBulkPermission::onOkBtn, this));  	mCommitCallbackRegistrar.add("BulkPermission.Apply",	boost::bind(&LLFloaterBulkPermission::onApplyBtn, this));  	mCommitCallbackRegistrar.add("BulkPermission.Close",	boost::bind(&LLFloaterBulkPermission::onCloseBtn, this));  	mCommitCallbackRegistrar.add("BulkPermission.CheckAll",	boost::bind(&LLFloaterBulkPermission::onCheckAll, this)); @@ -66,6 +67,21 @@ LLFloaterBulkPermission::LLFloaterBulkPermission(const LLSD& seed)  BOOL LLFloaterBulkPermission::postBuild()  { +	mBulkChangeIncludeAnimations = gSavedSettings.getBOOL("BulkChangeIncludeAnimations"); +	mBulkChangeIncludeBodyParts = gSavedSettings.getBOOL("BulkChangeIncludeBodyParts"); +	mBulkChangeIncludeClothing = gSavedSettings.getBOOL("BulkChangeIncludeClothing"); +	mBulkChangeIncludeGestures = gSavedSettings.getBOOL("BulkChangeIncludeGestures"); +	mBulkChangeIncludeNotecards = gSavedSettings.getBOOL("BulkChangeIncludeNotecards"); +	mBulkChangeIncludeObjects = gSavedSettings.getBOOL("BulkChangeIncludeObjects"); +	mBulkChangeIncludeScripts = gSavedSettings.getBOOL("BulkChangeIncludeScripts"); +	mBulkChangeIncludeSounds = gSavedSettings.getBOOL("BulkChangeIncludeSounds"); +	mBulkChangeIncludeTextures = gSavedSettings.getBOOL("BulkChangeIncludeTextures"); +	mBulkChangeShareWithGroup = gSavedSettings.getBOOL("BulkChangeShareWithGroup"); +	mBulkChangeEveryoneCopy = gSavedSettings.getBOOL("BulkChangeEveryoneCopy"); +	mBulkChangeNextOwnerModify = gSavedSettings.getBOOL("BulkChangeNextOwnerModify"); +	mBulkChangeNextOwnerCopy = gSavedSettings.getBOOL("BulkChangeNextOwnerCopy"); +	mBulkChangeNextOwnerTransfer = gSavedSettings.getBOOL("BulkChangeNextOwnerTransfer"); +  	return TRUE;  } @@ -144,6 +160,12 @@ void LLFloaterBulkPermission::inventoryChanged(LLViewerObject* viewer_object,  	}  } +void LLFloaterBulkPermission::onOkBtn() +{ +	doApply(); +	closeFloater(); +} +  void LLFloaterBulkPermission::onApplyBtn()  {  	doApply(); @@ -151,6 +173,20 @@ void LLFloaterBulkPermission::onApplyBtn()  void LLFloaterBulkPermission::onCloseBtn()  { +	gSavedSettings.setBOOL("BulkChangeIncludeAnimations", mBulkChangeIncludeAnimations); +	gSavedSettings.setBOOL("BulkChangeIncludeBodyParts", mBulkChangeIncludeBodyParts); +	gSavedSettings.setBOOL("BulkChangeIncludeClothing", mBulkChangeIncludeClothing); +	gSavedSettings.setBOOL("BulkChangeIncludeGestures", mBulkChangeIncludeGestures); +	gSavedSettings.setBOOL("BulkChangeIncludeNotecards", mBulkChangeIncludeNotecards); +	gSavedSettings.setBOOL("BulkChangeIncludeObjects", mBulkChangeIncludeObjects); +	gSavedSettings.setBOOL("BulkChangeIncludeScripts", mBulkChangeIncludeScripts); +	gSavedSettings.setBOOL("BulkChangeIncludeSounds", mBulkChangeIncludeSounds); +	gSavedSettings.setBOOL("BulkChangeIncludeTextures", mBulkChangeIncludeTextures); +	gSavedSettings.setBOOL("BulkChangeShareWithGroup", mBulkChangeShareWithGroup); +	gSavedSettings.setBOOL("BulkChangeEveryoneCopy", mBulkChangeEveryoneCopy); +	gSavedSettings.setBOOL("BulkChangeNextOwnerModify", mBulkChangeNextOwnerModify); +	gSavedSettings.setBOOL("BulkChangeNextOwnerCopy", mBulkChangeNextOwnerCopy); +	gSavedSettings.setBOOL("BulkChangeNextOwnerTransfer", mBulkChangeNextOwnerTransfer);  	closeFloater();  } diff --git a/indra/newview/llfloaterbulkpermission.h b/indra/newview/llfloaterbulkpermission.h index 7dd05df7ee..25e76eca65 100755 --- a/indra/newview/llfloaterbulkpermission.h +++ b/indra/newview/llfloaterbulkpermission.h @@ -72,6 +72,7 @@ private:  								bool is_new);  	void onCloseBtn(); +	void onOkBtn();  	void onApplyBtn();  	void onCommitCopy();  	void onCheckAll() { doCheckUncheckAll(TRUE); } @@ -94,6 +95,21 @@ private:  	LLUUID mCurrentObjectID;  	BOOL mDone; +	bool mBulkChangeIncludeAnimations; +	bool mBulkChangeIncludeBodyParts; +	bool mBulkChangeIncludeClothing; +	bool mBulkChangeIncludeGestures; +	bool mBulkChangeIncludeNotecards; +	bool mBulkChangeIncludeObjects; +	bool mBulkChangeIncludeScripts; +	bool mBulkChangeIncludeSounds; +	bool mBulkChangeIncludeTextures; +	bool mBulkChangeShareWithGroup; +	bool mBulkChangeEveryoneCopy; +	bool mBulkChangeNextOwnerModify; +	bool mBulkChangeNextOwnerCopy; +	bool mBulkChangeNextOwnerTransfer; +  	LLUUID mID;  	const char* mStartString; diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp index a3d715530d..b570de14aa 100755 --- a/indra/newview/llfloaterconversationpreview.cpp +++ b/indra/newview/llfloaterconversationpreview.cpp @@ -50,6 +50,7 @@ LLFloaterConversationPreview::LLFloaterConversationPreview(const LLSD& session_i  BOOL LLFloaterConversationPreview::postBuild()  {  	mChatHistory = getChild<LLChatHistory>("chat_history"); +	LLLoadHistoryThread::setLoadEndSignal(boost::bind(&LLFloaterConversationPreview::SetPages, this, _1, _2));  	const LLConversation* conv = LLConversationLog::instance().getConversation(mSessionID);  	std::string name; @@ -70,7 +71,7 @@ BOOL LLFloaterConversationPreview::postBuild()  		name = LLTrans::getString("NearbyChatTitle");  		file = "chat";  	} - +	mChatHistoryFileName = file;  	LLStringUtil::format_map_t args;  	args["[NAME]"] = name;  	std::string title = getString("Title", args); @@ -80,23 +81,46 @@ BOOL LLFloaterConversationPreview::postBuild()  	load_params["load_all_history"] = true;  	load_params["cut_off_todays_date"] = false; -	LLLogChat::loadChatHistory(file, mMessages, load_params); -	mCurrentPage = mMessages.size() / mPageSize; +	LLSD loading; +	loading[LL_IM_TEXT] = LLTrans::getString("loading_chat_logs"); +	mMessages.push_back(loading);  	mPageSpinner = getChild<LLSpinCtrl>("history_page_spin");  	mPageSpinner->setCommitCallback(boost::bind(&LLFloaterConversationPreview::onMoreHistoryBtnClick, this));  	mPageSpinner->setMinValue(1); -	mPageSpinner->setMaxValue(mCurrentPage + 1); -	mPageSpinner->set(mCurrentPage + 1); - -	std::string total_page_num = llformat("/ %d", mCurrentPage + 1); -	getChild<LLTextBox>("page_num_label")->setValue(total_page_num); - +	mPageSpinner->set(1); +	mPageSpinner->setEnabled(false); +	mChatHistoryLoaded = false; +	LLLogChat::startChatHistoryThread(file, load_params);  	return LLFloater::postBuild();  } +void LLFloaterConversationPreview::SetPages(std::list<LLSD>& messages, const std::string& file_name) +{ +	if(file_name == mChatHistoryFileName) +	{ +		mMessages = messages; + + +		mCurrentPage = mMessages.size() / mPageSize; +		mPageSpinner->setEnabled(true); +		mPageSpinner->setMaxValue(mCurrentPage+1); +		mPageSpinner->set(mCurrentPage+1); + +		std::string total_page_num = llformat("/ %d", mCurrentPage+1); +		getChild<LLTextBox>("page_num_label")->setValue(total_page_num); +		mChatHistoryLoaded = true; + +	} + +}  void LLFloaterConversationPreview::draw()  { +	if(mChatHistoryLoaded) +	{ +		showHistory(); +		mChatHistoryLoaded = false; +	}  	LLFloater::draw();  } @@ -128,6 +152,11 @@ void LLFloaterConversationPreview::showHistory()  	for (int msg_num = 0; (iter != mMessages.end() && msg_num < mPageSize); ++iter, ++msg_num)  	{ +		if (iter->size() == 0) +		{ +			continue; +		} +  		LLSD msg = *iter;  		LLUUID from_id 		= LLUUID::null; diff --git a/indra/newview/llfloaterconversationpreview.h b/indra/newview/llfloaterconversationpreview.h index b17ae84b63..389f3dfd09 100755 --- a/indra/newview/llfloaterconversationpreview.h +++ b/indra/newview/llfloaterconversationpreview.h @@ -42,6 +42,7 @@ public:  	virtual ~LLFloaterConversationPreview(){};  	virtual BOOL postBuild(); +	void SetPages(std::list<LLSD>& messages,const std::string& file_name);  	virtual void draw();  	virtual void onOpen(const LLSD& key); @@ -59,6 +60,8 @@ private:  	std::list<LLSD> mMessages;  	std::string		mAccountName;  	std::string		mCompleteName; +	std::string     mChatHistoryFileName; +	bool			mChatHistoryLoaded;  };  #endif /* LLFLOATERCONVERSATIONPREVIEW_H_ */ diff --git a/indra/newview/llfloatergotoline.cpp b/indra/newview/llfloatergotoline.cpp new file mode 100644 index 0000000000..d66e418926 --- /dev/null +++ b/indra/newview/llfloatergotoline.cpp @@ -0,0 +1,160 @@ +/** + * @file llfloatergotoline.h + * @author MartinRJ + * @brief LLFloaterGotoLine class implementation + * + * $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 "llfloatergotoline.h" +#include "llpreviewscript.h" +#include "llfloaterreg.h" +#include "lllineeditor.h" +#include "llviewertexteditor.h" +#include "llviewerwindow.h" + +LLFloaterGotoLine* LLFloaterGotoLine::sInstance = NULL; + +LLFloaterGotoLine::LLFloaterGotoLine(LLScriptEdCore* editor_core) +:       LLFloater(LLSD()), +        mGotoBox(NULL), +        mEditorCore(editor_core) +{ +        buildFromFile("floater_goto_line.xml"); + +        sInstance = this; +         +        // find floater in which script panel is embedded +        LLView* viewp = (LLView*)editor_core; +        while(viewp) +        { +                LLFloater* floaterp = dynamic_cast<LLFloater*>(viewp); +                if (floaterp) +                { +                        floaterp->addDependentFloater(this); +                        break; +                } +                viewp = viewp->getParent(); +        } +} + +BOOL LLFloaterGotoLine::postBuild() +{ +	mGotoBox = getChild<LLLineEditor>("goto_line"); +	mGotoBox->setCommitCallback(boost::bind(&LLFloaterGotoLine::onGotoBoxCommit, this)); +	mGotoBox->setCommitOnFocusLost(FALSE); +        getChild<LLLineEditor>("goto_line")->setPrevalidate(LLTextValidate::validateNonNegativeS32); +        childSetAction("goto_btn", onBtnGoto,this); +        setDefaultBtn("goto_btn"); + +        return TRUE; +} + +//static  +void LLFloaterGotoLine::show(LLScriptEdCore* editor_core) +{ +        if (sInstance && sInstance->mEditorCore && sInstance->mEditorCore != editor_core) +        { +                sInstance->closeFloater(); +                delete sInstance; +        } + +        if (!sInstance) +        { +                // sInstance will be assigned in the constructor. +                new LLFloaterGotoLine(editor_core); +        } + +        sInstance->openFloater(); +} + +LLFloaterGotoLine::~LLFloaterGotoLine() +{ +        sInstance = NULL; +} + +// static  +void LLFloaterGotoLine::onBtnGoto(void *userdata) +{ +        LLFloaterGotoLine* self = (LLFloaterGotoLine*)userdata; +        self->handleBtnGoto(); +} + +void LLFloaterGotoLine::handleBtnGoto() +{ +        S32 row = 0; +        S32 column = 0; +        row = getChild<LLUICtrl>("goto_line")->getValue().asInteger(); +        if (row >= 0) +        { +                if (mEditorCore && mEditorCore->mEditor) +                { +			mEditorCore->mEditor->deselect(); +			mEditorCore->mEditor->setCursor(row, column); +			mEditorCore->mEditor->setFocus(TRUE); +                } +        } +} + +bool LLFloaterGotoLine::hasAccelerators() const +{ +        if (mEditorCore) +        { +                return mEditorCore->hasAccelerators(); +        } +        return FALSE; +} + +BOOL LLFloaterGotoLine::handleKeyHere(KEY key, MASK mask) +{ +        if (mEditorCore) +        { +                return mEditorCore->handleKeyHere(key, mask); +        } + +        return FALSE; +} + +void LLFloaterGotoLine::onGotoBoxCommit() +{ +        S32 row = 0; +        S32 column = 0; +        row = getChild<LLUICtrl>("goto_line")->getValue().asInteger(); +        if (row >= 0) +        { +                if (mEditorCore && mEditorCore->mEditor) +                { +			mEditorCore->mEditor->setCursor(row, column); + +			S32 rownew = 0; +			S32 columnnew = 0; +			mEditorCore->mEditor->getCurrentLineAndColumn( &rownew, &columnnew, FALSE );  // don't include wordwrap +			if (rownew == row && columnnew == column) +			{ +			        mEditorCore->mEditor->deselect(); +			        mEditorCore->mEditor->setFocus(TRUE); +			        sInstance->closeFloater(); +			} //else do nothing (if the cursor-position didn't change) +                } +        } +} diff --git a/indra/newview/llfloatergotoline.h b/indra/newview/llfloatergotoline.h new file mode 100644 index 0000000000..058d601752 --- /dev/null +++ b/indra/newview/llfloatergotoline.h @@ -0,0 +1,66 @@ +/** + * @file llfloatergotoline.h + * @author MartinRJ + * @brief LLFloaterGotoLine class definition + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERGOTOLINE_H +#define LL_LLFLOATERGOTOLINE_H + +#include "llfloater.h" +#include "lllineeditor.h" +#include "llpreviewscript.h" + +class LLScriptEdCore; + +class LLFloaterGotoLine : public LLFloater +{ +public: +        LLFloaterGotoLine(LLScriptEdCore* editor_core); +        ~LLFloaterGotoLine(); + +        /*virtual*/     BOOL    postBuild(); +        static void show(LLScriptEdCore* editor_core); + +        static void onBtnGoto(void* userdata); +        void handleBtnGoto(); + +        LLScriptEdCore* getEditorCore() { return mEditorCore; } +        static LLFloaterGotoLine* getInstance() { return sInstance; } + +        virtual bool hasAccelerators() const; +        virtual BOOL handleKeyHere(KEY key, MASK mask); + +private: + +        LLScriptEdCore* mEditorCore; + +        static LLFloaterGotoLine*       sInstance; + +protected: +	LLLineEditor*			mGotoBox; +        void onGotoBoxCommit(); +}; + +#endif  // LL_LLFLOATERGOTOLINE_H diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 1fbe1be11a..d6b4909318 100755 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -47,6 +47,7 @@  #include "llfloaterpreference.h"  #include "llimview.h"  #include "llnotificationsutil.h" +#include "lltoolbarview.h"  #include "lltransientfloatermgr.h"  #include "llviewercontrol.h"  #include "llconversationview.h" @@ -54,6 +55,7 @@  #include "llworld.h"  #include "llsdserialize.h"  #include "llviewerobjectlist.h" +#include "boost/foreach.hpp"  //  // LLFloaterIMContainer @@ -63,7 +65,8 @@ LLFloaterIMContainer::LLFloaterIMContainer(const LLSD& seed, const Params& param  	mExpandCollapseBtn(NULL),  	mConversationsRoot(NULL),  	mConversationsEventStream("ConversationsEvents"), -	mInitialized(false) +	mInitialized(false), +	mIsFirstLaunch(true)  {      mEnableCallbackRegistrar.add("IMFloaterContainer.Check", boost::bind(&LLFloaterIMContainer::isActionChecked, this, _2));  	mCommitCallbackRegistrar.add("IMFloaterContainer.Action", boost::bind(&LLFloaterIMContainer::onCustomAction,  this, _2)); @@ -113,6 +116,10 @@ void LLFloaterIMContainer::sessionAdded(const LLUUID& session_id, const std::str  void LLFloaterIMContainer::sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id)  { +	if(!isInVisibleChain()) +	{ +		setVisibleAndFrontmost(false); +	}  	selectConversationPair(session_id, true);  	collapseMessagesPane(false);  } @@ -204,6 +211,7 @@ BOOL LLFloaterIMContainer::postBuild()  	// a scroller for folder view  	LLRect scroller_view_rect = mConversationsListPanel->getRect();  	scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); +	scroller_view_rect.mBottom += getChild<LLLayoutStack>("conversations_pane_buttons_stack")->getRect().getHeight();  	LLScrollContainer::Params scroller_params(LLUICtrlFactory::getDefaultParams<LLFolderViewScrollContainer>());  	scroller_params.rect(scroller_view_rect); @@ -221,7 +229,8 @@ BOOL LLFloaterIMContainer::postBuild()  	mExpandCollapseBtn->setClickedCallback(boost::bind(&LLFloaterIMContainer::onExpandCollapseButtonClicked, this));  	mStubCollapseBtn = getChild<LLButton>("stub_collapse_btn");  	mStubCollapseBtn->setClickedCallback(boost::bind(&LLFloaterIMContainer::onStubCollapseButtonClicked, this)); -	getChild<LLButton>("speak_btn")->setClickedCallback(boost::bind(&LLFloaterIMContainer::onSpeakButtonClicked, this)); +    mSpeakBtn = getChild<LLButton>("speak_btn"); +	mSpeakBtn->setClickedCallback(boost::bind(&LLFloaterIMContainer::onSpeakButtonClicked, this));  	childSetAction("add_btn", boost::bind(&LLFloaterIMContainer::onAddButtonClicked, this)); @@ -258,7 +267,6 @@ BOOL LLFloaterIMContainer::postBuild()  void LLFloaterIMContainer::onOpen(const LLSD& key)  {  	LLMultiFloater::onOpen(key); -	openNearbyChat();  	reSelectConversation();  	assignResizeLimits();  } @@ -593,6 +601,7 @@ void LLFloaterIMContainer::setMinimized(BOOL b)  	//Switching from minimized to un-minimized  	if(was_minimized && !b)  	{ +		gToolBarView->flashCommand(LLCommandId("chat"), false);  		LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(mSelectedSession);  		if(session_floater && !session_floater->isTornOff()) @@ -621,7 +630,6 @@ void LLFloaterIMContainer::setVisible(BOOL visible)  			LLFloaterReg::toggleInstanceOrBringToFront(name);              selectConversationPair(LLUUID(NULL), false, false);  		} -		openNearbyChat();  		flashConversationItemWidget(mSelectedSession,false);  		LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(mSelectedSession); @@ -651,7 +659,11 @@ void LLFloaterIMContainer::setVisible(BOOL visible)  		LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(widget_it->second);  		if (widget)  		{ -		    widget->setVisibleIfDetached(visible); +			LLFloater* session_floater = widget->getSessionFloater(); +			if (session_floater != nearby_chat) +			{ +				widget->setVisibleIfDetached(visible); +			}  		}  	} @@ -659,10 +671,37 @@ void LLFloaterIMContainer::setVisible(BOOL visible)  	LLMultiFloater::setVisible(visible);  } +void LLFloaterIMContainer::getDetachedConversationFloaters(floater_list_t& floaters) +{ +	typedef conversations_widgets_map::value_type conv_pair; +	BOOST_FOREACH(conv_pair item, mConversationsWidgets) +	{ +		LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(item.second); +		if (widget) +		{ +			LLFloater* session_floater = widget->getSessionFloater(); +			if (session_floater && session_floater->isDetachedAndNotMinimized()) +			{ +				floaters.push_back(session_floater); +			} +		} +	} +} +  void LLFloaterIMContainer::setVisibleAndFrontmost(BOOL take_focus, const LLSD& key)  {  	LLMultiFloater::setVisibleAndFrontmost(take_focus, key); -    selectConversationPair(getSelectedSession(), false, take_focus); +	// Do not select "Nearby Chat" conversation, since it will bring its window to front +	// Only select other sessions +	if (!getSelectedSession().isNull()) +	{ +		selectConversationPair(getSelectedSession(), false, take_focus); +	} +	if (mInitialized && mIsFirstLaunch) +	{ +		collapseMessagesPane(gSavedPerAccountSettings.getBOOL("ConversationsMessagePaneCollapsed")); +		mIsFirstLaunch = false; +	}  }  void LLFloaterIMContainer::updateResizeLimits() @@ -779,13 +818,6 @@ void LLFloaterIMContainer::reshapeFloaterAndSetResizeLimits(bool collapse, S32 d  	setCanMinimize(at_least_one_panel_is_expanded);      assignResizeLimits(); - -    // 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);  }  void LLFloaterIMContainer::assignResizeLimits() @@ -793,15 +825,12 @@ void LLFloaterIMContainer::assignResizeLimits()  	bool is_conv_pane_expanded = !mConversationsPane->isCollapsed();  	bool is_msg_pane_expanded = !mMessagesPane->isCollapsed(); -	// With two panels visible number of borders is three, because the borders -	// between the panels are merged into one -    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_target_width = is_conv_pane_expanded? -			(is_msg_pane_expanded? -					mConversationsPane->getRect().getWidth() -					: mConversationsPane->getExpandedMinDim()) -			: mConversationsPane->getMinDim(); +    S32 summary_width_of_visible_borders = (is_msg_pane_expanded ? mConversationsStack->getPanelSpacing() : 0) + 1; + +	S32 conv_pane_target_width = is_conv_pane_expanded +		? ( is_msg_pane_expanded?mConversationsPane->getRect().getWidth():mConversationsPane->getExpandedMinDim() ) +		: mConversationsPane->getMinDim(); +  	S32 msg_pane_min_width  = is_msg_pane_expanded ? mMessagesPane->getExpandedMinDim() : 0;  	S32 new_min_width = conv_pane_target_width + msg_pane_min_width + summary_width_of_visible_borders; @@ -961,11 +990,11 @@ void LLFloaterIMContainer::setSortOrder(const LLConversationSort& order)  			conversation_floater->setSortOrder(order);  		}  	} -	 +  	gSavedSettings.setU32("ConversationSortOrder", (U32)order);  } -void LLFloaterIMContainer::getSelectedUUIDs(uuid_vec_t& selected_uuids) +void LLFloaterIMContainer::getSelectedUUIDs(uuid_vec_t& selected_uuids, bool participant_uuids/* = true*/)  {      const std::set<LLFolderViewItem*> selectedItems = mConversationsRoot->getSelectionList(); @@ -978,7 +1007,7 @@ void LLFloaterIMContainer::getSelectedUUIDs(uuid_vec_t& selected_uuids)          conversationItem = static_cast<LLConversationItem *>((*it)->getViewModelItem());  		//When a one-on-one conversation exists, retrieve the participant id from the conversation floater -		if(conversationItem->getType() == LLConversationItem::CONV_SESSION_1_ON_1) +		if(conversationItem->getType() == LLConversationItem::CONV_SESSION_1_ON_1 && participant_uuids)  		{  			LLFloaterIMSession * conversation_floaterp = LLFloaterIMSession::findInstance(conversationItem->getUUID());  			LLUUID participant_id = conversation_floaterp->getOtherParticipantUUID(); @@ -1137,6 +1166,11 @@ void LLFloaterIMContainer::doToSelectedConversation(const std::string& command,          {              LLFloater::onClickClose(conversationFloater);          } +        else if("close_selected_conversations" == command) +        { +        	getSelectedUUIDs(selectedIDS,false); +        	closeSelectedConversations(selectedIDS); +        }          else if("open_voice_conversation" == command)          {              gIMMgr->startCall(conversationItem->getUUID()); @@ -1147,7 +1181,7 @@ void LLFloaterIMContainer::doToSelectedConversation(const std::string& command,          }          else if("chat_history" == command)          { -			if (selectedIDS.size() > 0) +        	if (selectedIDS.size() > 0)  			{  				LLAvatarActions::viewChatHistory(selectedIDS.front());  			} @@ -1160,6 +1194,17 @@ void LLFloaterIMContainer::doToSelectedConversation(const std::string& command,          	}          }      } +    //if there is no LLFloaterIMSession* instance for selected conversation it might be Nearby chat +    else +    { +    	if(conversationItem->getType() == LLConversationItem::CONV_SESSION_NEARBY) +    	{ +    		if("chat_history" == command) +    	    { +    	      	LLFloaterReg::showInstance("preview_conversation", LLSD(LLUUID::null), true); +    	    } +    	} +    }  }  void LLFloaterIMContainer::doToSelected(const LLSD& userdata) @@ -1189,7 +1234,7 @@ void LLFloaterIMContainer::doToSelectedGroup(const LLSD& userdata)      if (action == "group_profile")      { -        LLGroupActions::show(mSelectedSession); +    	LLGroupActions::show(mSelectedSession);      }      else if (action == "activate_group")      { @@ -1215,7 +1260,19 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata)  	//Enable Chat history item for ad-hoc and group conversations  	if ("can_chat_history" == item && uuids.size() > 0)  	{ -		return LLLogChat::isTranscriptExist(uuids.front()); +		//Disable menu item if selected participant is user agent +		if(uuids.front() != gAgentID) +		{ +			if (getCurSelectedViewModelItem()->getType() == LLConversationItem::CONV_SESSION_NEARBY) +			{ +				return LLLogChat::isNearbyTranscriptExist(); +			} +			else +			{ +				bool is_group = (getCurSelectedViewModelItem()->getType() == LLConversationItem::CONV_SESSION_GROUP); +				return LLLogChat::isTranscriptExist(uuids.front(),is_group); +			} +		}  	}  	// If nothing is selected(and selected item is not group chat), everything needs to be disabled @@ -1890,13 +1947,6 @@ void LLFloaterIMContainer::openNearbyChat()  	}  } -void LLFloaterIMContainer::onNearbyChatClosed() -{ -	// If nearby chat is the only remaining conversation and it is closed, close whole conversation floater as well -	if (mConversationsItems.size() == 1) -		closeFloater(); -} -  void LLFloaterIMContainer::reSelectConversation()  {  	LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(mSelectedSession); @@ -1908,7 +1958,6 @@ void LLFloaterIMContainer::reSelectConversation()  void LLFloaterIMContainer::updateSpeakBtnState()  { -	LLButton* mSpeakBtn = getChild<LLButton>("speak_btn");  	mSpeakBtn->setToggleState(LLVoiceClient::getInstance()->getUserPTTState());  	mSpeakBtn->setEnabled(LLAgent::isActionAllowed("speak"));  } @@ -1929,6 +1978,17 @@ void LLFloaterIMContainer::flashConversationItemWidget(const LLUUID& session_id,  	}  } +void LLFloaterIMContainer::highlightConversationItemWidget(const LLUUID& session_id, bool is_highlighted) +{ +	//Finds the conversation line item to highlight using the session_id +	LLConversationViewSession * widget = dynamic_cast<LLConversationViewSession *>(get_ptr_in_map(mConversationsWidgets,session_id)); + +	if (widget) +	{ +		widget->setHighlightState(is_highlighted); +	} +} +  bool LLFloaterIMContainer::isScrolledOutOfSight(LLConversationViewSession* conversation_item_widget)  {  	llassert(conversation_item_widget != NULL); @@ -1944,23 +2004,28 @@ bool LLFloaterIMContainer::isScrolledOutOfSight(LLConversationViewSession* conve  BOOL LLFloaterIMContainer::handleKeyHere(KEY key, MASK mask )  { +	BOOL handled = FALSE; +  	if(mask == MASK_ALT)  	{  		if (KEY_RETURN == key )  		{  			expandConversation(); +			handled = TRUE;  		}  		if ((KEY_DOWN == key ) || (KEY_RIGHT == key))  		{  			selectNextorPreviousConversation(true); +			handled = TRUE;  		}  		if ((KEY_UP == key) || (KEY_LEFT == key))  		{  			selectNextorPreviousConversation(false); +			handled = TRUE;  		}  	} -	return TRUE; +	return handled;  }  bool LLFloaterIMContainer::selectAdjacentConversation(bool focus_selected) @@ -2017,7 +2082,22 @@ void LLFloaterIMContainer::expandConversation()  	}  } -void LLFloaterIMContainer::closeFloater(bool app_quitting/* = false*/) +// By default, if torn off session is currently frontmost, LLFloater::isFrontmost() will return FALSE, which can lead to some bugs +// So LLFloater::isFrontmost() is overriden here to check both selected session and the IM floater itself +// Exclude "Nearby Chat" session from the check, as "Nearby Chat" window and "Conversations" floater can be brought +// to front independently +/*virtual*/ +BOOL LLFloaterIMContainer::isFrontmost() +{ +	LLFloaterIMSessionTab* selected_session = LLFloaterIMSessionTab::getConversation(mSelectedSession); +	LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); +	return (selected_session && selected_session->isFrontmost() && (selected_session != nearby_chat)) +		|| LLFloater::isFrontmost(); +} + +// For conversations, closeFloater() (linked to Ctrl-W) does not actually close the floater but the active conversation. +// This is intentional so it doesn't confuse the user. onClickCloseBtn() closes the whole floater. +void LLFloaterIMContainer::onClickCloseBtn()  {  	// Always unminimize before trying to close.  	// Most of the time the user will never see this state. @@ -2026,7 +2106,80 @@ void LLFloaterIMContainer::closeFloater(bool app_quitting/* = false*/)  		LLMultiFloater::setMinimized(FALSE);  	} -	LLFloater::closeFloater(app_quitting); +	LLFloater::closeFloater(); +} + +void LLFloaterIMContainer::closeHostedFloater() +{ +	onClickCloseBtn(); +} + +void LLFloaterIMContainer::closeAllConversations() +{ +	LLDynamicArray<LLUUID> ids; +	for (conversations_items_map::iterator it_session = mConversationsItems.begin(); it_session != mConversationsItems.end(); it_session++) +	{ +		LLUUID session_id = it_session->first; +		if (session_id != LLUUID()) +		{ +			ids.push_back(session_id); +		} +	} + +	for (LLDynamicArray<LLUUID>::const_iterator it = ids.begin(); it != ids.end(); 	++it) +	{ +		LLFloaterIMSession *conversationFloater = LLFloaterIMSession::findInstance(*it); +		LLFloater::onClickClose(conversationFloater); +	} +} + +void LLFloaterIMContainer::closeSelectedConversations(const uuid_vec_t& ids) +{ +	for (uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); ++it) +	{ +		//We don't need to close Nearby chat, so skip it +		if (*it != LLUUID()) +		{ +			LLFloaterIMSession *conversationFloater = LLFloaterIMSession::findInstance(*it); +			if(conversationFloater) +			{ +				LLFloater::onClickClose(conversationFloater); +			} +		} +	} +} +void LLFloaterIMContainer::closeFloater(bool app_quitting/* = false*/) +{ +	if(app_quitting) +	{ +		closeAllConversations(); +		onClickCloseBtn(); +	} +	else +	{ +		// Check for currently active session +		LLUUID session_id = getSelectedSession(); +		// If current session is Nearby Chat or there is only one session remaining, close the floater +		if (mConversationsItems.size() == 1 || session_id == LLUUID() || app_quitting) +		{ +			onClickCloseBtn(); +		} +		else +		{ +			// Otherwise, close current conversation +			LLFloaterIMSessionTab* active_conversation = LLFloaterIMSessionTab::getConversation(session_id); +			if (active_conversation) +			{ +				active_conversation->closeFloater(); +			} +		} +	} +} + +void LLFloaterIMContainer::handleReshape(const LLRect& rect, bool by_user) +{ +	LLMultiFloater::handleReshape(rect, by_user); +	storeRectControl();  }  // EOF diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index e39d20ec35..36da457cac 100755 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -63,6 +63,8 @@ public:  	/*virtual*/ void setVisible(BOOL visible);  	/*virtual*/ void setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD());  	/*virtual*/ void updateResizeLimits(); +	/*virtual*/ void handleReshape(const LLRect& rect, bool by_user); +  	void onCloseFloater(LLUUID& id);  	/*virtual*/ void addFloater(LLFloater* floaterp,  @@ -105,8 +107,6 @@ public:  	LLConversationItem* getSessionModel(const LLUUID& session_id) { return get_ptr_in_map(mConversationsItems,session_id); }  	LLConversationSort& getSortOrder() { return mConversationViewModel.getSorter(); } -	void onNearbyChatClosed(); -  	// Handling of lists of participants is public so to be common with llfloatersessiontab  	// *TODO : Find a better place for this.      bool checkContextMenuItem(const std::string& item, uuid_vec_t& selectedIDS); @@ -116,6 +116,10 @@ public:  	void assignResizeLimits();  	virtual BOOL handleKeyHere(KEY key, MASK mask );  	/*virtual*/ void closeFloater(bool app_quitting = false); +    void closeAllConversations(); +    void closeSelectedConversations(const uuid_vec_t& ids); +	/*virtual*/ BOOL isFrontmost(); +  private:  	typedef std::map<LLUUID,LLFloater*> avatarID_panel_map_t; @@ -130,6 +134,8 @@ private:  	void onStubCollapseButtonClicked();  	void processParticipantsStyleUpdate();  	void onSpeakButtonClicked(); +	/*virtual*/ void onClickCloseBtn(); +	/*virtual*/ void closeHostedFloater();  	void collapseConversationsPane(bool collapse, bool save_is_allowed=true); @@ -144,7 +150,7 @@ private:  	void setSortOrderParticipants(const LLConversationFilter::ESortOrderType order);  	void setSortOrder(const LLConversationSort& order); -    void getSelectedUUIDs(uuid_vec_t& selected_uuids); +    void getSelectedUUIDs(uuid_vec_t& selected_uuids, bool participant_uuids = true);      const LLConversationItem * getCurSelectedViewModelItem();      void getParticipantUUIDs(uuid_vec_t& selected_uuids);      void doToSelected(const LLSD& userdata); @@ -169,6 +175,7 @@ private:  	LLButton* mExpandCollapseBtn;  	LLButton* mStubCollapseBtn; +    LLButton* mSpeakBtn;  	LLPanel* mStubPanel;  	LLTextBox* mStubTextBox;  	LLLayoutPanel* mMessagesPane; @@ -176,6 +183,7 @@ private:  	LLLayoutStack* mConversationsStack;  	bool mInitialized; +	bool mIsFirstLaunch;  	LLUUID mSelectedSession;  	std::string mGeneralTitle; @@ -190,9 +198,12 @@ public:  	void updateSpeakBtnState();  	static bool isConversationLoggingAllowed();  	void flashConversationItemWidget(const LLUUID& session_id, bool is_flashes); +	void highlightConversationItemWidget(const LLUUID& session_id, bool is_highlighted);  	bool isScrolledOutOfSight(LLConversationViewSession* conversation_item_widget);  	boost::signals2::connection mMicroChangedSignal;  	S32 getConversationListItemSize() { return mConversationsWidgets.size(); } +	typedef std::list<LLFloater*> floater_list_t; +	void getDetachedConversationFloaters(floater_list_t& floaters);  private:  	LLConversationViewSession* createConversationItemWidget(LLConversationItem* item); diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 56b0c15cb9..3d77ea4f0b 100755 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -125,7 +125,7 @@ BOOL LLFloaterIMNearbyChat::postBuild()  	setTitle(LLTrans::getString("NearbyChatTitle"));  	// obsolete, but may be needed for backward compatibility? -	gSavedSettings.declareS32("nearbychat_showicons_and_names", 2, "NearByChat header settings", true); +	gSavedSettings.declareS32("nearbychat_showicons_and_names", 2, "NearByChat header settings", LLControlVariable::PERSIST_NONDFT);  	if (gSavedPerAccountSettings.getBOOL("LogShowHistory"))  	{ @@ -138,19 +138,28 @@ BOOL LLFloaterIMNearbyChat::postBuild()  // virtual  void LLFloaterIMNearbyChat::closeHostedFloater()  { -	// Should check how many conversations are ongoing. Close all if 1 only (the Nearby Chat), select next one otherwise +	// If detached from conversations window close anyway +	if (!getHost()) +	{ +		setVisible(FALSE); +	} + +	// Should check how many conversations are ongoing. Select next to "Nearby Chat" in case there are some other besides. +	// Close conversations window in case "Nearby Chat" is attached and the only conversation  	LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance();  	if (floater_container->getConversationListItemSize() == 1)  	{ -		floater_container->closeFloater(); +		if (getHost()) +		{ +			floater_container->closeFloater(); +		}  	}  	else  	{  		if (!getHost())  		{ -			setVisible(FALSE); +			floater_container->selectNextConversationByID(LLUUID());  		} -		floater_container->selectNextConversationByID(LLUUID());  	}  } @@ -262,7 +271,7 @@ void LLFloaterIMNearbyChat::setVisibleAndFrontmost(BOOL take_focus, const LLSD&  {  	LLFloaterIMSessionTab::setVisibleAndFrontmost(take_focus, key); -	if(!isTornOff() && matchesKey(key)) +	if(matchesKey(key))  	{  		LLFloaterIMContainer::getInstance()->selectConversationPair(mSessionID, true, take_focus);  	} @@ -296,7 +305,6 @@ void LLFloaterIMNearbyChat::onClose(bool app_quitting)  {  	// Override LLFloaterIMSessionTab::onClose() so that Nearby Chat is not removed from the conversation floater  	LLFloaterIMSessionTab::restoreFloater(); -	onClickCloseBtn();  }  // virtual @@ -306,13 +314,7 @@ void LLFloaterIMNearbyChat::onClickCloseBtn()  	{  		return;  	} -	LLFloaterIMSessionTab::onTearOffClicked(); -	 -	LLFloaterIMContainer *im_box = LLFloaterIMContainer::findInstance(); -	if (im_box) -	{ -		im_box->onNearbyChatClosed(); -	} +	closeHostedFloater();  }  void LLFloaterIMNearbyChat::onChatFontChange(LLFontGL* fontp) @@ -350,11 +352,17 @@ bool LLFloaterIMNearbyChat::isChatVisible() const  void LLFloaterIMNearbyChat::showHistory()  {  	openFloater(); +	LLFloaterIMContainer::getInstance()->selectConversation(LLUUID(NULL)); +  	if(!isMessagePaneExpanded())  	{  		restoreFloater();  		setFocus(true);  	} +	else +	{ +		LLFloaterIMContainer::getInstance()->setFocus(TRUE); +	}  	setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT);  } @@ -568,7 +576,10 @@ void LLFloaterIMNearbyChat::sendChat( EChatType type )  			if (0 == channel)  			{  				// discard returned "found" boolean -				LLGestureMgr::instance().triggerAndReviseString(utf8text, &utf8_revised_text); +				if(!LLGestureMgr::instance().triggerAndReviseString(utf8text, &utf8_revised_text)) +				{ +					utf8_revised_text = utf8text; +				}  			}  			else  			{ @@ -582,7 +593,7 @@ void LLFloaterIMNearbyChat::sendChat( EChatType type )  			if (!utf8_revised_text.empty())  			{  				// Chat with animation -				sendChatFromViewer(utf8_revised_text, type, TRUE); +				sendChatFromViewer(utf8_revised_text, type, gSavedSettings.getBOOL("PlayChatAnim"));  			}  		} @@ -636,10 +647,7 @@ void LLFloaterIMNearbyChat::addMessage(const LLChat& chat,bool archive,const LLS  void LLFloaterIMNearbyChat::onChatBoxCommit()  { -	if (mInputEditor->getText().length() > 0) -	{ -		sendChat(CHAT_TYPE_NORMAL); -	} +	sendChat(CHAT_TYPE_NORMAL);  	gAgent.stopTyping();  } diff --git a/indra/newview/llfloaterimnearbychathandler.cpp b/indra/newview/llfloaterimnearbychathandler.cpp index 9ce5e12897..cc00b6fd10 100755 --- a/indra/newview/llfloaterimnearbychathandler.cpp +++ b/indra/newview/llfloaterimnearbychathandler.cpp @@ -606,6 +606,7 @@ void LLFloaterIMNearbyChatHandler::processChat(const LLChat& chat_msg,  		//Don't show nearby toast, if conversation is visible and selected  		if ((nearby_chat->hasFocus()) || +			(LLFloater::isVisible(nearby_chat) && nearby_chat->isTornOff() && !nearby_chat->isMinimized()) ||  		    ((im_box->getSelectedSession().isNull() &&  				((LLFloater::isVisible(im_box) && !im_box->isMinimized() && im_box->isFrontmost())  						|| (LLFloater::isVisible(nearby_chat) && !nearby_chat->isMinimized() && nearby_chat->isFrontmost()))))) diff --git a/indra/newview/llfloaterimnearbychatlistener.cpp b/indra/newview/llfloaterimnearbychatlistener.cpp index 14a22bcd84..5a5f6c72c8 100755 --- a/indra/newview/llfloaterimnearbychatlistener.cpp +++ b/indra/newview/llfloaterimnearbychatlistener.cpp @@ -33,7 +33,7 @@  #include "llagent.h"  #include "llchat.h" - +#include "llviewercontrol.h"  LLFloaterIMNearbyChatListener::LLFloaterIMNearbyChatListener(LLFloaterIMNearbyChat & chatbar) @@ -95,6 +95,6 @@ void LLFloaterIMNearbyChatListener::sendChat(LLSD const & chat_data) const  	}  	// Send it as if it was typed in -	mChatbar.sendChatFromViewer(chat_to_send, type_o_chat, (BOOL)(channel == 0)); +	mChatbar.sendChatFromViewer(chat_to_send, type_o_chat, ((BOOL)(channel == 0)) && gSavedSettings.getBOOL("PlayChatAnim"));  } diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index 8ec85e1160..5cb9df5625 100755 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -109,18 +109,6 @@ void LLFloaterIMSession::refresh()  void LLFloaterIMSession::onTearOffClicked()  {      LLFloaterIMSessionTab::onTearOffClicked(); - -    if(mIsP2PChat) -    { -        if(isTornOff()) -        { -            mSpeakingIndicator->setSpeakerId(mOtherParticipantUUID, mSessionID); -        } -        else -        { -            mSpeakingIndicator->setSpeakerId(LLUUID::null); -        } -    }  }  // virtual @@ -442,8 +430,11 @@ void LLFloaterIMSession::addSessionParticipants(const uuid_vec_t& uuids)  	}  	else  	{ -		// remember whom we have invited, to notify others later, when the invited ones actually join -		mInvitedParticipants.insert(mInvitedParticipants.end(), uuids.begin(), uuids.end()); +		if(findInstance(mSessionID)) +		{ +			// remember whom we have invited, to notify others later, when the invited ones actually join +			mInvitedParticipants.insert(mInvitedParticipants.end(), uuids.begin(), uuids.end()); +		}  		inviteToSession(uuids);  	} @@ -469,13 +460,18 @@ void LLFloaterIMSession::addP2PSessionParticipants(const LLSD& notification, con  	temp_ids.insert(temp_ids.end(), uuids.begin(), uuids.end());  	// then we can close the current session -	onClose(false); +	if(findInstance(mSessionID)) +	{ +		onClose(false); + +		// remember whom we have invited, to notify others later, when the invited ones actually join +		mInvitedParticipants.insert(mInvitedParticipants.end(), uuids.begin(), uuids.end()); +	}  	// we start a new session so reset the initialization flag  	mSessionInitialized = false; -	// remember whom we have invited, to notify others later, when the invited ones actually join -	mInvitedParticipants.insert(mInvitedParticipants.end(), uuids.begin(), uuids.end()); +  	// Start a new ad hoc voice call if we invite new participants to a P2P call,  	// or start a text chat otherwise. diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index ce6e639305..0ccfdb9a7b 100755 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -55,7 +55,6 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id)    ,  mSessionID(session_id.asUUID())    , mConversationsRoot(NULL)    , mScroller(NULL) -  , mSpeakingIndicator(NULL)    , mChatHistory(NULL)    , mInputEditor(NULL)    , mInputEditorPad(0) @@ -212,7 +211,7 @@ void LLFloaterIMSessionTab::assignResizeLimits()  	mRightPartPanel->setIgnoreReshape(is_participants_pane_collapsed);      S32 participants_pane_target_width = is_participants_pane_collapsed? -    		0 : (mParticipantListPanel->getRect().getWidth() + LLPANEL_BORDER_WIDTH); +    		0 : (mParticipantListPanel->getRect().getWidth() + mParticipantListAndHistoryStack->getPanelSpacing());      S32 new_min_width = participants_pane_target_width + mRightPartPanel->getExpandedMinDim() + mFloaterExtraWidth; @@ -241,7 +240,10 @@ BOOL LLFloaterIMSessionTab::postBuild()  	mTearOffBtn->setCommitCallback(boost::bind(&LLFloaterIMSessionTab::onTearOffClicked, this));  	mGearBtn = getChild<LLButton>("gear_btn"); - +    mAddBtn = getChild<LLButton>("add_btn"); +	mVoiceButton = getChild<LLButton>("voice_call_btn"); +    mTranslationCheckBox = getChild<LLUICtrl>("translate_chat_checkbox_lp"); +      	mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel");  	mRightPartPanel = getChild<LLLayoutPanel>("right_part_holder"); @@ -256,8 +258,6 @@ BOOL LLFloaterIMSessionTab::postBuild()  	scroller_params.rect(scroller_view_rect);  	mScroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params);  	mScroller->setFollowsAll(); -	 -    mSpeakingIndicator = getChild<LLOutputMonitorCtrl>("speaking_indicator");  	// Insert that scroller into the panel widgets hierarchy  	mParticipantListPanel->addChild(mScroller);	 @@ -270,6 +270,7 @@ BOOL LLFloaterIMSessionTab::postBuild()  	mInputPanels = getChild<LLLayoutStack>("input_panels");  	mInputEditor->setTextExpandedCallback(boost::bind(&LLFloaterIMSessionTab::reshapeChatLayoutPanel, this)); +	mInputEditor->setMouseUpCallback(boost::bind(&LLFloaterIMSessionTab::onInputEditorClicked, this));  	mInputEditor->setCommitOnFocusLost( FALSE );  	mInputEditor->setPassDelete(TRUE);  	mInputEditor->setFont(LLViewerChat::getChatFont()); @@ -372,7 +373,7 @@ void LLFloaterIMSessionTab::draw()  void LLFloaterIMSessionTab::enableDisableCallBtn()  { -    getChildView("voice_call_btn")->setEnabled( +    mVoiceButton->setEnabled(      		mSessionID.notNull()      		&& mSession      		&& mSession->mSessionInitialized @@ -399,6 +400,16 @@ void LLFloaterIMSessionTab::onFocusLost()  	LLTransientDockableFloater::onFocusLost();  } +void LLFloaterIMSessionTab::onInputEditorClicked() +{ +	LLFloaterIMContainer* im_box = LLFloaterIMContainer::findInstance(); +	if (im_box) +	{ +		im_box->flashConversationItemWidget(mSessionID,false); +	} +	gToolBarView->flashCommand(LLCommandId("chat"), false); +} +  std::string LLFloaterIMSessionTab::appendTime()  {  	time_t utc_time; @@ -758,7 +769,7 @@ void LLFloaterIMSessionTab::reshapeChatLayoutPanel()  void LLFloaterIMSessionTab::showTranslationCheckbox(BOOL show)  { -	getChild<LLUICtrl>("translate_chat_checkbox_lp")->setVisible(mIsNearbyChat? show : FALSE); +	mTranslationCheckBox->setVisible(mIsNearbyChat && show);  }  // static @@ -805,15 +816,10 @@ void LLFloaterIMSessionTab::reloadEmptyFloaters()  void LLFloaterIMSessionTab::updateCallBtnState(bool callIsActive)  { -	LLButton* voiceButton = getChild<LLButton>("voice_call_btn"); -	voiceButton->setImageOverlay( -			callIsActive? getString("call_btn_stop") : getString("call_btn_start")); - -	voiceButton->setToolTip( -			callIsActive? getString("end_call_button_tooltip") : getString("start_call_button_tooltip")); +	mVoiceButton->setImageOverlay(callIsActive? getString("call_btn_stop") : getString("call_btn_start")); +	mVoiceButton->setToolTip(callIsActive? getString("end_call_button_tooltip") : getString("start_call_button_tooltip"));  	enableDisableCallBtn(); -  }  void LLFloaterIMSessionTab::onSlide(LLFloaterIMSessionTab* self) @@ -898,6 +904,7 @@ void LLFloaterIMSessionTab::restoreFloater()  		mExpandCollapseLineBtn->setImageOverlay(getString("expandline_icon"));  		setMessagePaneExpanded(true);  		saveCollapsedState(); +		mInputEditor->enableSingleLineMode(false);  		enableResizeCtrls(true, true, true);  	}  } @@ -953,8 +960,8 @@ void LLFloaterIMSessionTab::updateGearBtn()  	if(prevVisibility != mGearBtn->getVisible())  	{  		LLRect gear_btn_rect =  mGearBtn->getRect(); -		LLRect add_btn_rect = getChild<LLButton>("add_btn")->getRect(); -		LLRect call_btn_rect = getChild<LLButton>("voice_call_btn")->getRect(); +		LLRect add_btn_rect = mAddBtn->getRect(); +		LLRect call_btn_rect = mVoiceButton->getRect();  		S32 gap_width = call_btn_rect.mLeft - add_btn_rect.mRight;  		S32 right_shift = gear_btn_rect.getWidth() + gap_width;  		if(mGearBtn->getVisible()) @@ -968,24 +975,24 @@ void LLFloaterIMSessionTab::updateGearBtn()  			add_btn_rect.translate(-right_shift,0);  			call_btn_rect.translate(-right_shift,0);  		} -		getChild<LLButton>("add_btn")->setRect(add_btn_rect); -		getChild<LLButton>("voice_call_btn")->setRect(call_btn_rect); +		mAddBtn->setRect(add_btn_rect); +		mVoiceButton->setRect(call_btn_rect);  	}  }  void LLFloaterIMSessionTab::initBtns()  {  	LLRect gear_btn_rect =  mGearBtn->getRect(); -	LLRect add_btn_rect = getChild<LLButton>("add_btn")->getRect(); -	LLRect call_btn_rect = getChild<LLButton>("voice_call_btn")->getRect(); +	LLRect add_btn_rect = mAddBtn->getRect(); +	LLRect call_btn_rect = mVoiceButton->getRect();  	S32 gap_width = call_btn_rect.mLeft - add_btn_rect.mRight;  	S32 right_shift = gear_btn_rect.getWidth() + gap_width;  	add_btn_rect.translate(-right_shift,0);  	call_btn_rect.translate(-right_shift,0); -	getChild<LLButton>("add_btn")->setRect(add_btn_rect); -	getChild<LLButton>("voice_call_btn")->setRect(call_btn_rect); +	mAddBtn->setRect(add_btn_rect); +	mVoiceButton->setRect(call_btn_rect);  }  // static @@ -1083,21 +1090,26 @@ void LLFloaterIMSessionTab::saveCollapsedState()  }  BOOL LLFloaterIMSessionTab::handleKeyHere(KEY key, MASK mask )  { +	BOOL handled = FALSE; +  	if(mask == MASK_ALT)  	{  		LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance();  		if (KEY_RETURN == key && !isTornOff())  		{  			floater_container->expandConversation(); +			handled = TRUE;  		}  		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 TRUE; +	return handled;  } diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index 302d5a8066..e7b05a584b 100755 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -171,8 +171,7 @@ protected:  	LLFolderView* mConversationsRoot;  	LLScrollContainer* mScroller; -    LLOutputMonitorCtrl* mSpeakingIndicator; -	LLChatHistory* mChatHistory; +    LLChatHistory* mChatHistory;  	LLChatEntry* mInputEditor;  	LLLayoutPanel * mChatLayoutPanel;  	LLLayoutStack * mInputPanels; @@ -182,6 +181,9 @@ protected:  	LLButton* mTearOffBtn;  	LLButton* mCloseBtn;  	LLButton* mGearBtn; +	LLButton* mAddBtn; +    LLButton* mVoiceButton; +    LLUICtrl* mTranslationCheckBox;  private:  	// Handling selection and contextual menu @@ -201,6 +203,8 @@ private:  	 */  	void reshapeChatLayoutPanel(); +	void onInputEditorClicked(); +  	bool checkIfTornOff();      bool mIsHostAttached;      bool mHasVisibleBeenInitialized; diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 55b03986d0..4ebe813be6 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -452,6 +452,7 @@ BOOL LLFloaterPreference::postBuild()  	getChild<LLComboBox>("ConferenceIMOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"ConferenceIMOptions"));  	getChild<LLComboBox>("GroupChatOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"GroupChatOptions"));  	getChild<LLComboBox>("NearbyChatOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"NearbyChatOptions")); +	getChild<LLComboBox>("ObjectIMOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"ObjectIMOptions"));  	// if floater is opened before login set default localized do not disturb message  	if (LLStartUp::getStartupState() < STATE_STARTED) @@ -721,6 +722,7 @@ void LLFloaterPreference::onOpen(const LLSD& key)  	onNotificationsChange("ConferenceIMOptions");  	onNotificationsChange("GroupChatOptions");  	onNotificationsChange("NearbyChatOptions"); +	onNotificationsChange("ObjectIMOptions");  	LLPanelLogin::setAlwaysRefresh(true);  	refresh(); @@ -928,7 +930,7 @@ void LLFloaterPreference::onNotificationsChange(const std::string& OptionName)  	bool show_notifications_alert = true;  	for (notifications_map::iterator it_notification = mNotificationOptions.begin(); it_notification != mNotificationOptions.end(); it_notification++)  	{ -		if(it_notification->second != "None") +		if(it_notification->second != "No action")  		{  			show_notifications_alert = false;  			break; diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp index 586965e5a0..c28657dbcd 100755 --- a/indra/newview/llfolderviewmodelinventory.cpp +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -74,6 +74,7 @@ void LLFolderViewModelInventory::sort( LLFolderViewFolder* folder )  		it != end_it;  		++it)  	{ +        // Recursive call to sort() on child (CHUI-849)  		LLFolderViewFolder* child_folderp = *it;  		sort(child_folderp); @@ -129,12 +130,12 @@ void LLFolderViewModelItemInventory::requestSort()  void LLFolderViewModelItemInventory::setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset, std::string::size_type string_size)  {  	LLFolderViewModelItemCommon::setPassedFilter(passed, filter_generation, string_offset, string_size); - -	bool passed_filter_before = mPrevPassedAllFilters; +	bool before = mPrevPassedAllFilters;  	mPrevPassedAllFilters = passedFilter(filter_generation); -	if (passed_filter_before != mPrevPassedAllFilters) +    if (before != mPrevPassedAllFilters)  	{ +        // Need to rearrange the folder if the filtered state of the item changed  		LLFolderViewFolder* parent_folder = mFolderViewItem->getParentFolder();  		if (parent_folder)  		{ @@ -150,11 +151,11 @@ bool LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* ite  	bool continue_filtering = true;  	if (item->getLastFilterGeneration() < filter_generation)  	{ -		// recursive application of the filter for child items +		// Recursive application of the filter for child items (CHUI-849)  		continue_filtering = item->filter( filter );  	} -	// track latest generation to pass any child items, for each folder up to root +	// Update latest generation to pass filter in parent and propagate up to root  	if (item->passedFilter())  	{  		LLFolderViewModelItemInventory* view_model = this; @@ -174,53 +175,61 @@ bool LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter)  	const S32 filter_generation = filter.getCurrentGeneration();  	const S32 must_pass_generation = filter.getFirstRequiredGeneration(); -	if (getLastFilterGeneration() >= must_pass_generation  +    if (getLastFilterGeneration() >= must_pass_generation  		&& getLastFolderFilterGeneration() >= must_pass_generation  		&& !passedFilter(must_pass_generation))  	{  		// failed to pass an earlier filter that was a subset of the current one -		// go ahead and flag this item as done +		// go ahead and flag this item as not pass  		setPassedFilter(false, filter_generation);  		setPassedFolderFilter(false, filter_generation);  		return true;  	} -	const bool passed_filter_folder = (getInventoryType() == LLInventoryType::IT_CATEGORY)  -		? filter.checkFolder(this) -		: true; +    // *TODO : Revise the logic for fast pass on less restrictive filter case +    /* +     const S32 sufficient_pass_generation = filter.getFirstSuccessGeneration(); +    if (getLastFilterGeneration() >= sufficient_pass_generation +		&& getLastFolderFilterGeneration() >= sufficient_pass_generation +		&& passedFilter(sufficient_pass_generation)) +	{ +		// passed an earlier filter that was a superset of the current one +		// go ahead and flag this item as pass +		setPassedFilter(true, filter_generation); +		setPassedFolderFilter(true, filter_generation); +		return true; +	} +     */ +     +	const bool passed_filter_folder = (getInventoryType() == LLInventoryType::IT_CATEGORY) ? filter.checkFolder(this) : true;  	setPassedFolderFilter(passed_filter_folder, filter_generation); -	if(!mChildren.empty() +	bool continue_filtering = true; + +	if (!mChildren.empty()  		&& (getLastFilterGeneration() < must_pass_generation // haven't checked descendants against minimum required generation to pass -			|| descendantsPassedFilter(must_pass_generation))) // or at least one descendant has passed the minimum requirement +            || descendantsPassedFilter(must_pass_generation))) // or at least one descendant has passed the minimum requirement  	{  		// now query children -		for (child_list_t::iterator iter = mChildren.begin(), end_iter = mChildren.end(); -			iter != end_iter && filter.getFilterCount() > 0; -			++iter) +		for (child_list_t::iterator iter = mChildren.begin(), end_iter = mChildren.end(); iter != end_iter; ++iter)  		{ -			if (!filterChildItem((*iter), filter)) +			continue_filtering = filterChildItem((*iter), filter); +            if (!continue_filtering)  			{  				break;  			}  		}  	} -	// if we didn't use all filter iterations -	// that means we filtered all of our descendants -	// so filter ourselves now -	if (filter.getFilterCount() > 0) +	// If we didn't use all the filter time that means we filtered all of our descendants so we can filter ourselves now +    if (continue_filtering)  	{ -		filter.decrementFilterCount(); - +        // This is where filter check on the item done (CHUI-849)  		const bool passed_filter = filter.check(this);  		setPassedFilter(passed_filter, filter_generation, filter.getStringMatchOffset(this), filter.getFilterStringSize()); -		return true; -	} -	else -	{ -		return false; +        continue_filtering = !filter.isTimedOut();  	} +    return continue_filtering;  }  LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() @@ -307,8 +316,8 @@ bool LLInventorySort::operator()(const LLFolderViewModelItemInventory* const& a,  	}  } -LLFolderViewModelItemInventory::LLFolderViewModelItemInventory( class LLFolderViewModelInventory& root_view_model )  -	:	LLFolderViewModelItemCommon(root_view_model), -	mPrevPassedAllFilters(false) +LLFolderViewModelItemInventory::LLFolderViewModelItemInventory( class LLFolderViewModelInventory& root_view_model ) : +    LLFolderViewModelItemCommon(root_view_model), +    mPrevPassedAllFilters(false)  {  } diff --git a/indra/newview/llfolderviewmodelinventory.h b/indra/newview/llfolderviewmodelinventory.h index 890d03d1c9..9dcfdfa185 100755 --- a/indra/newview/llfolderviewmodelinventory.h +++ b/indra/newview/llfolderviewmodelinventory.h @@ -59,9 +59,8 @@ public:  	virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0;  	virtual LLToolDragAndDrop::ESource getDragSource() const = 0; -  protected: -	bool								mPrevPassedAllFilters; +    bool mPrevPassedAllFilters;  };  class LLInventorySort diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp index a0f2918bd7..302d21c2e4 100755 --- a/indra/newview/llgroupactions.cpp +++ b/indra/newview/llgroupactions.cpp @@ -116,6 +116,80 @@ public:  };  LLGroupHandler gGroupHandler; +// This object represents a pending request for specified group member information +// which is needed to check whether avatar can leave group +class LLFetchGroupMemberData : public LLGroupMgrObserver +{ +public: +	LLFetchGroupMemberData(const LLUUID& group_id) :  +		mGroupId(group_id), +		mRequestProcessed(false), +		LLGroupMgrObserver(group_id)  +	{ +		llinfos << "Sending new group member request for group_id: "<< group_id << llendl; +		LLGroupMgr* mgr = LLGroupMgr::getInstance(); +		// register ourselves as an observer +		mgr->addObserver(this); +		// send a request +		mgr->sendGroupPropertiesRequest(group_id); +		mgr->sendCapGroupMembersRequest(group_id); +	} + +	~LLFetchGroupMemberData() +	{ +		if (!mRequestProcessed) +		{ +			// Request is pending +			llwarns << "Destroying pending group member request for group_id: " +				<< mGroupId << llendl; +		} +		// Remove ourselves as an observer +		LLGroupMgr::getInstance()->removeObserver(this); +	} + +	void changed(LLGroupChange gc) +	{ +		if (gc == GC_MEMBER_DATA && !mRequestProcessed) +		{ +			LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupId); +			if (!gdatap) +			{ +				llwarns << "LLGroupMgr::getInstance()->getGroupData() was NULL" << llendl; +			}  +			else if (!gdatap->isMemberDataComplete()) +			{ +				llwarns << "LLGroupMgr::getInstance()->getGroupData()->isMemberDataComplete() was FALSE" << llendl; +			} +			else +			{ +				processGroupData(); +				mRequestProcessed = true; +			} +		} +	} + +	LLUUID getGroupId() { return mGroupId; } +	virtual void processGroupData() = 0; +protected: +	LLUUID mGroupId; +private: +	bool mRequestProcessed; +}; + +class LLFetchLeaveGroupData: public LLFetchGroupMemberData +{ +public: +	 LLFetchLeaveGroupData(const LLUUID& group_id) +		 : LLFetchGroupMemberData(group_id) +	 {} +	 void processGroupData() +	 { +		 LLGroupActions::processLeaveGroupDataResponse(mGroupId); +	 } +}; + +LLFetchLeaveGroupData* gFetchLeaveGroupData = NULL; +  // static  void LLGroupActions::search()  { @@ -208,23 +282,52 @@ bool LLGroupActions::onJoinGroup(const LLSD& notification, const LLSD& response)  void LLGroupActions::leave(const LLUUID& group_id)  {  	if (group_id.isNull()) +	{  		return; +	} -	S32 count = gAgent.mGroups.count(); -	S32 i; -	for (i = 0; i < count; ++i) +	LLGroupData group_data; +	if (gAgent.getGroupData(group_id, group_data))  	{ -		if(gAgent.mGroups.get(i).mID == group_id) -			break; +		LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_id); +		if (!gdatap || !gdatap->isMemberDataComplete()) +		{ +			if (gFetchLeaveGroupData != NULL) +			{ +				delete gFetchLeaveGroupData; +				gFetchLeaveGroupData = NULL; +			} +			gFetchLeaveGroupData = new LLFetchLeaveGroupData(group_id); +		} +		else +		{ +			processLeaveGroupDataResponse(group_id); +		}  	} -	if (i < count) +} + +//static +void LLGroupActions::processLeaveGroupDataResponse(const LLUUID group_id) +{ +	LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_id); +	LLUUID agent_id = gAgent.getID(); +	LLGroupMgrGroupData::member_list_t::iterator mit = gdatap->mMembers.find(agent_id); +	//get the member data for the group +	if ( mit != gdatap->mMembers.end() )  	{ -		LLSD args; -		args["GROUP"] = gAgent.mGroups.get(i).mName; -		LLSD payload; -		payload["group_id"] = group_id; -		LLNotificationsUtil::add("GroupLeaveConfirmMember", args, payload, onLeaveGroup); +		LLGroupMemberData* member_data = (*mit).second; + +		if ( member_data && member_data->isOwner() && gdatap->mMemberCount == 1) +		{ +			LLNotificationsUtil::add("OwnerCannotLeaveGroup"); +			return; +		}  	} +	LLSD args; +	args["GROUP"] = gdatap->mName; +	LLSD payload; +	payload["group_id"] = group_id; +	LLNotificationsUtil::add("GroupLeaveConfirmMember", args, payload, onLeaveGroup);  }  // static diff --git a/indra/newview/llgroupactions.h b/indra/newview/llgroupactions.h index 3f9852f194..afc4686dd7 100755 --- a/indra/newview/llgroupactions.h +++ b/indra/newview/llgroupactions.h @@ -114,6 +114,14 @@ public:  private:  	static bool onJoinGroup(const LLSD& notification, const LLSD& response);  	static bool onLeaveGroup(const LLSD& notification, const LLSD& response); +	 +	/** +	 * This function is called by LLFetchLeaveGroupData upon receiving a response to a group  +	 * members data request. +	 */ +	static void processLeaveGroupDataResponse(const LLUUID group_id); + +	friend class LLFetchLeaveGroupData;  };  #endif // LL_LLGROUPACTIONS_H diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 3b72ad3cd9..9e23755d73 100755 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -103,6 +103,7 @@ BOOL LLSessionTimeoutTimer::tick()  } +void notify_of_message(const LLSD& msg, bool is_dnd_msg);  void process_dnd_im(const LLSD& notification)  { @@ -129,15 +130,9 @@ void process_dnd_im(const LLSD& notification)              fromID,               false,               false); //will need slight refactor to retrieve whether offline message or not (assume online for now) +	} -		LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); -		 -		if (im_box) -		{ -			im_box->flashConversationItemWidget(sessionID, true); -		} - -    } +	notify_of_message(data, true);  } @@ -158,75 +153,106 @@ static void on_avatar_name_cache_toast(const LLUUID& agent_id,  	LLNotificationsUtil::add("IMToast", args, args, boost::bind(&LLFloaterIMContainer::showConversation, LLFloaterIMContainer::getInstance(), msg["session_id"].asUUID()));  } -void on_new_message(const LLSD& msg) +void notify_of_message(const LLSD& msg, bool is_dnd_msg)  { -    std::string user_preferences; -    LLUUID participant_id = msg["from_id"].asUUID(); -    LLUUID session_id = msg["session_id"].asUUID(); -    LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); - -    // do not show notification which goes from agent -    if (gAgent.getID() == participant_id) -    { -        return; -    } +	std::string user_preferences; +	LLUUID participant_id = msg[is_dnd_msg ? "FROM_ID" : "from_id"].asUUID(); +	LLUUID session_id = msg[is_dnd_msg ? "SESSION_ID" : "session_id"].asUUID(); +	LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); -    // determine state of conversations floater -    enum {CLOSED, NOT_ON_TOP, ON_TOP, ON_TOP_AND_ITEM_IS_SELECTED} conversations_floater_status; +	// do not show notification which goes from agent +	if (gAgent.getID() == participant_id) +	{ +		return; +	} +	// determine state of conversations floater +	enum {CLOSED, NOT_ON_TOP, ON_TOP, ON_TOP_AND_ITEM_IS_SELECTED} conversations_floater_status; -    LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); +	LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");  	LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); - +	bool store_dnd_message = false; // flag storage of a dnd message +	bool is_session_focused = session_floater->isTornOff() && session_floater->hasFocus();  	if (!LLFloater::isVisible(im_box) || im_box->isMinimized())  	{  		conversations_floater_status = CLOSED;  	}  	else if (!im_box->hasFocus() && -			    !(session_floater && LLFloater::isVisible(session_floater) -	            && !session_floater->isMinimized() && session_floater->hasFocus())) +		!(session_floater && LLFloater::isVisible(session_floater) +		&& !session_floater->isMinimized() && session_floater->hasFocus()))  	{  		conversations_floater_status = NOT_ON_TOP;  	}  	else if (im_box->getSelectedSession() != session_id)  	{  		conversations_floater_status = ON_TOP; -    } +	}  	else  	{  		conversations_floater_status = ON_TOP_AND_ITEM_IS_SELECTED;  	} -    //  determine user prefs for this session -    if (session_id.isNull()) -    { -    	user_preferences = gSavedSettings.getString("NotificationNearbyChatOptions"); -    } -    else if(session->isP2PSessionType()) -    { -        if (LLAvatarTracker::instance().isBuddy(participant_id)) -        { -        	user_preferences = gSavedSettings.getString("NotificationFriendIMOptions"); -        } -        else -        { -        	user_preferences = gSavedSettings.getString("NotificationNonFriendIMOptions"); -        } -    } -    else if(session->isAdHocSessionType()) -    { -    	user_preferences = gSavedSettings.getString("NotificationConferenceIMOptions"); -    } -    else if(session->isGroupSessionType()) -    { -    	user_preferences = gSavedSettings.getString("NotificationGroupChatOptions"); -    } +	//  determine user prefs for this session +	if (session_id.isNull()) +	{ +		if (msg["source_type"].asInteger() == CHAT_SOURCE_OBJECT) +		{ +			user_preferences = gSavedSettings.getString("NotificationObjectIMOptions"); +			if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundObjectIM") == TRUE)) +			{ +				make_ui_sound("UISndNewIncomingIMSession"); +			} +		} +		else +		{ +			user_preferences = gSavedSettings.getString("NotificationNearbyChatOptions"); +			if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundNearbyChatIM") == TRUE)) +			{ +				make_ui_sound("UISndNewIncomingIMSession"); +			} +		} +	} +	else if(session->isP2PSessionType()) +	{ +		if (LLAvatarTracker::instance().isBuddy(participant_id)) +		{ +			user_preferences = gSavedSettings.getString("NotificationFriendIMOptions"); +			if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundFriendIM") == TRUE)) +			{ +				make_ui_sound("UISndNewIncomingIMSession"); +			} +		} +		else +		{ +			user_preferences = gSavedSettings.getString("NotificationNonFriendIMOptions"); +			if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundNonFriendIM") == TRUE)) +			{ +				make_ui_sound("UISndNewIncomingIMSession"); +			} +		} +	} +	else if(session->isAdHocSessionType()) +	{ +		user_preferences = gSavedSettings.getString("NotificationConferenceIMOptions"); +		if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundConferenceIM") == TRUE)) +		{ +			make_ui_sound("UISndNewIncomingIMSession"); +		} +	} +	else if(session->isGroupSessionType()) +	{ +		user_preferences = gSavedSettings.getString("NotificationGroupChatOptions"); +		if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundGroupChatIM") == TRUE)) +		{ +			make_ui_sound("UISndNewIncomingIMSession"); +		} +	} -    // actions: +	// actions:      // 0. nothing - exit -    if (("none" == user_preferences || +    if (("noaction" == user_preferences ||      		ON_TOP_AND_ITEM_IS_SELECTED == conversations_floater_status)      	&& session_floater->isMessagePaneExpanded())      { @@ -261,57 +287,103 @@ void on_new_message(const LLSD& msg)  				}  			}  		} -        else -        { -            //If in DND mode, allow notification to be stored so upon DND exit -            //useMostItrusiveIMNotification will be called to notify user a message exists -            if(session_id.notNull() -               && participant_id.notNull() -		       && !session_floater->isShown()) -            { -                LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); -	        } -        } -    } +		else +		{ +			store_dnd_message = true; +		} -    // 2. Flash line item -    if ("openconversations" == user_preferences -    		|| ON_TOP == conversations_floater_status -    		|| ("toast" == user_preferences && ON_TOP != conversations_floater_status) -    		|| ("flash" == user_preferences && CLOSED == conversations_floater_status)) -    { -    	if(!LLMuteList::getInstance()->isMuted(participant_id)) -    	{ -    		im_box->flashConversationItemWidget(session_id, true); -    	} -    } +	} -    // 3. Flash FUI button -    if (("toast" == user_preferences || "flash" == user_preferences) && -    		(CLOSED == conversations_floater_status -    		    || NOT_ON_TOP == conversations_floater_status)) -    { -    	if(!LLMuteList::getInstance()->isMuted(participant_id) -            && !gAgent.isDoNotDisturb()) -    	{ -    		gToolBarView->flashCommand(LLCommandId("chat"), true); -    	} -    } +	// 2. Flash line item +	if ("openconversations" == user_preferences +		|| ON_TOP == conversations_floater_status +		|| ("toast" == user_preferences && ON_TOP != conversations_floater_status) +		|| ("flash" == user_preferences && (CLOSED == conversations_floater_status +				 	 	 	 	 	 	|| NOT_ON_TOP == conversations_floater_status)) +		|| is_dnd_msg) +	{ +		if(!LLMuteList::getInstance()->isMuted(participant_id)) +		{ +			if(gAgent.isDoNotDisturb()) +			{ +				store_dnd_message = true; +			} +			else +			{ +				if (is_dnd_msg && (ON_TOP == conversations_floater_status ||  +									NOT_ON_TOP == conversations_floater_status ||  +									CLOSED == conversations_floater_status)) +				{ +					im_box->highlightConversationItemWidget(session_id, true); +				} +				else +				{ +					im_box->flashConversationItemWidget(session_id, true); +				} +			} +		} +	} -    // 4. Toast -    if ((("toast" == user_preferences) && -    		(CLOSED == conversations_floater_status -    		    || NOT_ON_TOP == conversations_floater_status)) -    		    || !session_floater->isMessagePaneExpanded()) +	// 3. Flash FUI button +	if (("toast" == user_preferences || "flash" == user_preferences) && +		(CLOSED == conversations_floater_status +		|| NOT_ON_TOP == conversations_floater_status) +		&& !is_session_focused +		&& !is_dnd_msg) //prevent flashing FUI button because the conversation floater will have already opened +	{ +		if(!LLMuteList::getInstance()->isMuted(participant_id)) +		{ +			if(!gAgent.isDoNotDisturb()) +			{ +				gToolBarView->flashCommand(LLCommandId("chat"), true, im_box->isMinimized()); +			} +			else +			{ +				store_dnd_message = true; +			} +		} +	} -    { -        //Show IM toasts (upper right toasts) -        // Skip toasting for system messages and for nearby chat -        if(session_id.notNull() && participant_id.notNull()) -        { -            LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); -        } -    } +	// 4. Toast +	if ((("toast" == user_preferences) && +		(ON_TOP_AND_ITEM_IS_SELECTED != conversations_floater_status) && +		(!session_floater->isTornOff() || !LLFloater::isVisible(session_floater))) +		|| !session_floater->isMessagePaneExpanded()) + +	{ +		//Show IM toasts (upper right toasts) +		// Skip toasting for system messages and for nearby chat +		if(session_id.notNull() && participant_id.notNull()) +		{ +			if(!is_dnd_msg) +			{ +				if(gAgent.isDoNotDisturb()) +				{ +					store_dnd_message = true; +				} +				else +				{ +					LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); +				} +			} +		} +	} +	if (store_dnd_message) +	{ +		// If in DND mode, allow notification to be stored so upon DND exit  +		// the user will be notified with some limitations (see 'is_dnd_msg' flag checks) +		if(session_id.notNull() +			&& participant_id.notNull() +			&& !session_floater->isShown()) +		{ +			LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); +		} +	} +} + +void on_new_message(const LLSD& msg) +{ +	notify_of_message(msg, false);  }  LLIMModel::LLIMModel()  @@ -2597,6 +2669,13 @@ void LLIMMgr::addMessage(  		fixed_session_name = session_name;  		name_is_setted = true;  	} +	bool skip_message = false; +	if (gSavedSettings.getBOOL("VoiceCallsFriendsOnly")) +	{ +		// Evaluate if we need to skip this message when that setting is true (default is false) +		skip_message = (LLAvatarTracker::instance().getBuddyInfo(other_participant_id) == NULL);	// Skip non friends... +		skip_message &= !(other_participant_id == gAgentID);	// You are your best friend... Don't skip yourself +	}  	bool new_session = !hasSession(new_session_id);  	if (new_session) @@ -2608,6 +2687,12 @@ void LLIMMgr::addMessage(  		}  		LLIMModel::getInstance()->newSession(new_session_id, fixed_session_name, dialog, other_participant_id, false, is_offline_msg); +		LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(new_session_id); +		skip_message &= !session->isGroupSessionType();			// Do not skip group chats... +		if(skip_message) +		{ +			gIMMgr->leaveSession(new_session_id); +		}  		// When we get a new IM, and if you are a god, display a bit  		// of information about the source. This is to help liaisons  		// when answering questions. @@ -2648,23 +2733,13 @@ void LLIMMgr::addMessage(          }  	} -	bool skip_message = false; -	if (gSavedSettings.getBOOL("VoiceCallsFriendsOnly")) -	{ -		// Evaluate if we need to skip this message when that setting is true (default is false) -		LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(new_session_id); -		skip_message = (LLAvatarTracker::instance().getBuddyInfo(other_participant_id) == NULL);	// Skip non friends... -		skip_message &= !session->isGroupSessionType();			// Do not skip group chats... -		skip_message &= !(other_participant_id == gAgentID);	// You are your best friend... Don't skip yourself -	} -  	if (!LLMuteList::getInstance()->isMuted(other_participant_id, LLMute::flagTextChat) && !skip_message)  	{  		LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, msg);  	}  	// Open conversation floater if offline messages are present -	if (is_offline_msg) +	if (is_offline_msg && !skip_message)      {          LLFloaterReg::showInstance("im_container");  	    LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container")-> @@ -2971,10 +3046,9 @@ void LLIMMgr::inviteToSession(  	{  		bool isRejectGroupCall = (gSavedSettings.getBOOL("VoiceCallsRejectGroup") && (notify_box_type == "VoiceInviteGroup"));  		bool isRejectNonFriendCall = (gSavedSettings.getBOOL("VoiceCallsFriendsOnly") && (LLAvatarTracker::instance().getBuddyInfo(caller_id) == NULL)); -		bool isRejectDoNotDisturb = (gAgent.isDoNotDisturb() && !hasSession(session_id)); -		if	(isRejectGroupCall || isRejectNonFriendCall || isRejectDoNotDisturb) +		if	(isRejectGroupCall || isRejectNonFriendCall || gAgent.isDoNotDisturb())  		{ -			if (isRejectDoNotDisturb && !isRejectGroupCall && !isRejectNonFriendCall) +			if (gAgent.isDoNotDisturb() && !isRejectGroupCall && !isRejectNonFriendCall)  			{  				LLSD args;  				addSystemMessage(session_id, "you_auto_rejected_call", args); diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 92f2d33073..3c6974cf6d 100755 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -70,11 +70,8 @@ LLInventoryFilter::LLInventoryFilter(const Params& p)  	mFilterSubString(p.substring),  	mCurrentGeneration(0),  	mFirstRequiredGeneration(0), -	mFirstSuccessGeneration(0), -	mFilterCount(0) +	mFirstSuccessGeneration(0)  { -	mNextFilterGeneration = mCurrentGeneration + 1; -  	// copy mFilterOps into mDefaultFilterOps  	markDefault();  } @@ -92,9 +89,7 @@ bool LLInventoryFilter::check(const LLFolderViewModelItem* item)  		return passed_clipboard;  	} -	std::string::size_type string_offset = mFilterSubString.size() ? listener->getSearchableName().find(mFilterSubString) : std::string::npos; - -	BOOL passed = (mFilterSubString.size() == 0 || string_offset != std::string::npos); +	bool passed = (mFilterSubString.size() ? listener->getSearchableName().find(mFilterSubString) != std::string::npos : true);  	passed = passed && checkAgainstFilterType(listener);  	passed = passed && checkAgainstPermissions(listener);  	passed = passed && checkAgainstFilterLinks(listener); @@ -105,17 +100,12 @@ bool LLInventoryFilter::check(const LLFolderViewModelItem* item)  bool LLInventoryFilter::check(const LLInventoryItem* item)  { -	std::string::size_type string_offset = mFilterSubString.size() ? item->getName().find(mFilterSubString) : std::string::npos; - +	const bool passed_string = (mFilterSubString.size() ? item->getName().find(mFilterSubString) != std::string::npos : true);  	const bool passed_filtertype = checkAgainstFilterType(item);  	const bool passed_permissions = checkAgainstPermissions(item); -	const BOOL passed_clipboard = checkAgainstClipboard(item->getUUID()); -	const bool passed = (passed_filtertype  -		&& passed_permissions -		&& passed_clipboard  -		&&	(mFilterSubString.size() == 0 || string_offset != std::string::npos)); +	const bool passed_clipboard = checkAgainstClipboard(item->getUUID()); -	return passed; +	return passed_filtertype && passed_permissions && passed_clipboard && passed_string;  }  bool LLInventoryFilter::checkFolder(const LLFolderViewModelItem* item) const @@ -439,7 +429,7 @@ void LLInventoryFilter::updateFilterTypes(U64 types, U64& current_types)  		current_types = types;  		if (more_bits_set && fewer_bits_set)  		{ -			// neither less or more restrive, both simultaneously +			// neither less or more restrictive, both simultaneously  			// so we need to filter from scratch  			setModified(FILTER_RESTART);  		} @@ -714,7 +704,7 @@ void LLInventoryFilter::resetDefault()  void LLInventoryFilter::setModified(EFilterModified behavior)  {  	mFilterText.clear(); -	mCurrentGeneration = mNextFilterGeneration++; +	mCurrentGeneration++;  	if (mFilterModified == FILTER_NONE)  	{ @@ -1021,21 +1011,19 @@ LLInventoryFilter::EFolderShow LLInventoryFilter::getShowFolderState() const  	return mFilterOps.mShowFolderState;   } -void LLInventoryFilter::setFilterCount(S32 count)  -{  -	mFilterCount = count;  -} -S32 LLInventoryFilter::getFilterCount() const +bool LLInventoryFilter::isTimedOut()  { -	return mFilterCount; +	return mFilterTime.hasExpired();  } -void LLInventoryFilter::decrementFilterCount()  -{  -	mFilterCount--;  +void LLInventoryFilter::resetTime(S32 timeout) +{ +	mFilterTime.reset(); +    F32 time_in_sec = (F32)(timeout)/1000.0; +	mFilterTime.setTimerExpirySec(time_in_sec);  } -S32 LLInventoryFilter::getCurrentGeneration() const  +S32 LLInventoryFilter::getCurrentGeneration() const  {   	return mCurrentGeneration;  } diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h index 4912b5ca91..ce516af0b9 100755 --- a/indra/newview/llinventoryfilter.h +++ b/indra/newview/llinventoryfilter.h @@ -215,12 +215,11 @@ public:  	void 				setModified(EFilterModified behavior = FILTER_RESTART);  	// +-------------------------------------------------------------------+ -	// + Count +	// + Time  	// +-------------------------------------------------------------------+ -	void 				setFilterCount(S32 count); -	S32 				getFilterCount() const; -	void 				decrementFilterCount(); - +	void 				resetTime(S32 timeout); +    bool                isTimedOut(); +      	// +-------------------------------------------------------------------+  	// + Default  	// +-------------------------------------------------------------------+ @@ -262,13 +261,15 @@ private:  	const std::string		mName;  	S32						mCurrentGeneration; +    // The following makes checking for pass/no pass possible even if the item is not checked against the current generation +    // Any item that *did not pass* the "required generation" will *not pass* the current one +    // Any item that *passes* the "success generation" will *pass* the current one  	S32						mFirstRequiredGeneration;  	S32						mFirstSuccessGeneration; -	S32						mNextFilterGeneration; -	S32						mFilterCount;  	EFilterModified 		mFilterModified; - +	LLTimer                 mFilterTime; +      	std::string 			mFilterText;  	std::string 			mEmptyLookupMessage;  }; diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index cf1fd4c0d0..e5b9e11d48 100755 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -192,7 +192,7 @@ LLFolderView * LLInventoryPanel::createFolderRoot(LLUUID root_id )      p.show_item_link_overlays = mShowItemLinkOverlays;      p.root = NULL;      p.options_menu = "menu_inventory.xml"; -	 +      return LLUICtrlFactory::create<LLFolderView>(p);  } @@ -396,6 +396,7 @@ LLInventoryFilter::EFolderShow LLInventoryPanel::getShowFolderState()  	return getFilter().getShowFolderState();  } +// Called when something changed in the global model (new item, item coming through the wire, rename, move, etc...) (CHUI-849)  void LLInventoryPanel::modelChanged(U32 mask)  {  	static LLFastTimer::DeclareTimer FTM_REFRESH("Inventory Refresh"); diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 2d7454b636..90b169ecd3 100755 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -25,7 +25,7 @@   */  #include "llviewerprecompiledheaders.h" - +#include "llfloaterconversationpreview.h"  #include "llagent.h"  #include "llagentui.h"  #include "llavatarnamecache.h" @@ -206,6 +206,7 @@ private:  };  LLLogChat::save_history_signal_t * LLLogChat::sSaveHistorySignal = NULL; +LLLoadHistoryThread::load_end_signal_t * LLLoadHistoryThread::mLoadEndSignal = NULL;  //static  std::string LLLogChat::makeLogFileName(std::string filename) @@ -336,75 +337,83 @@ void LLLogChat::saveHistory(const std::string& filename,  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_WARNS("LLLogChat::loadChatHistory") << "Session name is Empty!" << LL_ENDL; +					return ; +				} -	LLFILE* fptr = LLFile::fopen(makeLogFileName(file_name), "r");/*Flawfinder: ignore*/ -	if (!fptr) -	{ -		fptr = LLFile::fopen(oldLogFileName(file_name), "r");/*Flawfinder: ignore*/ -		if (!fptr) -		{ -			return;						//No previous conversation with this name. -		} -	} -  -	char buffer[LOG_RECALL_SIZE];		/*Flawfinder: ignore*/ -	char *bptr; -	S32 len; -	bool firstline = TRUE; +				bool load_all_history = load_params.has("load_all_history") ? load_params["load_all_history"].asBoolean() : false; -	if (load_all_history || fseek(fptr, (LOG_RECALL_SIZE - 1) * -1  , SEEK_END)) -	{	//We need to load the whole historyFile or it's smaller than recall size, so get it all. -		firstline = FALSE; -		if (fseek(fptr, 0, SEEK_SET)) -		{ -			fclose(fptr); -			return; -		} -	} +				LLFILE* fptr = LLFile::fopen(LLLogChat::makeLogFileName(file_name), "r");/*Flawfinder: ignore*/ +				if (!fptr) +				{ +					fptr = LLFile::fopen(LLLogChat::oldLogFileName(file_name), "r");/*Flawfinder: ignore*/ +					if (!fptr) +					{ +						return;						//No previous conversation with this name. +					} +				} -	while (fgets(buffer, LOG_RECALL_SIZE, fptr)  && !feof(fptr))  -	{ -		len = strlen(buffer) - 1;		/*Flawfinder: ignore*/ -		for (bptr = (buffer + len); (*bptr == '\n' || *bptr == '\r') && bptr>buffer; bptr--)	*bptr='\0'; -		 -		if (firstline) -		{ -			firstline = FALSE; -			continue; -		} +				char buffer[LOG_RECALL_SIZE];		/*Flawfinder: ignore*/ +				char *bptr; +				S32 len; +				bool firstline = TRUE; + +				if (load_all_history || fseek(fptr, (LOG_RECALL_SIZE - 1) * -1  , SEEK_END)) +				{	//We need to load the whole historyFile or it's smaller than recall size, so get it all. +					firstline = FALSE; +					if (fseek(fptr, 0, SEEK_SET)) +					{ +						fclose(fptr); +						return; +					} +				} +			while (fgets(buffer, LOG_RECALL_SIZE, fptr)  && !feof(fptr)) +				{ +					len = strlen(buffer) - 1;		/*Flawfinder: ignore*/ +					for (bptr = (buffer + len); (*bptr == '\n' || *bptr == '\r') && bptr>buffer; bptr--)	*bptr='\0'; + +					if (firstline) +					{ +						firstline = FALSE; +						continue; +					} + +					std::string line(buffer); + +					//updated 1.23 plain text log format requires a space added before subsequent lines in a multilined message +					if (' ' == line[0]) +					{ +						line.erase(0, MULTI_LINE_PREFIX.length()); +						append_to_last_message(messages, '\n' + line); +					} +					else if (0 == len && ('\n' == line[0] || '\r' == line[0])) +					{ +						//to support old format's multilined messages with new lines used to divide paragraphs +						append_to_last_message(messages, line); +					} +					else +					{ +						LLSD item; +						if (!LLChatLogParser::parse(line, item, load_params)) +						{ +							item[LL_IM_TEXT] = line; +						} +						messages.push_back(item); +					} +				} +				fclose(fptr); -		std::string line(buffer); -		//updated 1.23 plaint text log format requires a space added before subsequent lines in a multilined message -		if (' ' == line[0]) -		{ -			line.erase(0, MULTI_LINE_PREFIX.length()); -			append_to_last_message(messages, '\n' + line); -		} -		else if (0 == len && ('\n' == line[0] || '\r' == line[0])) -		{ -			//to support old format's multilined messages with new lines used to divide paragraphs -			append_to_last_message(messages, line); -		} -		else -		{ -			LLSD item; -			if (!LLChatLogParser::parse(line, item, load_params)) -			{ -				item[LL_IM_TEXT] = line; -			} -			messages.push_back(item); -		} -	} -	fclose(fptr);  } +void LLLogChat::startChatHistoryThread(const std::string& file_name, const LLSD& load_params) +{ + +	LLLoadHistoryThread* mThread = new LLLoadHistoryThread(); +	mThread->start(); +	mThread->setHistoryParams(file_name, load_params); +}  // static  std::string LLLogChat::oldLogFileName(std::string filename)  { @@ -461,6 +470,13 @@ void LLLogChat::findTranscriptFiles(std::string pattern, std::vector<std::string  		LLFILE * filep = LLFile::fopen(fullname, "rb");  		if (NULL != filep)  		{ +			if(makeLogFileName("chat")== fullname) +			{ +				//Add Nearby chat history to the list of transcriptions +				list_of_transcriptions.push_back(gDirUtilp->add(dirname, filename)); +				LLFile::close(filep); +				return; +			}  			char buffer[LOG_RECALL_SIZE];  			fseek(filep, 0, SEEK_END);			// seek to end of file @@ -631,7 +647,7 @@ void LLLogChat::deleteTranscripts()  }  // static -bool LLLogChat::isTranscriptExist(const LLUUID& avatar_id) +bool LLLogChat::isTranscriptExist(const LLUUID& avatar_id, bool is_group)  {  	std::vector<std::string> list_of_transcriptions;  	LLLogChat::getListOfTranscriptFiles(list_of_transcriptions); @@ -641,20 +657,53 @@ bool LLLogChat::isTranscriptExist(const LLUUID& avatar_id)  		LLAvatarName avatar_name;  		LLAvatarNameCache::get(avatar_id, &avatar_name);  		std::string avatar_user_name = avatar_name.getAccountName(); -		std::replace(avatar_user_name.begin(), avatar_user_name.end(), '.', '_'); - -		BOOST_FOREACH(std::string& transcript_file_name, list_of_transcriptions) +		if(!is_group)  		{ -			if (std::string::npos != transcript_file_name.find(avatar_user_name)) +			std::replace(avatar_user_name.begin(), avatar_user_name.end(), '.', '_'); +			BOOST_FOREACH(std::string& transcript_file_name, list_of_transcriptions)  			{ -				return true; +				if (std::string::npos != transcript_file_name.find(avatar_user_name)) +				{ +					return true; +				}  			}  		} +		else +		{ +			std::string file_name; +			gCacheName->getGroupName(avatar_id, file_name); +			file_name = makeLogFileName(file_name); +			BOOST_FOREACH(std::string& transcript_file_name, list_of_transcriptions) +			{ +				if (transcript_file_name == file_name) +				{ +					return true; +				} +			} +		} +  	}  	return false;  } +bool LLLogChat::isNearbyTranscriptExist() +{ +	std::vector<std::string> list_of_transcriptions; +	LLLogChat::getListOfTranscriptFiles(list_of_transcriptions); + +	std::string file_name; +	file_name = makeLogFileName("chat"); +	BOOST_FOREACH(std::string& transcript_file_name, list_of_transcriptions) +	{ +	   	if (transcript_file_name == file_name) +	   	{ +			return true; +		 } +	} +	return false; +} +  //*TODO mark object's names in a special way so that they will be distinguishable form avatar name   //which are more strict by its nature (only firstname and secondname)  //Example, an object's name can be written like "Object <actual_object's_name>" @@ -795,3 +844,116 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params  	im[LL_IM_TEXT] = name_and_text[IDX_TEXT];  	return true;  //parsed name and message text, maybe have a timestamp too  } + + + +	LLLoadHistoryThread::LLLoadHistoryThread() : LLThread("load chat history") + 	{ +		mNewLoad = false; +	} + +	void LLLoadHistoryThread::run() +	{ +		while (!LLApp::isQuitting()) +			{ +			    if(mNewLoad) +				{ +					loadHistory(mFileName,mMessages,mLoadParams); +					shutdown(); +				} +			} +	} +	void LLLoadHistoryThread::setHistoryParams(const std::string& file_name, const LLSD& load_params) +	{ +		mFileName = file_name; +		mLoadParams = load_params; +		mNewLoad = true; +	} +	void LLLoadHistoryThread::loadHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params) +	{ + +		if (file_name.empty()) +			{ +			LL_WARNS("LLLogChat::loadHistory") << "Session name is Empty!" << LL_ENDL; +				return ; +			} + +			bool load_all_history = load_params.has("load_all_history") ? load_params["load_all_history"].asBoolean() : false; + +			LLFILE* fptr = LLFile::fopen(LLLogChat::makeLogFileName(file_name), "r");/*Flawfinder: ignore*/ +			if (!fptr) +			{ +				fptr = LLFile::fopen(LLLogChat::oldLogFileName(file_name), "r");/*Flawfinder: ignore*/ +				if (!fptr) +				{ +					mNewLoad = false; +					(*mLoadEndSignal)(messages, file_name); +					return;						//No previous conversation with this name. +				} +			} + +			char buffer[LOG_RECALL_SIZE];		/*Flawfinder: ignore*/ +			char *bptr; +			S32 len; +			bool firstline = TRUE; + +			if (load_all_history || fseek(fptr, (LOG_RECALL_SIZE - 1) * -1  , SEEK_END)) +			{	//We need to load the whole historyFile or it's smaller than recall size, so get it all. +				firstline = FALSE; +				if (fseek(fptr, 0, SEEK_SET)) +				{ +					fclose(fptr); +					mNewLoad = false; +					(*mLoadEndSignal)(messages, file_name); +					return; +				} +			} +		while (fgets(buffer, LOG_RECALL_SIZE, fptr)  && !feof(fptr)) +			{ +				len = strlen(buffer) - 1;		/*Flawfinder: ignore*/ +				for (bptr = (buffer + len); (*bptr == '\n' || *bptr == '\r') && bptr>buffer; bptr--)	*bptr='\0'; + +				if (firstline) +				{ +					firstline = FALSE; +					continue; +				} + +				std::string line(buffer); + +				//updated 1.23 plaint text log format requires a space added before subsequent lines in a multilined message +				if (' ' == line[0]) +				{ +					line.erase(0, MULTI_LINE_PREFIX.length()); +					append_to_last_message(messages, '\n' + line); +				} +				else if (0 == len && ('\n' == line[0] || '\r' == line[0])) +				{ +					//to support old format's multilined messages with new lines used to divide paragraphs +					append_to_last_message(messages, line); +				} +				else +				{ +					LLSD item; +					if (!LLChatLogParser::parse(line, item, load_params)) +					{ +						item[LL_IM_TEXT] = line; +					} +					messages.push_back(item); +				} +			} +			fclose(fptr); +			mNewLoad = false; +			(*mLoadEndSignal)(messages, file_name); +	} + +	//static +	boost::signals2::connection LLLoadHistoryThread::setLoadEndSignal(const load_end_signal_t::slot_type& cb) +	{ +		if (NULL == mLoadEndSignal) +		{ +			mLoadEndSignal = new load_end_signal_t(); +		} + +		return mLoadEndSignal->connect(cb); +	} diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h index e819f00dd9..acee99afa2 100755 --- a/indra/newview/lllogchat.h +++ b/indra/newview/lllogchat.h @@ -28,6 +28,24 @@  #define LL_LLLOGCHAT_H  class LLChat; +class LLLoadHistoryThread : public LLThread +{ +private: +	std::string mFileName; +	std::list<LLSD> mMessages; +	LLSD mLoadParams; +	bool mNewLoad; +public: +	LLLoadHistoryThread(); + +	void setHistoryParams(const std::string& file_name, const LLSD& load_params); +	virtual void loadHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params); +    virtual void run(); + +   typedef boost::signals2::signal<void (std::list<LLSD>& messages,const std::string& file_name)> load_end_signal_t; +   static load_end_signal_t * mLoadEndSignal; +   static boost::signals2::connection setLoadEndSignal(const load_end_signal_t::slot_type& cb); +};  class LLLogChat  { @@ -39,6 +57,7 @@ public:  		LOG_LLSD,  		LOG_END  	}; +  	static std::string timestamp(bool withdate = false);  	static std::string makeLogFileName(std::string(filename));  	/** @@ -54,6 +73,7 @@ public:  	static void getListOfTranscriptBackupFiles(std::vector<std::string>& list_of_transcriptions);  	static void loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params = LLSD()); +	static void startChatHistoryThread(const std::string& file_name, const LLSD& load_params);  	typedef boost::signals2::signal<void ()> save_history_signal_t;  	static boost::signals2::connection setSaveHistorySignal(const save_history_signal_t::slot_type& cb); @@ -67,7 +87,8 @@ public:  		std::vector<std::string>& listOfFilesToMove);  	static void deleteTranscripts(); -	static bool isTranscriptExist(const LLUUID& avatar_id); +	static bool isTranscriptExist(const LLUUID& avatar_id, bool is_group=false); +	static bool isNearbyTranscriptExist();  private:  	static std::string cleanFileName(std::string filename); @@ -126,6 +147,7 @@ protected:  	virtual ~LLChatLogParser() {};  }; +  // LLSD map lookup constants  extern const std::string LL_IM_TIME; //("time");  extern const std::string LL_IM_TEXT; //("message"); diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp index d79f1040bb..4cbdfde868 100755 --- a/indra/newview/llmaniprotate.cpp +++ b/indra/newview/llmaniprotate.cpp @@ -1376,74 +1376,28 @@ LLQuaternion LLManipRotate::dragConstrained( S32 x, S32 y )  		BOOL hit = getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, constraint_axis);  		projected_mouse -= snap_plane_center; -		S32 snap_plane = 0; - -		F32 dot = cam_to_snap_plane * constraint_axis; -		if (llabs(dot) < 0.01f) -		{ -			// looking at ring edge on, project onto view plane and check if mouse is past ring -			getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_to_snap_plane); -			projected_mouse -= snap_plane_center; -			dot = projected_mouse * constraint_axis; -			if (projected_mouse * constraint_axis > 0) -			{ -				snap_plane = 1; -			} -			projected_mouse -= dot * constraint_axis; -		} -		else if (dot > 0.f) -		{ -			// look for mouse position outside and in front of snap circle -			if (hit && projected_mouse.magVec() > SNAP_GUIDE_INNER_RADIUS * mRadiusMeters && projected_mouse * cam_to_snap_plane < 0.f) -			{ -				snap_plane = 1; -			} -		} -		else -		{ -			// look for mouse position inside or in back of snap circle -			if (projected_mouse.magVec() < SNAP_GUIDE_INNER_RADIUS * mRadiusMeters || projected_mouse * cam_to_snap_plane > 0.f || !hit) -			{ -				snap_plane = 1; -			} -		} - -		if (snap_plane == 0) -		{ -			// try other plane -			snap_plane_center = (center - (constraint_axis * mRadiusMeters * 0.5f)); -			if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) -			{ -				cam_to_snap_plane.setVec(1.f, 0.f, 0.f); -			} -			else -			{ -				cam_to_snap_plane = snap_plane_center - gAgentCamera.getCameraPositionAgent(); -				cam_to_snap_plane.normVec(); -			} - -			hit = getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, constraint_axis); -			projected_mouse -= snap_plane_center; - -			dot = cam_to_snap_plane * constraint_axis; +		if (gSavedSettings.getBOOL("SnapEnabled")) { +			S32 snap_plane = 0; +	 +			F32 dot = cam_to_snap_plane * constraint_axis;  			if (llabs(dot) < 0.01f)  			{  				// looking at ring edge on, project onto view plane and check if mouse is past ring  				getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_to_snap_plane);  				projected_mouse -= snap_plane_center;  				dot = projected_mouse * constraint_axis; -				if (projected_mouse * constraint_axis < 0) +				if (projected_mouse * constraint_axis > 0)  				{ -					snap_plane = 2; +					snap_plane = 1;  				}  				projected_mouse -= dot * constraint_axis;  			} -			else if (dot < 0.f) +			else if (dot > 0.f)  			{  				// look for mouse position outside and in front of snap circle  				if (hit && projected_mouse.magVec() > SNAP_GUIDE_INNER_RADIUS * mRadiusMeters && projected_mouse * cam_to_snap_plane < 0.f)  				{ -					snap_plane = 2; +					snap_plane = 1;  				}  			}  			else @@ -1451,78 +1405,136 @@ LLQuaternion LLManipRotate::dragConstrained( S32 x, S32 y )  				// look for mouse position inside or in back of snap circle  				if (projected_mouse.magVec() < SNAP_GUIDE_INNER_RADIUS * mRadiusMeters || projected_mouse * cam_to_snap_plane > 0.f || !hit)  				{ -					snap_plane = 2; +					snap_plane = 1;  				}  			} -		} - -		if (snap_plane > 0) -		{ -			LLVector3 cam_at_axis; -			if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) -			{ -				cam_at_axis.setVec(1.f, 0.f, 0.f); -			} -			else -			{ -				cam_at_axis = snap_plane_center - gAgentCamera.getCameraPositionAgent(); -				cam_at_axis.normVec(); -			} - -			// first, project mouse onto screen plane at point tangent to rotation radius.  -			getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_at_axis); -			// project that point onto rotation plane -			projected_mouse -= snap_plane_center; -			projected_mouse -= projected_vec(projected_mouse, constraint_axis); - -			F32 mouse_lateral_dist = llmin(SNAP_GUIDE_INNER_RADIUS * mRadiusMeters, projected_mouse.magVec()); -			F32 mouse_depth = SNAP_GUIDE_INNER_RADIUS * mRadiusMeters; -			if (llabs(mouse_lateral_dist) > 0.01f) -			{ -				mouse_depth = sqrtf((SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) * (SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) -  -									(mouse_lateral_dist * mouse_lateral_dist)); -			} -			LLVector3 projected_camera_at = cam_at_axis - projected_vec(cam_at_axis, constraint_axis); -			projected_mouse -= mouse_depth * projected_camera_at; - -			if (!mInSnapRegime) +	 +			if (snap_plane == 0)  			{ -				mSmoothRotate = TRUE; +				// try other plane +				snap_plane_center = (center - (constraint_axis * mRadiusMeters * 0.5f)); +				if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) +				{ +					cam_to_snap_plane.setVec(1.f, 0.f, 0.f); +				} +				else +				{ +					cam_to_snap_plane = snap_plane_center - gAgentCamera.getCameraPositionAgent(); +					cam_to_snap_plane.normVec(); +				} +	 +				hit = getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, constraint_axis); +				projected_mouse -= snap_plane_center; +	 +				dot = cam_to_snap_plane * constraint_axis; +				if (llabs(dot) < 0.01f) +				{ +					// looking at ring edge on, project onto view plane and check if mouse is past ring +					getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_to_snap_plane); +					projected_mouse -= snap_plane_center; +					dot = projected_mouse * constraint_axis; +					if (projected_mouse * constraint_axis < 0) +					{ +						snap_plane = 2; +					} +					projected_mouse -= dot * constraint_axis; +				} +				else if (dot < 0.f) +				{ +					// look for mouse position outside and in front of snap circle +					if (hit && projected_mouse.magVec() > SNAP_GUIDE_INNER_RADIUS * mRadiusMeters && projected_mouse * cam_to_snap_plane < 0.f) +					{ +						snap_plane = 2; +					} +				} +				else +				{ +					// look for mouse position inside or in back of snap circle +					if (projected_mouse.magVec() < SNAP_GUIDE_INNER_RADIUS * mRadiusMeters || projected_mouse * cam_to_snap_plane > 0.f || !hit) +					{ +						snap_plane = 2; +					} +				}  			} -			mInSnapRegime = TRUE; -			// 0 to 360 deg -			F32 mouse_angle = fmodf(atan2(projected_mouse * axis1, projected_mouse * axis2) * RAD_TO_DEG + 360.f, 360.f); -			F32 relative_mouse_angle = fmodf(mouse_angle + (SNAP_ANGLE_DETENTE / 2), SNAP_ANGLE_INCREMENT); -			//fmodf(llround(mouse_angle * RAD_TO_DEG, 7.5f) + 360.f, 360.f); - -			LLVector3 object_axis; -			getObjectAxisClosestToMouse(object_axis); -			object_axis = object_axis * first_object_node->mSavedRotation; - -			// project onto constraint plane -			object_axis = object_axis - (object_axis * getConstraintAxis()) * getConstraintAxis(); -			object_axis.normVec(); - -			if (relative_mouse_angle < SNAP_ANGLE_DETENTE) +			if (snap_plane > 0)  			{ -				F32 quantized_mouse_angle = mouse_angle - (relative_mouse_angle - (SNAP_ANGLE_DETENTE * 0.5f)); -				angle = (quantized_mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2); +				LLVector3 cam_at_axis; +				if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) +				{ +					cam_at_axis.setVec(1.f, 0.f, 0.f); +				} +				else +				{ +					cam_at_axis = snap_plane_center - gAgentCamera.getCameraPositionAgent(); +					cam_at_axis.normVec(); +				} +	 +				// first, project mouse onto screen plane at point tangent to rotation radius.  +				getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_at_axis); +				// project that point onto rotation plane +				projected_mouse -= snap_plane_center; +				projected_mouse -= projected_vec(projected_mouse, constraint_axis); +	 +				F32 mouse_lateral_dist = llmin(SNAP_GUIDE_INNER_RADIUS * mRadiusMeters, projected_mouse.magVec()); +				F32 mouse_depth = SNAP_GUIDE_INNER_RADIUS * mRadiusMeters; +				if (llabs(mouse_lateral_dist) > 0.01f) +				{ +					mouse_depth = sqrtf((SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) * (SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) -  +										(mouse_lateral_dist * mouse_lateral_dist)); +				} +				LLVector3 projected_camera_at = cam_at_axis - projected_vec(cam_at_axis, constraint_axis); +				projected_mouse -= mouse_depth * projected_camera_at; +	 +				if (!mInSnapRegime) +				{ +					mSmoothRotate = TRUE; +				} +				mInSnapRegime = TRUE; +				// 0 to 360 deg +				F32 mouse_angle = fmodf(atan2(projected_mouse * axis1, projected_mouse * axis2) * RAD_TO_DEG + 360.f, 360.f); +				 +				F32 relative_mouse_angle = fmodf(mouse_angle + (SNAP_ANGLE_DETENTE / 2), SNAP_ANGLE_INCREMENT); +				//fmodf(llround(mouse_angle * RAD_TO_DEG, 7.5f) + 360.f, 360.f); +	 +				LLVector3 object_axis; +				getObjectAxisClosestToMouse(object_axis); +				object_axis = object_axis * first_object_node->mSavedRotation; +	 +				// project onto constraint plane +				object_axis = object_axis - (object_axis * getConstraintAxis()) * getConstraintAxis(); +				object_axis.normVec(); +	 +				if (relative_mouse_angle < SNAP_ANGLE_DETENTE) +				{ +					F32 quantized_mouse_angle = mouse_angle - (relative_mouse_angle - (SNAP_ANGLE_DETENTE * 0.5f)); +					angle = (quantized_mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2); +				} +				else +				{ +					angle = (mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2); +				} +				return LLQuaternion( -angle, constraint_axis );  			}  			else  			{ -				angle = (mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2); +				if (mInSnapRegime) +				{ +					mSmoothRotate = TRUE; +				} +				mInSnapRegime = FALSE;  			} -			return LLQuaternion( -angle, constraint_axis );  		} -		else -		{ +		else {  			if (mInSnapRegime)  			{  				mSmoothRotate = TRUE;  			}  			mInSnapRegime = FALSE; - +		} +		 +		if (!mInSnapRegime) +		{  			LLVector3 up_from_axis = mCenterToCamNorm % constraint_axis;  			up_from_axis.normVec();  			LLVector3 cur_intersection; diff --git a/indra/newview/llnotificationstorage.h b/indra/newview/llnotificationstorage.h index 7aabf7d09e..53fd898ea4 100755 --- a/indra/newview/llnotificationstorage.h +++ b/indra/newview/llnotificationstorage.h @@ -44,6 +44,7 @@ public:  protected:  	bool writeNotifications(const LLSD& pNotificationData) const;  	bool readNotifications(LLSD& pNotificationData) const; +	void setFileName(std::string pFileName) {mFileName = pFileName;}  	LLNotificationResponderInterface* createResponder(const std::string& pNotificationName, const LLSD& pParams) const; diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index a85335f1ba..4ca961c1f9 100755 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -83,13 +83,6 @@ bool LLTipHandler::processNotification(const LLNotificationPtr& notification)  	if (notification->canLogToChat())  	{  		LLHandlerUtil::logToNearbyChat(notification, CHAT_SOURCE_SYSTEM); - -		// don't show toast if Nearby Chat is opened -		LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); -		if (nearby_chat->isChatVisible()) -		{ -			return false; -		}  	}  	std::string session_name = notification->getPayload()["SESSION_NAME"]; diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index bcb90bcb56..911ecaad9d 100755 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -82,10 +82,6 @@ const S32 MAX_PASSWORD = 16;  LLPanelLogin *LLPanelLogin::sInstance = NULL;  BOOL LLPanelLogin::sCapslockDidNotification = FALSE; -// Helper for converting a user name into the canonical "Firstname Lastname" form. -// For new accounts without a last name "Resident" is added as a last name. -static std::string canonicalize_username(const std::string& name); -  class LLLoginRefreshHandler : public LLCommandHandler  {  public: @@ -266,7 +262,6 @@ void LLPanelLogin::addFavoritesToStartLocation()  	// Load favorites into the combo.  	std::string user_defined_name = getChild<LLComboBox>("username_combo")->getSimple(); -	std::string canonical_user_name = canonicalize_username(user_defined_name);  	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml");  	LLSD fav_llsd;  	llifstream file; @@ -279,7 +274,7 @@ void LLPanelLogin::addFavoritesToStartLocation()  		// The account name in stored_favorites.xml has Resident last name even if user has  		// a single word account name, so it can be compared case-insensitive with the  		// user defined "firstname lastname". -		S32 res = LLStringUtil::compareInsensitive(canonical_user_name, iter->first); +		S32 res = LLStringUtil::compareInsensitive(user_defined_name, iter->first);  		if (res != 0)  		{  			lldebugs << "Skipping favorites for " << iter->first << llendl; @@ -1012,29 +1007,3 @@ void LLPanelLogin::onLocationSLURL()  	LLStartUp::setStartSLURL(location); // calls onUpdateStartSLURL, above   } - - -std::string canonicalize_username(const std::string& name) -{ -	std::string cname = name; -	LLStringUtil::trim(cname); - -	// determine if the username is a first/last form or not. -	size_t separator_index = cname.find_first_of(" ._"); -	std::string first = cname.substr(0, separator_index); -	std::string last; -	if (separator_index != cname.npos) -	{ -		last = cname.substr(separator_index+1, cname.npos); -		LLStringUtil::trim(last); -	} -	else -	{ -		// ...on Linden grids, single username users as considered to have -		// last name "Resident" -		last = "Resident"; -	} - -	// Username in traditional "firstname lastname" form. -	return first + ' ' + last; -} diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index d6535c88e9..53deded2f2 100755 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -130,6 +130,8 @@ BOOL LLPanelMainInventory::postBuild()  	mFilterTabs = getChild<LLTabContainer>("inventory filter tabs");  	mFilterTabs->setCommitCallback(boost::bind(&LLPanelMainInventory::onFilterSelected, this)); +    mCounterCtrl = getChild<LLUICtrl>("ItemcountText"); +      	//panel->getFilter().markDefault();  	// Set up the default inv. panel/filter settings. @@ -566,7 +568,7 @@ void LLPanelMainInventory::draw()  void LLPanelMainInventory::updateItemcountText()  {  	// *TODO: Calling setlocale() on each frame may be inefficient. -	LLLocale locale(LLStringUtil::getLocale()); +	//LLLocale locale(LLStringUtil::getLocale());  	std::string item_count_string;  	LLResMgr::getInstance()->getIntegerString(item_count_string, gInventory.getItemCount()); @@ -589,8 +591,7 @@ void LLPanelMainInventory::updateItemcountText()  		text = getString("ItemcountUnknown");  	} -	// *TODO: Cache the LLUICtrl* for the ItemcountText control -	getChild<LLUICtrl>("ItemcountText")->setValue(text); +    mCounterCtrl->setValue(text);  }  void LLPanelMainInventory::onFocusReceived() diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h index 899931aa89..394b004e20 100755 --- a/indra/newview/llpanelmaininventory.h +++ b/indra/newview/llpanelmaininventory.h @@ -121,6 +121,7 @@ private:  	LLFilterEditor*				mFilterEditor;  	LLTabContainer*				mFilterTabs; +    LLUICtrl*                   mCounterCtrl;  	LLHandle<LLFloater>			mFinderHandle;  	LLInventoryPanel*			mActivePanel;  	bool						mResortActivePanel; diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 4138558bad..d7c634d619 100755 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -76,6 +76,8 @@ static const std::string BLOCKED_TAB_NAME	= "blocked_panel"; // blocked avatars  static const std::string COLLAPSED_BY_USER  = "collapsed_by_user"; +extern S32 gMaxAgentGroups; +  /** Comparator for comparing avatar items by last interaction date */  class LLAvatarItemRecentComparator : public LLAvatarItemComparator  { @@ -808,6 +810,8 @@ void LLPanelPeople::updateButtons()  		LLPanel* groups_panel = mTabContainer->getCurrentPanel();  		groups_panel->getChildView("minus_btn")->setEnabled(item_selected && selected_id.notNull()); // a real group selected +		groups_panel->getChild<LLUICtrl>("groupcount")->setTextArg("[COUNT]", llformat("%d",gAgent.mGroups.count())); +		groups_panel->getChild<LLUICtrl>("groupcount")->setTextArg("[REMAINING]", llformat("%d",(gMaxAgentGroups-gAgent.mGroups.count())));  	}  	else  	{ diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index e2e7006773..5acc98904b 100755 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -36,6 +36,8 @@  #include "lltabcontainer.h"  #include "llviewercontrol.h"  #include "llviewernetwork.h" +#include "llmutelist.h" +#include "llpanelblockedlist.h"  static const std::string PANEL_PICKS = "panel_picks"; @@ -137,6 +139,12 @@ public:  			return true;  		} +		if (verb == "removefriend") +		{ +			LLAvatarActions::removeFriendDialog(avatar_id); +			return true; +		} +  		if (verb == "mute")  		{  			if (! LLAvatarActions::isBlocked(avatar_id)) @@ -155,6 +163,18 @@ public:  			return true;  		} +		if (verb == "block") +		{ +			if (params.size() > 2) +			{ +				const std::string object_name = params[2].asString(); +				LLMute mute(avatar_id, object_name, LLMute::OBJECT); +				LLMuteList::getInstance()->add(mute); +				LLPanelBlockedList::showPanelAndSelect(mute.mID); +			} +			return true; +		} +  		return false;  	}  }; diff --git a/indra/newview/llpersistentnotificationstorage.cpp b/indra/newview/llpersistentnotificationstorage.cpp index 666f10df96..076c3e0235 100755 --- a/indra/newview/llpersistentnotificationstorage.cpp +++ b/indra/newview/llpersistentnotificationstorage.cpp @@ -38,7 +38,8 @@  LLPersistentNotificationStorage::LLPersistentNotificationStorage()  	: LLSingleton<LLPersistentNotificationStorage>() -	, LLNotificationStorage(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "open_notifications.xml")) +	, LLNotificationStorage("") +	, mLoaded(false)  {  } @@ -89,8 +90,13 @@ void LLPersistentNotificationStorage::loadNotifications()  	LL_INFOS("LLPersistentNotificationStorage") << "start loading notifications" << LL_ENDL; -	LLNotifications::instance().getChannel("Persistent")-> -		connectChanged(boost::bind(&LLPersistentNotificationStorage::onPersistentChannelChanged, this, _1)); +	if (mLoaded) +	{ +		LL_INFOS("LLPersistentNotificationStorage") << "notifications already loaded, exiting" << LL_ENDL; +		return; +	} + +	mLoaded = true;  	LLSD input;  	if (!readNotifications(input) ||input.isUndefined()) @@ -135,8 +141,20 @@ void LLPersistentNotificationStorage::loadNotifications()  	LL_INFOS("LLPersistentNotificationStorage") << "finished loading notifications" << LL_ENDL;  } +void LLPersistentNotificationStorage::initialize() +{ +	setFileName(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "open_notifications.xml")); +	LLNotifications::instance().getChannel("Persistent")-> +		connectChanged(boost::bind(&LLPersistentNotificationStorage::onPersistentChannelChanged, this, _1)); +} +  bool LLPersistentNotificationStorage::onPersistentChannelChanged(const LLSD& payload)  { +	// In case we received channel changed signal but haven't yet loaded notifications, do it +	if (!mLoaded) +	{ +		loadNotifications(); +	}  	// we ignore "load" messages, but rewrite the persistence file on any other  	const std::string sigtype = payload["sigtype"].asString();  	if ("load" != sigtype) diff --git a/indra/newview/llpersistentnotificationstorage.h b/indra/newview/llpersistentnotificationstorage.h index 98a825d2c1..bf0306380e 100755 --- a/indra/newview/llpersistentnotificationstorage.h +++ b/indra/newview/llpersistentnotificationstorage.h @@ -53,10 +53,13 @@ public:  	void saveNotifications();  	void loadNotifications(); +	void initialize(); +  protected:  private:  	bool onPersistentChannelChanged(const LLSD& payload); +	bool mLoaded;  };  #endif // LL_LLPERSISTENTNOTIFICATIONSTORAGE_H diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 968a912ea2..e533be7f24 100755 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -86,6 +86,7 @@  #include "lltrans.h"  #include "llviewercontrol.h"  #include "llappviewer.h" +#include "llfloatergotoline.h"  const std::string HELLO_LSL =  	"default\n" @@ -193,12 +194,17 @@ private:  	LLScriptEdCore* mEditorCore;  	static LLFloaterScriptSearch*	sInstance; + +protected: +	LLLineEditor*			mSearchBox; +        void onSearchBoxCommit();  };  LLFloaterScriptSearch* LLFloaterScriptSearch::sInstance = NULL;  LLFloaterScriptSearch::LLFloaterScriptSearch(LLScriptEdCore* editor_core)  :	LLFloater(LLSD()), +	mSearchBox(NULL),  	mEditorCore(editor_core)  {  	buildFromFile("floater_script_search.xml"); @@ -221,6 +227,9 @@ LLFloaterScriptSearch::LLFloaterScriptSearch(LLScriptEdCore* editor_core)  BOOL LLFloaterScriptSearch::postBuild()  { +	mSearchBox = getChild<LLLineEditor>("search_text"); +	mSearchBox->setCommitCallback(boost::bind(&LLFloaterScriptSearch::onSearchBoxCommit, this)); +	mSearchBox->setCommitOnFocusLost(FALSE);  	childSetAction("search_btn", onBtnSearch,this);  	childSetAction("replace_btn", onBtnReplace,this);  	childSetAction("replace_all_btn", onBtnReplaceAll,this); @@ -315,6 +324,15 @@ BOOL LLFloaterScriptSearch::handleKeyHere(KEY key, MASK mask)  	return FALSE;  } +void LLFloaterScriptSearch::onSearchBoxCommit() +{ +	if (mEditorCore && mEditorCore->mEditor) +	{ +		LLCheckBoxCtrl* caseChk = getChild<LLCheckBoxCtrl>("case_text"); +		mEditorCore->mEditor->selectNext(getChild<LLUICtrl>("search_text")->getValue().asString(), caseChk->get()); +	} +} +  /// ---------------------------------------------------------------------------  /// LLScriptEdCore  /// --------------------------------------------------------------------------- @@ -503,6 +521,9 @@ void LLScriptEdCore::initMenu()  	menuItem = getChild<LLMenuItemCallGL>("Search / Replace...");  	menuItem->setClickCallback(boost::bind(&LLFloaterScriptSearch::show, this)); +	menuItem = getChild<LLMenuItemCallGL>("Go to line..."); +	menuItem->setClickCallback(boost::bind(&LLFloaterGotoLine::show, this)); +  	menuItem = getChild<LLMenuItemCallGL>("Help...");  	menuItem->setClickCallback(boost::bind(&LLScriptEdCore::onBtnHelp, this)); diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h index 7563cecd9d..9fb0a4fb63 100755 --- a/indra/newview/llpreviewscript.h +++ b/indra/newview/llpreviewscript.h @@ -34,6 +34,7 @@  #include "llcombobox.h"  #include "lliconctrl.h"  #include "llframetimer.h" +#include "llfloatergotoline.h"  class LLLiveLSLFile;  class LLMessageSystem; @@ -49,6 +50,7 @@ class LLKeywordToken;  class LLVFS;  class LLViewerInventoryItem;  class LLScriptEdContainer; +class LLFloaterGotoLine;  // Inner, implementation class.  LLPreviewScript and LLLiveLSLEditor each own one of these.  class LLScriptEdCore : public LLPanel @@ -58,6 +60,7 @@ class LLScriptEdCore : public LLPanel  	friend class LLLiveLSLEditor;  	friend class LLFloaterScriptSearch;  	friend class LLScriptEdContainer; +	friend class LLFloaterGotoLine;  protected:  	// Supposed to be invoked only by the container. diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index cff3a7e02a..67a76460a7 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -51,6 +51,7 @@  #include "lllandmark.h"  #include "llcachename.h"  #include "lldir.h" +#include "lldonotdisturbnotificationstorage.h"  #include "llerrorcontrol.h"  #include "llfloaterreg.h"  #include "llfocusmgr.h" @@ -68,6 +69,7 @@  #include "llfloaterimnearbychat.h"  #include "llnotifications.h"  #include "llnotificationsutil.h" +#include "llpersistentnotificationstorage.h"  #include "llteleporthistory.h"  #include "llregionhandle.h"  #include "llsd.h" @@ -900,6 +902,10 @@ bool idle_startup()  		gDirUtilp->setLindenUserDir(userid);  		LLFile::mkdir(gDirUtilp->getLindenUserDir()); +		// As soon as directories are ready initialize notification storages +		LLPersistentNotificationStorage::getInstance()->initialize(); +		LLDoNotDisturbNotificationStorage::getInstance()->initialize(); +  		// Set PerAccountSettingsFile to the default value.  		gSavedSettings.setString("PerAccountSettingsFile",  			gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT,  diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index 4846c54189..626d69aca4 100755 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -428,9 +428,18 @@ void LLNotificationWellWindow::onItemClick(LLSysWellItem* item)  void LLNotificationWellWindow::onItemClose(LLSysWellItem* item)  {  	LLUUID id = item->getID(); -	removeItemByID(id); +	  	if(mChannel) +	{ +		// removeItemByID() is invoked from killToastByNotificationID() and item will removed;  		mChannel->killToastByNotificationID(id); +	} +	else +	{ +		// removeItemByID() should be called one time for each item to remove it from notification well +		removeItemByID(id); +	} +  }  void LLNotificationWellWindow::onAdd( LLNotificationPtr notify ) diff --git a/indra/newview/lltoastimpanel.cpp b/indra/newview/lltoastimpanel.cpp index 75e6e3d13a..09ab31df36 100755 --- a/indra/newview/lltoastimpanel.cpp +++ b/indra/newview/lltoastimpanel.cpp @@ -28,6 +28,7 @@  #include "lltoastimpanel.h"  #include "llagent.h" +#include "llavatarnamecache.h"  #include "llfloaterreg.h"  #include "llgroupactions.h"  #include "llgroupiconctrl.h" @@ -61,6 +62,15 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) :	LLToastPanel(p.notif  	style_params.font.name(font_name);  	style_params.font.size(font_size); +	LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(p.session_id); +	mIsGroupMsg = (im_session && im_session->mSessionType == LLIMModel::LLIMSession::GROUP_SESSION); +	if(mIsGroupMsg) +	{ +		mAvatarName->setValue(im_session->mName); +		LLAvatarName avatar_name; +		LLAvatarNameCache::get(p.avatar_id, &avatar_name); +		p.message = "[From " + avatar_name.getDisplayName() + "]\n" + p.message; +	}  	//Handle IRC styled /me messages.  	std::string prefix = p.message.substr(0, 4); @@ -81,12 +91,17 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) :	LLToastPanel(p.notif  		mMessage->setText(p.message, style_params);  	} -	mAvatarName->setValue(p.from); +	if(!mIsGroupMsg) +	{ +		mAvatarName->setValue(p.from); +	}  	mTime->setValue(p.time);  	mSessionID = p.session_id;  	mAvatarID = p.avatar_id;  	mNotification = p.notification; + +  	initIcon();  	S32 maxLinesCount; @@ -147,7 +162,14 @@ void LLToastIMPanel::spawnNameToolTip()  	LLToolTip::Params params;  	params.background_visible(false); -	params.click_callback(boost::bind(&LLFloaterReg::showInstance, "inspect_avatar", LLSD().with("avatar_id", mAvatarID), FALSE)); +	if(!mIsGroupMsg) +	{ +		params.click_callback(boost::bind(&LLFloaterReg::showInstance, "inspect_avatar", LLSD().with("avatar_id", mAvatarID), FALSE)); +	} +	else +	{ +		params.click_callback(boost::bind(&LLFloaterReg::showInstance, "inspect_group", LLSD().with("group_id", mSessionID), FALSE)); +	}  	params.delay_time(0.0f);		// spawn instantly on hover  	params.image(LLUI::getUIImage("Info_Small"));  	params.message(""); diff --git a/indra/newview/lltoastimpanel.h b/indra/newview/lltoastimpanel.h index 3eb11fb3bc..767617dabc 100755 --- a/indra/newview/lltoastimpanel.h +++ b/indra/newview/lltoastimpanel.h @@ -73,6 +73,8 @@ private:  	LLTextBox*			mAvatarName;  	LLTextBox*			mTime;  	LLTextBox*			mMessage; + +	bool                mIsGroupMsg;  };  #endif // LLTOASTIMPANEL_H_ diff --git a/indra/newview/lltoolbarview.cpp b/indra/newview/lltoolbarview.cpp index b2318f9158..78a555d67d 100755 --- a/indra/newview/lltoolbarview.cpp +++ b/indra/newview/lltoolbarview.cpp @@ -51,8 +51,6 @@ LLToolBarView* gToolBarView = NULL;  static LLDefaultChildRegistry::Register<LLToolBarView> r("toolbar_view"); -void handleLoginToolbarSetup(); -  bool isToolDragged()  {  	return (LLToolDragAndDrop::getInstance()->getSource() == LLToolDragAndDrop::SOURCE_VIEWER); @@ -111,8 +109,6 @@ BOOL LLToolBarView::postBuild()  		mToolbars[i]->setButtonAddCallback(boost::bind(LLToolBarView::onToolBarButtonAdded,_1));  		mToolbars[i]->setButtonRemoveCallback(boost::bind(LLToolBarView::onToolBarButtonRemoved,_1));  	} - -	LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&handleLoginToolbarSetup));  	return TRUE;  } @@ -180,13 +176,13 @@ S32 LLToolBarView::stopCommandInProgress(const LLCommandId& commandId)  	return command_location;  } -S32 LLToolBarView::flashCommand(const LLCommandId& commandId, bool flash) +S32 LLToolBarView::flashCommand(const LLCommandId& commandId, bool flash, bool force_flashing/* = false */)  {  	S32 command_location = hasCommand(commandId);  	if (command_location != TOOLBAR_NONE)  	{ -		mToolbars[command_location]->flashCommand(commandId, flash); +		mToolbars[command_location]->flashCommand(commandId, flash, force_flashing);  	}  	return command_location; @@ -696,18 +692,3 @@ bool LLToolBarView::isModified() const  } -// -// HACK to bring up destinations guide at startup -// - -void handleLoginToolbarSetup() -{ -	// Open the destinations guide by default on first login, per Rhett -	if (gSavedPerAccountSettings.getBOOL("DisplayDestinationsOnInitialRun") || gAgent.isFirstLogin()) -	{ -		LLFloaterReg::showInstance("destinations"); - -		gSavedPerAccountSettings.setBOOL("DisplayDestinationsOnInitialRun", FALSE); -	} -} - diff --git a/indra/newview/lltoolbarview.h b/indra/newview/lltoolbarview.h index 7125dd9990..dcc3862074 100755 --- a/indra/newview/lltoolbarview.h +++ b/indra/newview/lltoolbarview.h @@ -90,7 +90,7 @@ public:  	S32 removeCommand(const LLCommandId& commandId, int& rank);	// Sets the rank the removed command was at, RANK_NONE if not found  	S32 enableCommand(const LLCommandId& commandId, bool enabled);  	S32 stopCommandInProgress(const LLCommandId& commandId); -	S32 flashCommand(const LLCommandId& commandId, bool flash); +	S32 flashCommand(const LLCommandId& commandId, bool flash, bool force_flashing = false);  	// Loads the toolbars from the existing user or default settings  	bool loadToolbars(bool force_default = false);	// return false if load fails diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index afbb59e723..744ec4de2b 100755 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -83,7 +83,9 @@  BOOL 				gHackGodmode = FALSE;  #endif - +// Should you contemplate changing the name "Global", please first grep for +// that string literal. There are at least a couple other places in the C++ +// code that assume the LLControlGroup named "Global" is gSavedSettings.  LLControlGroup gSavedSettings("Global");	// saved at end of session  LLControlGroup gSavedPerAccountSettings("PerAccount"); // saved at end of session  LLControlGroup gCrashSettings("CrashSettings");	// saved at end of session diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index f744f5ace2..1f0ffac737 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -259,11 +259,15 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response)  		    break;  	    } -	    LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm())); -	    modified_form->setElementEnabled("Accept", false); -	    modified_form->setElementEnabled("Decline", false); -	    notification_ptr->updateForm(modified_form); -	    notification_ptr->repost(); +		// TODO: this set of calls has undesirable behavior under Windows OS (CHUI-985): +		// here appears three additional toasts instead one modified +		// need investigation and fix + +	    // LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm())); +	    // modified_form->setElementEnabled("Accept", false); +	    // modified_form->setElementEnabled("Decline", false); +	    // notification_ptr->updateForm(modified_form); +	    // notification_ptr->repost();      }  	return false; @@ -2649,7 +2653,8 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  			{  				send_do_not_disturb_message(msg, from_id);  			} -			else +			 +			if (!is_muted)  			{  				LL_INFOS("Messaging") << "Received IM_GROUP_INVITATION message." << LL_ENDL;  				// Read the binary bucket for more information. @@ -3685,6 +3690,7 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)  		LLSD msg_notify = LLSD(LLSD::emptyMap());  		msg_notify["session_id"] = LLUUID();          msg_notify["from_id"] = chat.mFromID; +		msg_notify["source_type"] = chat.mSourceType;          on_new_message(msg_notify);  	}  } @@ -5942,6 +5948,15 @@ bool attempt_standard_notification(LLMessageSystem* msgsystem)  				return true;  			}  		} +		// HACK -- handle callbacks for specific alerts. +		if( notificationID == "HomePositionSet" ) +		{ +			// save the home location image to disk +			std::string snap_filename = gDirUtilp->getLindenUserDir(); +			snap_filename += gDirUtilp->getDirDelimiter(); +			snap_filename += SCREEN_HOME_FILENAME; +			gViewerWindow->saveSnapshot(snap_filename, gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw(), FALSE, FALSE); +		}  		LLNotificationsUtil::add(notificationID, llsdBlock);  		return true; @@ -6017,14 +6032,6 @@ void process_alert_core(const std::string& message, BOOL modal)  	{  		LLViewerStats::getInstance()->incStat(LLViewerStats::ST_KILLED_COUNT);  	} -	else if( message == "Home position set." ) -	{ -		// save the home location image to disk -		std::string snap_filename = gDirUtilp->getLindenUserDir(); -		snap_filename += gDirUtilp->getDirDelimiter(); -		snap_filename += SCREEN_HOME_FILENAME; -		gViewerWindow->saveSnapshot(snap_filename, gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw(), FALSE, FALSE); -	}  	const std::string ALERT_PREFIX("ALERT: ");  	const std::string NOTIFY_PREFIX("NOTIFY: "); diff --git a/indra/newview/llviewernetwork.cpp b/indra/newview/llviewernetwork.cpp index 97f4c3e5fe..e7821d4b9e 100755 --- a/indra/newview/llviewernetwork.cpp +++ b/indra/newview/llviewernetwork.cpp @@ -43,6 +43,8 @@ const std::string  GRID_LABEL_VALUE = "label";  const std::string  GRID_ID_VALUE = "grid_login_id";  /// the url for the login cgi script  const std::string  GRID_LOGIN_URI_VALUE = "login_uri"; +/// url base for update queries +const std::string  GRID_UPDATE_SERVICE_URL = "update_query_url_base";  ///  const std::string  GRID_HELPER_URI_VALUE = "helper_uri";  /// the splash page url @@ -63,6 +65,8 @@ const std::string DEFAULT_LOGIN_PAGE = "http://viewer-login.agni.lindenlab.com/"  const std::string MAIN_GRID_LOGIN_URI = "https://login.agni.lindenlab.com/cgi-bin/login.cgi"; +const std::string SL_UPDATE_QUERY_URL = "https://update.secondlife.com/update"; +  const std::string MAIN_GRID_SLURL_BASE = "http://maps.secondlife.com/secondlife/";  const std::string SYSTEM_GRID_APP_SLURL_BASE = "secondlife:///app"; @@ -120,12 +124,14 @@ void LLGridManager::initialize(const std::string& grid_file)  				  MAIN_GRID_LOGIN_URI,  				  "https://secondlife.com/helpers/",  				  DEFAULT_LOGIN_PAGE, +				  SL_UPDATE_QUERY_URL,  				  "Agni");  	addSystemGrid("Second Life Beta Test Grid (Aditi)",  				  "util.aditi.lindenlab.com",  				  "https://login.aditi.lindenlab.com/cgi-bin/login.cgi",  				  "http://aditi-secondlife.webdev.lindenlab.com/helpers/",  				  DEFAULT_LOGIN_PAGE, +				  SL_UPDATE_QUERY_URL,  				  "Aditi");  	LLSD other_grids; @@ -332,6 +338,7 @@ void LLGridManager::addSystemGrid(const std::string& label,  								  const std::string& login_uri,  								  const std::string& helper,  								  const std::string& login_page, +								  const std::string& update_url_base,  								  const std::string& login_id)  {  	LLSD grid = LLSD::emptyMap(); @@ -341,6 +348,7 @@ void LLGridManager::addSystemGrid(const std::string& label,  	grid[GRID_LOGIN_URI_VALUE] = LLSD::emptyArray();  	grid[GRID_LOGIN_URI_VALUE].append(login_uri);  	grid[GRID_LOGIN_PAGE_VALUE] = login_page; +	grid[GRID_UPDATE_SERVICE_URL] = update_url_base;  	grid[GRID_IS_SYSTEM_GRID_VALUE] = true;  	grid[GRID_LOGIN_IDENTIFIER_TYPES] = LLSD::emptyArray();  	grid[GRID_LOGIN_IDENTIFIER_TYPES].append(CRED_IDENTIFIER_TYPE_AGENT); @@ -537,6 +545,30 @@ std::string LLGridManager::getGridLoginID()  	return mGridList[mGrid][GRID_ID_VALUE];  } +std::string LLGridManager::getUpdateServiceURL() +{ +	std::string update_url_base = gSavedSettings.getString("CmdLineUpdateService");; +	if ( !update_url_base.empty() ) +	{ +		LL_INFOS2("UpdaterService","GridManager") +			<< "Update URL base overridden from command line: " << update_url_base +			<< LL_ENDL; +	} +	else if ( mGridList[mGrid].has(GRID_UPDATE_SERVICE_URL) ) +	{ +		update_url_base = mGridList[mGrid][GRID_UPDATE_SERVICE_URL].asString(); +	} +	else +	{ +		LL_WARNS2("UpdaterService","GridManager") +			<< "The grid property '" << GRID_UPDATE_SERVICE_URL +			<< "' is not defined for the grid '" << mGrid << "'" +			<< LL_ENDL; +	} +			 +	return update_url_base; +} +  void LLGridManager::updateIsInProductionGrid()  {  	mIsInProductionGrid = false; diff --git a/indra/newview/llviewernetwork.h b/indra/newview/llviewernetwork.h index 3f56103b2e..8526c0ba7f 100755 --- a/indra/newview/llviewernetwork.h +++ b/indra/newview/llviewernetwork.h @@ -140,6 +140,14 @@ class LLGridManager : public LLSingleton<LLGridManager>  	 */  	//@} +	/* ================================================================ +	 * @name Update Related Properties +	 * @{ +	 */ +	/// Get the update service URL base (host and path) for the selected grid +	std::string getUpdateServiceURL(); +	 +	//@}  	/* ================================================================  	 * @name URL Construction Properties @@ -207,6 +215,7 @@ class LLGridManager : public LLSingleton<LLGridManager>  					   const std::string& login,   					   const std::string& helper,  					   const std::string& login_page, +					   const std::string& update_url_base,  					   const std::string& login_id = "");	 diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index e98a2cb32c..963eb3eb88 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1824,7 +1824,6 @@ void LLViewerWindow::initBase()  	gFloaterView = main_view->getChild<LLFloaterView>("Floater View");  	gFloaterView->setFloaterSnapView(main_view->getChild<LLView>("floater_snap_region")->getHandle());  	gSnapshotFloaterView = main_view->getChild<LLSnapshotFloaterView>("Snapshot Floater View"); -	  	// Console  	llassert( !gConsole ); diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index a9176595c7..f53995732f 100755 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -884,4 +884,19 @@    <color      name="blue"      value="0 0 1 1"/> + +  <!--Resize bar colors --> + +  <color +    name="ResizebarBorderLight" +    value="0.231 0.231 0.231 1"/> + +  <color +    name="ResizebarBorderDark" +    value="0.133 0.133 0.133 1"/> + +  <color +    name="ResizebarBody" +    value="0.208 0.208 0.208 1"/> +      </colors> diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index b0e4b71d21..54f60f4441 100755 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -774,4 +774,7 @@ with the same filename but different name    <texture name="Popup_Caution" file_name="icons/pop_up_caution.png"/>    <texture name="Camera_Drag_Dot" file_name="world/CameraDragDot.png"/>    <texture name="NavBar Separator" file_name="navbar/separator.png"/> + +  <texture name="Horizontal Drag Handle" file_name="widgets/horizontal_drag_handle.png"/> +  <texture name="Vertical Drag Handle" file_name="widgets/vertical_drag_handle.png"/>  </textures> diff --git a/indra/newview/skins/default/textures/widgets/horizontal_drag_handle.png b/indra/newview/skins/default/textures/widgets/horizontal_drag_handle.pngBinary files differ new file mode 100644 index 0000000000..642eac4065 --- /dev/null +++ b/indra/newview/skins/default/textures/widgets/horizontal_drag_handle.png diff --git a/indra/newview/skins/default/textures/widgets/vertical_drag_handle.png b/indra/newview/skins/default/textures/widgets/vertical_drag_handle.pngBinary files differ new file mode 100644 index 0000000000..b06b70cf36 --- /dev/null +++ b/indra/newview/skins/default/textures/widgets/vertical_drag_handle.png diff --git a/indra/newview/skins/default/xui/da/floater_about.xml b/indra/newview/skins/default/xui/da/floater_about.xml index fc8bc33096..9206690c8f 100755 --- a/indra/newview/skins/default/xui/da/floater_about.xml +++ b/indra/newview/skins/default/xui/da/floater_about.xml @@ -8,7 +8,7 @@  		Bygget med [COMPILER] version [COMPILER_VERSION]  	</floater.string>  	<floater.string name="AboutPosition"> -		Du er ved [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] i regionen [REGION] lokaliseret ved <nolink>[HOSTNAME]</nolink> ([HOSTIP]) +		Du er ved [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] i regionen [REGION] lokaliseret ved <nolink>[HOSTNAME]</nolink> ([HOSTIP])  [SERVER_VERSION]  [SERVER_RELEASE_NOTES_URL]  	</floater.string> diff --git a/indra/newview/skins/default/xui/de/floater_about.xml b/indra/newview/skins/default/xui/de/floater_about.xml index 4387a61963..5245467183 100755 --- a/indra/newview/skins/default/xui/de/floater_about.xml +++ b/indra/newview/skins/default/xui/de/floater_about.xml @@ -8,7 +8,7 @@  		Kompiliert mit [COMPILER] version [COMPILER_VERSION]  	</floater.string>  	<floater.string name="AboutPosition"> -		Sie befinden sich in [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] in [REGION] auf <nolink>[HOSTNAME]</nolink> ([HOSTIP]) +		Sie befinden sich in [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] in [REGION] auf <nolink>[HOSTNAME]</nolink> ([HOSTIP])  [SERVER_VERSION]  [SERVER_RELEASE_NOTES_URL]  	</floater.string> diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml index 63eb87f27a..703015af20 100755 --- a/indra/newview/skins/default/xui/en/floater_about.xml +++ b/indra/newview/skins/default/xui/en/floater_about.xml @@ -22,7 +22,9 @@ Built with [COMPILER] version [COMPILER_VERSION]  </floater.string>    <floater.string       name="AboutPosition"> -You are at [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] in [REGION] located at <nolink>[HOSTNAME]</nolink> ([HOSTIP]) +You are at [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] in [REGION] located at <nolink>[HOSTNAME]</nolink> ([HOSTIP]) +SLURL: <nolink>[SLURL]</nolink> +(global coordinates [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1])  [SERVER_VERSION]  [SERVER_RELEASE_NOTES_URL] diff --git a/indra/newview/skins/default/xui/en/floater_bulk_perms.xml b/indra/newview/skins/default/xui/en/floater_bulk_perms.xml index 4e0cfb0cd4..e7ab3cacdc 100755 --- a/indra/newview/skins/default/xui/en/floater_bulk_perms.xml +++ b/indra/newview/skins/default/xui/en/floater_bulk_perms.xml @@ -6,7 +6,7 @@   layout="topleft"   name="floaterbulkperms"   help_topic="floaterbulkperms" - title="EDIT CONTENT PERMISSIONS" + title="ADJUST CONTENT PERMISSIONS"   width="410">      <floater.string       name="nothing_to_modify_text"> @@ -192,7 +192,7 @@       name="newperms"       top="90"       width="250"> -        New Content Permissions +        Adjust Content Permissions To      </text>        <text         type="string" @@ -292,11 +292,22 @@       height="23"       label="OK"       layout="topleft" -     left="205" -     name="apply" +     left="110" +     name="ok"       top_pad="10"       width="90">        <button.commit_callback +       function="BulkPermission.Ok"/> +    </button> +    <button +     follows="left|top" +     height="23" +     label="Apply" +     layout="topleft" +     left_pad="5" +     name="apply" +     width="90"> +      <button.commit_callback         function="BulkPermission.Apply"/>      </button>      <button diff --git a/indra/newview/skins/default/xui/en/floater_goto_line.xml b/indra/newview/skins/default/xui/en/floater_goto_line.xml new file mode 100644 index 0000000000..b236888219 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_goto_line.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + legacy_header_height="18" + default_tab_group="1" + height="90" + layout="topleft" + name="script goto" + help_topic="script_goto" + title="GO TO LINE" + width="200"> +    <button +     height="24" +     label="OK" +     label_selected="OK" +     layout="topleft" +     left="55" +     name="goto_btn" +     top="53" +     width="90" /> +    <text +     type="string" +     length="1" +     follows="left|top" +     height="16" +     layout="topleft" +     left="10" +     name="txt" +     top="21" +     width="65"> +        Go to line +    </text> +    <line_editor +     border_style="line" +     border_thickness="1" +     follows="left|top" +     height="16" +     layout="topleft" +     left="75" +     max_length_bytes="9" +     name="goto_line" +     tab_group="1" +     top="21" +     width="85" /> +</floater>
\ No newline at end of file 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 65f623a47e..1215efb7f9 100755 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -4,6 +4,7 @@   can_minimize="true"   can_resize="true"   height="210" + min_height="210"   layout="topleft"   name="floater_im_box"   help_topic="floater_im_box" @@ -24,24 +25,28 @@       value="Conv_toolbar_expand"/>      <layout_stack       animate="true"  -     bottom="-1" +     bottom="-5" +     drag_handle_gap="6" +     drag_handle_first_indent="27" +     drag_handle_second_indent="10"       follows="all"       layout="topleft"       left="0"       name="conversations_stack"       orientation="horizontal"       right="-1" +     show_drag_handle="true"       top="0">          <layout_panel           auto_resize="false"           user_resize="true"                   name="conversations_layout_panel"           min_dim="38" -         expanded_min_dim="156"> +         expanded_min_dim="136">              <layout_stack               animate="false"                follows="left|top|right" -             height="35" +             height="27"               layout="topleft"               left="0"               name="conversations_pane_buttons_stack" @@ -50,7 +55,6 @@               top="0">                  <layout_panel                   auto_resize="true" -                 height="35"                   name="conversations_pane_buttons_expanded">                      <menu_button                       follows="top|left" @@ -64,7 +68,7 @@                       left="5"                       name="sort_btn"                       tool_tip="View/sort options" -                     top="5" +                     top="1"                       width="31" />                      <button                       follows="top|left" @@ -74,7 +78,7 @@                       image_selected="Toolbar_Middle_Selected"                       image_unselected="Toolbar_Middle_Off"                       layout="topleft" -                     top="5" +                     top="1"                       left_pad="2"                       name="add_btn"                       tool_tip="Start a new conversation" @@ -87,7 +91,7 @@                       image_selected="Toolbar_Middle_Selected"                       image_unselected="Toolbar_Middle_Off"                       layout="topleft" -                     top="5" +                     top="1"                       left_pad="2"                       name="speak_btn"                       tool_tip="Speak with people using your microphone" @@ -95,9 +99,8 @@                  </layout_panel>                  <layout_panel                   auto_resize="false" -                 height="35"                   name="conversations_pane_buttons_collapsed" -                 width="41"> +                 width="31">                      <button                       follows="right|top"                       height="25" @@ -106,8 +109,8 @@                       image_selected="Toolbar_Middle_Selected"                       image_unselected="Toolbar_Middle_Off"                       layout="topleft" -                     top="5" -                     left="1" +                     top="1" +                     left="0"                       name="expand_collapse_btn"                       tool_tip="Collapse/Expand this list"                       width="31" /> @@ -119,7 +122,7 @@               layout="topleft"               name="conversations_list_panel"               opaque="true" -             top="35" +             top_pad="0"               left="5"               right="-1"/>          </layout_panel> @@ -127,7 +130,7 @@           auto_resize="true"           user_resize="true"           name="messages_layout_panel" -         expanded_min_dim="222"> +         expanded_min_dim="212">              <panel_container               bottom="-1"               follows="all" @@ -136,44 +139,44 @@               name="im_box_tab_container"               right="-1"               top="0"> -             <panel -               bottom="-1" -               follows="all" -               layout="topleft" -               name="stub_panel" -               opaque="true" -               top_pad="0" -               left="0" -               right="-1"> -                 <button -                 follows="right|top" -                 height="25" -                 image_hover_unselected="Toolbar_Middle_Over" -                 image_overlay="Conv_toolbar_collapse" -                 image_selected="Toolbar_Middle_Selected" -                 image_unselected="Toolbar_Middle_Off" +                <panel +                 bottom="-1" +                 follows="all"                   layout="topleft" -                 top="5" -                 right="-10" -                 name="stub_collapse_btn" -                 tool_tip="Collapse this pane" -                 width="31" /> -                 <text -                   type="string" -                   clip_partial="false" -                   follows="left|top|right" -                   layout="topleft" -                   left="15" -                   right="-15" -                   name="stub_textbox" -                   top="25" -                   height="40" -                   valign="center" -                   parse_urls="true" -                   wrap="true"> -                   This conversation is in a separate window.   [secondlife:/// Bring it back.] -                 </text> -             </panel> +                 name="stub_panel" +                 opaque="true" +                 top_pad="0" +                 left="0" +                 right="-1"> +                    <button +                     follows="right|top" +                     height="25" +                     image_hover_unselected="Toolbar_Middle_Over" +                     image_overlay="Conv_toolbar_collapse" +                     image_selected="Toolbar_Middle_Selected" +                     image_unselected="Toolbar_Middle_Off" +                     layout="topleft" +                     top="1" +                     right="-10" +                     name="stub_collapse_btn" +                     tool_tip="Collapse this pane" +                     width="31" /> +                    <text +                     type="string" +                     clip_partial="false" +                     follows="left|top|right" +                     layout="topleft" +                     left="15" +                     right="-15" +                     name="stub_textbox" +                     top="25" +                     height="40" +                     valign="center" +                     parse_urls="true" +                     wrap="true"> +                         This conversation is in a separate window.   [secondlife:/// Bring it back.] +                    </text> +                </panel>              </panel_container>          </layout_panel>      </layout_stack> diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 2152a9f6e9..43d0f2fb18 100755 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -70,26 +70,23 @@       top="0"       left="0"       right="-1" -     bottom="-3"> +     bottom="-1">          <layout_stack           animate="false"  +         bottom="-1"           default_tab_group="2"           follows="all" -         right="-5" -         bottom="-1" -         top="0" -         left="5" -         border_size="0" +         left="3"           layout="topleft" -         orientation="vertical"           name="main_stack" -         tab_group="1"> +         right="-3" +         orientation="vertical" +         tab_group="1" +         top="0">              <layout_panel               auto_resize="false"               name="toolbar_panel" -             height="35" -             right="-1" -             left="1"> +             height="25">                  <menu_button                   menu_filename="menu_im_session_showmodes.xml"                   follows="top|left" @@ -102,7 +99,7 @@                   left="5"                   name="view_options_btn"                   tool_tip="View/sort options" -                 top="5" +                 top="1"                   width="31" />                  <menu_button                   menu_filename="menu_im_conversation.xml" @@ -113,7 +110,7 @@                   image_selected="Toolbar_Middle_Selected"                   image_unselected="Toolbar_Middle_Off"                   layout="topleft" -                 top="5" +                 top="1"                   left_pad="2"                   name="gear_btn"                   visible="false" @@ -128,7 +125,7 @@                   image_selected="Toolbar_Middle_Selected"                   image_unselected="Toolbar_Middle_Off"                   layout="topleft" -                 top="5" +                 top="1"                   left_pad="2"                   name="add_btn"                   tool_tip="Add someone to this conversation" @@ -141,23 +138,11 @@                   image_selected="Toolbar_Middle_Selected"                   image_unselected="Toolbar_Middle_Off"                   layout="topleft" -                 top="5" +                 top="1"                   left_pad="2"                   name="voice_call_btn"                   tool_tip="Open voice connection" -                 width="31"/> -                <output_monitor -                 auto_update="true" -                 follows="top|left" -                 draw_border="false" -                 height="16" -                 layout="topleft" -                 top="10" -                 left_pad="10" -                 mouse_opaque="true" -                 name="speaking_indicator" -                 visible="false" -                 width="20" /> +                 width="31"/>                                  <button                   follows="right|top"                   height="25" @@ -166,8 +151,8 @@                   image_selected="Toolbar_Middle_Selected"                   image_unselected="Toolbar_Middle_Off"                   layout="topleft" -                 top="5" -                 right="-67" +                 top="1" +                 right="-70"                   name="close_btn"                   tool_tip="End this conversation"                   width="31" /> @@ -179,7 +164,7 @@                   image_selected="Toolbar_Middle_Selected"                   image_unselected="Toolbar_Middle_Off"                   layout="topleft" -                 top="5" +                 top="1"                   left_pad="2"                   name="expand_collapse_btn"                   tool_tip="Collapse/Expand this pane" @@ -194,18 +179,21 @@                   layout="topleft"                   left_pad="2"                   name="tear_off_btn" -                 top="5" +                 top="1"                   width="31" />              </layout_panel>              <layout_panel               name="body_panel" -             top="1" -             bottom="-1"> +             height="235">                  <layout_stack                   default_tab_group="2" +                 drag_handle_gap="6" +                 drag_handle_first_indent="0" +                 drag_handle_second_indent="1"                   follows="all"                   orientation="horizontal"                   name="im_panels" +                 show_drag_handle="true"                   tab_group="1"                   top="0"                   right="-1" @@ -217,14 +205,12 @@                       min_dim="0"                       width="150"                        user_resize="true" -                     auto_resize="false"  -                     bottom="-1" /> +                     auto_resize="false" />                      <layout_panel                       default_tab_group="3"                       tab_group="2"                       name="right_part_holder" -                     min_width="221" -                     bottom="-1"> +                     min_width="172">                          <layout_stack                           animate="true"                            default_tab_group="2" @@ -233,7 +219,7 @@                           name="translate_and_chat_stack"                           tab_group="1"                           top="0" -                         left="0" +                         left="1"                           right="-1"                           bottom="-1">                              <layout_panel @@ -259,7 +245,7 @@                                   parse_highlights="true"                                   parse_urls="true"                                   right="-1" -                                 left="5" +                                 left="0"                                   top="0"                                   bottom="-1" />                              </layout_panel> @@ -268,10 +254,7 @@                  </layout_stack>              </layout_panel>              <layout_panel -             top_delta="0" -             top="0" -             height="26" -             bottom="-1" +             height="35"               auto_resize="false"               name="chat_layout_panel">                  <layout_stack @@ -281,15 +264,11 @@                   orientation="horizontal"                   name="input_panels"                   top="0" -                 bottom="-2" +                 bottom="-1"                   left="0"                   right="-1">                      <layout_panel -                     name="input_editor_layout_panel" -                     auto_resize="true" -                     user_resize="false" -                     top="0" -                     bottom="-1"> +                     name="input_editor_layout_panel">                          <chat_editor                           layout="topleft"                           expand_lines_count="5" @@ -302,32 +281,27 @@                           max_length="1023"                           spellcheck="true"                           tab_group="3" -                         top="1" -                         bottom="-2" -                         left="4" -                         right="-4" +                         bottom="-8" +                         left="5" +                         right="-5"                           wrap="true" />                      </layout_panel>                      <layout_panel                       auto_resize="false" -                     user_resize="false"                       name="input_button_layout_panel" -                     width="30" -                     top="0" -                     bottom="-1"> +                     width="32">                          <button -                         layout="topleft"                           left="1" -                         right="-1" -                         top="1" -                         height="22" +                         top="4" +                         height="25"                           follows="left|right|top"                           image_hover_unselected="Toolbar_Middle_Over"                           image_overlay="Conv_expand_one_line"                           image_selected="Toolbar_Middle_Selected"                           image_unselected="Toolbar_Middle_Off"                           name="minz_btn" -                         tool_tip="Shows/hides message panel" /> +                         tool_tip="Shows/hides message panel" +                         width="28" />                      </layout_panel>                  </layout_stack>              </layout_panel> diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml index d8eb2f0ffd..31b1d091ee 100755 --- a/indra/newview/skins/default/xui/en/menu_conversation.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation.xml @@ -11,7 +11,7 @@       layout="topleft"       name="close_conversation">          <on_click function="Avatar.DoToSelected" parameter="close_conversation"/> -	 </menu_item_call> +	 </menu_item_call>	        <menu_item_call       label="Open voice conversation"       layout="topleft" @@ -25,6 +25,12 @@          <on_click function="Avatar.DoToSelected" parameter="disconnect_from_voice"/>      </menu_item_call>	  	<menu_item_separator layout="topleft" name="separator_disconnect_from_voice"/>	 +	<menu_item_call +     label="Close Selected" +     layout="topleft" +     name="close_selected_conversations"> +        <on_click function="Avatar.DoToSelected" parameter="close_selected_conversations"/> +	 </menu_item_call>      <menu_item_call       label="View Profile"       layout="topleft" diff --git a/indra/newview/skins/default/xui/en/menu_people_friends_view.xml b/indra/newview/skins/default/xui/en/menu_people_friends_view.xml index dde9432867..8790fde7c5 100755 --- a/indra/newview/skins/default/xui/en/menu_people_friends_view.xml +++ b/indra/newview/skins/default/xui/en/menu_people_friends_view.xml @@ -44,6 +44,8 @@      <menu_item_check.on_check       function="Floater.Visible"       parameter="conversation" /> +    <menu_item_check.on_enable +     function="Conversation.IsConversationLoggingAllowed" />      <menu_item_check.on_click       function="Floater.Toggle"       parameter="conversation" /> 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 7cd56f257a..e8b6116026 100755 --- a/indra/newview/skins/default/xui/en/menu_url_agent.xml +++ b/indra/newview/skins/default/xui/en/menu_url_agent.xml @@ -21,8 +21,15 @@       layout="topleft"       name="add_friend">          <menu_item_call.on_click -         function="Url.AddFriend" />         +         function="Url.AddFriend" />      </menu_item_call> +    <menu_item_call +     label="Remove Friend..." +     layout="topleft" +     name="remove_friend"> +        <menu_item_call.on_click +         function="Url.RemoveFriend" /> +        </menu_item_call>      <menu_item_separator       layout="topleft" />      <menu_item_call diff --git a/indra/newview/skins/default/xui/en/menu_url_objectim.xml b/indra/newview/skins/default/xui/en/menu_url_objectim.xml index 87ab58e622..b9d003b841 100755 --- a/indra/newview/skins/default/xui/en/menu_url_objectim.xml +++ b/indra/newview/skins/default/xui/en/menu_url_objectim.xml @@ -9,6 +9,13 @@          <menu_item_call.on_click           function="Url.Execute" />      </menu_item_call> +    <menu_item_call +     label="Block..." +     layout="topleft" +     name="block_object"> +        <menu_item_call.on_click +         function="Url.Block" /> +    </menu_item_call>      <menu_item_separator       layout="topleft" />      <menu_item_call diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index b71faa2d3e..dabfc4eebd 100755 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -874,6 +874,15 @@                   function="Tools.EnableSelectNextPart" />              </menu_item_call>          </menu> +        <menu_item_call +            label="Linksets..." +            name="pathfinding_linkset_menu_item"> +          <menu_item_call.on_click +              function="Floater.ToggleOrBringToFront" +              parameter="pathfinding_linksets" /> +          <menu_item_call.on_enable +              function="Tools.EnablePathfinding" /> +        </menu_item_call>           <menu_item_separator/>          <menu_item_call @@ -896,7 +905,7 @@            <menu_item_call.on_enable               function="Tools.SomethingSelectedNoHUD" />          </menu_item_call> - +		           <menu_item_separator/>          <menu diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 1867141758..9ed9a6f409 100755 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -3736,6 +3736,17 @@ Leave Group?    </notification>    <notification +   icon="alertmodal.tga" +   name="OwnerCannotLeaveGroup" +   type="alertmodal"> +    Unable to leave group. You cannot leave the group because you are the last owner of the group. Please assign another member to the owner role first. +    <tag>group</tag> +    <usetemplate +     name="okbutton" +     yestext="OK"/> +  </notification> + +  <notification     icon="alert.tga"     name="ConfirmKick"     type="alert"> @@ -5991,9 +6002,7 @@ Your calling card was declined.     icon="notifytip.tga"     name="TeleportToPerson"     type="notifytip"> -    To contact Residents like '[NAME]', click on the "People" button , select a Resident from the window that opens, then click 'IM' at the -    bottom of the window. -    (You can also double-click on their name in the list, or right-click and choose 'IM'). +    To open a private conversation with someone, right-click on their avatar and choose 'IM' from the menu.    </notification>    <notification @@ -6621,7 +6630,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th     icon="notify.tga"     name="JoinGroup"     persist="true" -   type="notify"> +   type="offer">      <tag>group</tag>  [MESSAGE]      <form name="form"> diff --git a/indra/newview/skins/default/xui/en/panel_group_notices.xml b/indra/newview/skins/default/xui/en/panel_group_notices.xml index 6d5fb51e85..c8ce5cdebf 100755 --- a/indra/newview/skins/default/xui/en/panel_group_notices.xml +++ b/indra/newview/skins/default/xui/en/panel_group_notices.xml @@ -202,14 +202,14 @@ Maximum 200 per group daily              Drag and drop item here to attach it:          </text>          <icon -         height="72" +         height="48"           image_name="DropTarget"           layout="topleft"           left_pad="10"           mouse_opaque="true"           name="drop_icon"           top_delta="-10" -         width="72" /> +         width="110" />          <button           follows="left|top"           layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index 7ce2627be9..ed274d0233 100755 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -480,10 +480,22 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M                       function="People.Group.Minus" />                  </dnd_button>              </panel> +            <text +                type="string" +                length="1" +                follows="all" +                height="14" +                layout="topleft" +                right="-10" +                top_pad="4" +                left="3" +                name="groupcount"> +              You belong to [COUNT] groups, and can join [REMAINING] more. +            </text>              <group_list               allow_select="true"                follows="all" -             height="406" +             height="388"               layout="topleft"               left="3"               name="group_list" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml index 2cc9d9c1b0..50fd57494f 100755 --- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml @@ -138,7 +138,7 @@     initial_value="1"     layout="topleft"     left_pad="0" -   max_val="1.4" +   max_val="1.5"     min_val="0.75"     name="ui_scale_slider"     top_pad="-14" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index bd096ebb88..8e867259c5 100755 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -14,6 +14,7 @@        border="false"        height="60"        layout="topleft" +      name="general_chat_settings"         top="10"        left="13"        width="517"> @@ -97,20 +98,13 @@        border="false"        height="165"        layout="topleft" +      name="im_notification_settings" 	        left="13"        width="517">      <text          layout="topleft"          height="12" -        name="notifications" -        left="0" -        width="120"> -      Notifications -    </text> -    <text -        layout="topleft" -        height="12"          name="friend_ims"          width="145"          left="0" @@ -138,17 +132,27 @@            name="FlashToolbarButton"            value="flash"/>        <item -          label="None" -          name="None" -          value="none"/> +          label="No action" +          name="NoAction" +          value="noaction"/>      </combo_box> +    <check_box +        control_name="PlaySoundFriendIM" +        height="23" +        label="Play sound" +        layout="topleft" +        name="play_sound_friend_im" +        left_pad="7" +        top_delta="-3" +        width="28"> +    </check_box>      <text          layout="topleft"          height="12"          name="non_friend_ims"          width="145"          left="0" -        top_pad="9"> +        top_pad="11">        Non-friend IMs:      </text>      <combo_box @@ -172,17 +176,27 @@            name="FlashToolbarButton"            value="flash"/>        <item -          label="None" -          name="None" -          value="none"/> +          label="No action" +          name="NoAction" +          value="noaction"/>      </combo_box> +    <check_box +        control_name="PlaySoundNonFriendIM" +        height="23" +        label="Play sound" +        layout="topleft" +        name="play_sound_non_friend_im" +        left_pad="7" +        top_delta="-3" +        width="28"> +    </check_box>      <text          layout="topleft"          left="0"          height="13"          name="conference_ims"          width="145" -        top_pad="9"> +        top_pad="11">        Conference IMs:      </text>      <combo_box @@ -206,17 +220,27 @@            name="FlashToolbarButton"            value="flash"/>        <item -          label="None" -          name="None" -          value="none"/> +          label="No action" +          name="NoAction" +          value="noaction"/>      </combo_box> +    <check_box +        control_name="PlaySoundConferenceIM" +        height="23" +        label="Play sound" +        layout="topleft" +        name="play_sound_conference_im" +        left_pad="7" +        top_delta="-3" +        width="28"> +    </check_box>      <text          layout="topleft"          left="0"          height="13"          name="group_chat"          width="145" -        top_pad="9"> +        top_pad="11">        Group chat:      </text>      <combo_box @@ -240,17 +264,27 @@            name="FlashToolbarButton"            value="flash"/>        <item -          label="None" -          name="None" -          value="none"/> +          label="No action" +          name="NoAction" +          value="noaction"/>      </combo_box> +    <check_box +        control_name="PlaySoundGroupChatIM" +        height="23" +        label="Play sound" +        layout="topleft" +        name="play_sound_group_chat_im" +        left_pad="7" +        top_delta="-3" +        width="28"> +    </check_box>      <text          layout="topleft"          left="0"          height="12"          name="nearby_chat"          width="145" -        top_pad="9"> +        top_pad="11">        Nearby chat:      </text>      <combo_box @@ -274,10 +308,64 @@            name="FlashToolBarButton"            value="flash"/>        <item -          label="None" -          name="None" -          value="none"/> +          label="No action" +          name="NoAction" +          value="noaction"/>      </combo_box> +    <check_box +        control_name="PlaySoundNearbyChatIM" +        height="23" +        label="Play sound" +        layout="topleft" +        name="play_sound_nearby_chat_im" +        left_pad="7" +        top_delta="-3" +        width="28"> +    </check_box> +    <text +        layout="topleft" +        left="0" +        height="12" +        name="object_ims" +        width="145" +        top_pad="11"> +      Object IMs: +    </text> +    <combo_box +        control_name="NotificationObjectIMOptions" +        height="23" +        layout="topleft" +        left_pad="5" +        top_delta="-6" +        name="ObjectIMOptions" +        width="223"> +      <item +          label="Open Conversations window" +          name="OpenConversationsWindow" +          value="openconversations"/> +      <item +          label="Pop up the message" +          name="PopUpMessage" +          value="toast"/> +      <item +          label="Flash toolbar button" +          name="FlashToolBarButton" +          value="flash"/> +      <item +          label="No action" +          name="NoAction" +          value="noaction"/> +    </combo_box> +    <check_box +        control_name="PlaySoundObjectIM" +        height="23" +        label="Play sound" +        layout="topleft" +        name="play_sound_object_im" +        left_pad="7" +        top_delta="-3" +        width="28"> +    </check_box>      <text          layout="topleft"          left="0" @@ -296,6 +384,7 @@        border="false"        height="50"        layout="topleft" +      name="play_sound_settings"  	        left="13"        top_pad="10"        width="517"> @@ -358,6 +447,7 @@    <panel        height="50"        layout="topleft" +      name="log_settings" 	        left="13"        top_pad="10"        width="505"> diff --git a/indra/newview/skins/default/xui/en/panel_script_ed.xml b/indra/newview/skins/default/xui/en/panel_script_ed.xml index 765b07ed8b..bcdef96138 100755 --- a/indra/newview/skins/default/xui/en/panel_script_ed.xml +++ b/indra/newview/skins/default/xui/en/panel_script_ed.xml @@ -125,6 +125,10 @@               label="Search / Replace..."               layout="topleft"               name="Search / Replace..." /> +            <menu_item_call +             label="Go to line..." +             layout="topleft" +             name="Go to line..." />          </menu>          <menu           top="0" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index a56213cdfe..a6b1961849 100755 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -209,7 +209,8 @@ Please try logging in again in a minute.</string>  	<string name="SLappAgentIM">IM</string>  	<string name="SLappAgentPay">Pay</string>  	<string name="SLappAgentOfferTeleport">Offer Teleport to </string> -	<string name="SLappAgentRequestFriend">Friend Request </string> +	<string name="SLappAgentRequestFriend">Friend Request</string> +  <string name="SLappAgentRemoveFriend">Friend Removal</string>  	<!-- ButtonToolTips, llfloater.cpp -->  	<string name="BUTTON_CLOSE_DARWIN">Close (⌘W)</string> @@ -3933,5 +3934,8 @@ Try enclosing path to the editor with double quotes.    <string name="logging_calls_enabled_log_empty">      There are no logged conversations. After you contact someone, or someone contacts you, a log entry will be shown here.    </string> +  <string name="loading_chat_logs"> +    Loading... +  </string>    </strings> diff --git a/indra/newview/skins/default/xui/es/floater_about.xml b/indra/newview/skins/default/xui/es/floater_about.xml index 3696c7e12c..7ca1e3721f 100755 --- a/indra/newview/skins/default/xui/es/floater_about.xml +++ b/indra/newview/skins/default/xui/es/floater_about.xml @@ -8,7 +8,7 @@  		Compilado con [COMPILER], versión [COMPILER_VERSION]  	</floater.string>  	<floater.string name="AboutPosition"> -		Estás en la posición [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1], de [REGION], alojada en <nolink>[HOSTNAME]</nolink> ([HOSTIP]) +		Estás en la posición [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1], de [REGION], alojada en <nolink>[HOSTNAME]</nolink> ([HOSTIP])  [SERVER_VERSION]  [SERVER_RELEASE_NOTES_URL]  	</floater.string> diff --git a/indra/newview/skins/default/xui/fr/floater_about.xml b/indra/newview/skins/default/xui/fr/floater_about.xml index a659cb4245..d45bdccf3e 100755 --- a/indra/newview/skins/default/xui/fr/floater_about.xml +++ b/indra/newview/skins/default/xui/fr/floater_about.xml @@ -8,7 +8,7 @@  		Compilé avec [COMPILER] version [COMPILER_VERSION]  	</floater.string>  	<floater.string name="AboutPosition"> -		Vous êtes à [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] dans [REGION], se trouvant à <nolink>[HOSTNAME]</nolink> ([HOSTIP]) +		Vous êtes à [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] dans [REGION], se trouvant à <nolink>[HOSTNAME]</nolink> ([HOSTIP])  [SERVER_VERSION]  [SERVER_RELEASE_NOTES_URL]  	</floater.string> diff --git a/indra/newview/skins/default/xui/it/floater_about.xml b/indra/newview/skins/default/xui/it/floater_about.xml index c672511fc5..b0fb585fa2 100755 --- a/indra/newview/skins/default/xui/it/floater_about.xml +++ b/indra/newview/skins/default/xui/it/floater_about.xml @@ -8,7 +8,7 @@  		Generato con [COMPILER] versione [COMPILER_VERSION]  	</floater.string>  	<floater.string name="AboutPosition"> -		Tu sei  [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] in [REGION] che si trova a <nolink>[HOSTNAME]</nolink> ([HOSTIP]) +		Tu sei  [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] in [REGION] che si trova a <nolink>[HOSTNAME]</nolink> ([HOSTIP])  [SERVER_VERSION]  [SERVER_RELEASE_NOTES_URL]  	</floater.string> diff --git a/indra/newview/skins/default/xui/ja/floater_about.xml b/indra/newview/skins/default/xui/ja/floater_about.xml index 6d5df75645..eae52c98ec 100755 --- a/indra/newview/skins/default/xui/ja/floater_about.xml +++ b/indra/newview/skins/default/xui/ja/floater_about.xml @@ -8,7 +8,7 @@  		コンパイラー [COMPILER] [COMPILER_VERSION] バージョン  	</floater.string>  	<floater.string name="AboutPosition"> -		あなたの現在地は、[POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] の [REGION] です。位置は <nolink>[HOSTNAME]</nolink> です。([HOSTIP]) +		あなたの現在地は、[POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] の [REGION] です。位置は <nolink>[HOSTNAME]</nolink> です。([HOSTIP])  [SERVER_VERSION]  [SERVER_RELEASE_NOTES_URL]  	</floater.string> diff --git a/indra/newview/skins/default/xui/pl/floater_about.xml b/indra/newview/skins/default/xui/pl/floater_about.xml index 409429ffaa..61a72ff27d 100755 --- a/indra/newview/skins/default/xui/pl/floater_about.xml +++ b/indra/newview/skins/default/xui/pl/floater_about.xml @@ -8,7 +8,7 @@  		Buduj z [COMPILER] wersją [COMPILER_VERSION]  	</floater.string>  	<floater.string name="AboutPosition"> -		Położenie [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] w [REGION] zlokalizowanym w <nolink>[HOSTNAME]</nolink> ([HOSTIP]) +		Położenie [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] w [REGION] zlokalizowanym w <nolink>[HOSTNAME]</nolink> ([HOSTIP])  [SERVER_VERSION]  [SERVER_RELEASE_NOTES_URL]  	</floater.string> diff --git a/indra/newview/skins/default/xui/pt/floater_about.xml b/indra/newview/skins/default/xui/pt/floater_about.xml index 299f88b22a..d089266342 100755 --- a/indra/newview/skins/default/xui/pt/floater_about.xml +++ b/indra/newview/skins/default/xui/pt/floater_about.xml @@ -7,7 +7,7 @@  		Construído com [COMPILER] versão [COMPILER_VERSION]  	</floater.string>  	<floater.string name="AboutPosition"> -		Você está em [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] em [REGION] localizado em [HOSTNAME]</nolink>([HOSTIP]) +		Você está em [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] em [REGION] localizado em [HOSTNAME]</nolink>([HOSTIP])  [SERVER_VERSION]  [SERVER_RELEASE_NOTES_URL]  	</floater.string> diff --git a/indra/newview/skins/default/xui/ru/floater_about.xml b/indra/newview/skins/default/xui/ru/floater_about.xml index bb6266ac9a..2b2b3cf453 100755 --- a/indra/newview/skins/default/xui/ru/floater_about.xml +++ b/indra/newview/skins/default/xui/ru/floater_about.xml @@ -8,7 +8,7 @@  		Использован компилятор [COMPILER], версия [COMPILER_VERSION]  	</floater.string>  	<floater.string name="AboutPosition"> -		Вы в точке [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] в регионе «[REGION]», расположенном на <nolink>[HOSTNAME]</nolink> ([HOSTIP]) +		Вы в точке [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] в регионе «[REGION]», расположенном на <nolink>[HOSTNAME]</nolink> ([HOSTIP])  [SERVER_VERSION]  [SERVER_RELEASE_NOTES_URL]  	</floater.string> diff --git a/indra/newview/skins/default/xui/tr/floater_about.xml b/indra/newview/skins/default/xui/tr/floater_about.xml index 9cc9c7a220..4dcf6200c6 100755 --- a/indra/newview/skins/default/xui/tr/floater_about.xml +++ b/indra/newview/skins/default/xui/tr/floater_about.xml @@ -8,7 +8,7 @@  		[COMPILER] [COMPILER_VERSION] sürümü ile oluşturuldu  	</floater.string>  	<floater.string name="AboutPosition"> -		<nolink>[HOSTNAME]</nolink> ([HOSTIP]) üzerinde bulunan [REGION] içerisinde [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] konumundasınız +		<nolink>[HOSTNAME]</nolink> ([HOSTIP]) üzerinde bulunan [REGION] içerisinde [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] konumundasınız  [SERVER_VERSION]  [SERVER_RELEASE_NOTES_URL]  	</floater.string> diff --git a/indra/newview/skins/default/xui/zh/floater_about.xml b/indra/newview/skins/default/xui/zh/floater_about.xml index 643881e416..1193243c7e 100755 --- a/indra/newview/skins/default/xui/zh/floater_about.xml +++ b/indra/newview/skins/default/xui/zh/floater_about.xml @@ -8,7 +8,7 @@  		以 [COMPILER_VERSION] 版本 [COMPILER] 建置  	</floater.string>  	<floater.string name="AboutPosition"> -		你的方位是 [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1],地區名:[REGION],主機:<nolink>[HOSTNAME]</nolink> ([HOSTIP]) +		你的方位是 [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1],地區名:[REGION],主機:<nolink>[HOSTNAME]</nolink> ([HOSTIP])  [SERVER_VERSION]  [SERVER_RELEASE_NOTES_URL]  	</floater.string> diff --git a/indra/newview/tests/llagentaccess_test.cpp b/indra/newview/tests/llagentaccess_test.cpp index 3ba25f3c10..a40b5c9a3d 100755 --- a/indra/newview/tests/llagentaccess_test.cpp +++ b/indra/newview/tests/llagentaccess_test.cpp @@ -49,10 +49,10 @@ LLControlGroup::~LLControlGroup()  }  // Implementation of just the LLControlGroup methods we requre -BOOL LLControlGroup::declareU32(const std::string& name, U32 initial_val, const std::string& comment, BOOL persist) +LLControlVariable* LLControlGroup::declareU32(const std::string& name, U32 initial_val, const std::string& comment, LLControlVariable::ePersist persist)  {  	test_preferred_maturity = initial_val; -	return true; +	return NULL;  }  void LLControlGroup::setU32(const std::string& name, U32 val) @@ -80,7 +80,7 @@ namespace tut  	void agentaccess_object_t::test<1>()  	{  		LLControlGroup cgr("test"); -		cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE); +		cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", LLControlVariable::PERSIST_NO);  		LLAgentAccess aa(cgr);  		cgr.setU32("PreferredMaturity", SIM_ACCESS_PG); @@ -109,7 +109,7 @@ namespace tut  	void agentaccess_object_t::test<2>()  	{  		LLControlGroup cgr("test"); -		cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE); +		cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", LLControlVariable::PERSIST_NO);  		LLAgentAccess aa(cgr);  		// make sure default is PG @@ -157,7 +157,7 @@ namespace tut  	void agentaccess_object_t::test<3>()  	{  		LLControlGroup cgr("test"); -		cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE); +		cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", LLControlVariable::PERSIST_NO);  		LLAgentAccess aa(cgr);  #ifndef HACKED_GODLIKE_VIEWER @@ -195,7 +195,7 @@ namespace tut  	void agentaccess_object_t::test<4>()  	{  		LLControlGroup cgr("test"); -		cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE); +		cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", LLControlVariable::PERSIST_NO);  		LLAgentAccess aa(cgr);  #ifndef HACKED_GODLIKE_VIEWER @@ -272,7 +272,7 @@ namespace tut  	void agentaccess_object_t::test<5>()  	{  		LLControlGroup cgr("test"); -		cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE); +		cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", LLControlVariable::PERSIST_NO);  		LLAgentAccess aa(cgr);  		cgr.setU32("PreferredMaturity", SIM_ACCESS_ADULT); diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp index f038112fd0..adeb848e03 100755 --- a/indra/newview/tests/lllogininstance_test.cpp +++ b/indra/newview/tests/lllogininstance_test.cpp @@ -135,6 +135,7 @@ void LLGridManager::addSystemGrid(const std::string& label,  								  const std::string& login,   								  const std::string& helper,  								  const std::string& login_page, +								  const std::string& update_url_base,  								  const std::string& login_id)  {  } @@ -175,8 +176,8 @@ F32 LLControlGroup::getF32(const std::string& name) { return 0.0f; }  U32 LLControlGroup::saveToFile(const std::string& filename, BOOL nondefault_only) { return 1; }  void LLControlGroup::setString(const std::string& name, const std::string& val) {}  std::string LLControlGroup::getString(const std::string& name) { return "test_string"; } -BOOL LLControlGroup::declareBOOL(const std::string& name, BOOL initial_val, const std::string& comment, BOOL persist) { return TRUE; } -BOOL LLControlGroup::declareString(const std::string& name, const std::string &initial_val, const std::string& comment, BOOL persist) { return TRUE; } +LLControlVariable* LLControlGroup::declareBOOL(const std::string& name, BOOL initial_val, const std::string& comment, LLControlVariable::ePersist persist) { return NULL; } +LLControlVariable* LLControlGroup::declareString(const std::string& name, const std::string &initial_val, const std::string& comment, LLControlVariable::ePersist persist) { return NULL; }  #include "lluicolortable.h"  void LLUIColorTable::saveUserSettings(void)const {} @@ -208,9 +209,7 @@ std::string const & LLUpdaterService::pumpName(void)  	return wakka;  }  bool LLUpdaterService::updateReadyToInstall(void) { return false; } -void LLUpdaterService::initialize(const std::string& url,  -								  const std::string& path, -								  const std::string& channel, +void LLUpdaterService::initialize(const std::string& channel,  								  const std::string& version,  								  const std::string& platform,  								  const std::string& platform_version, @@ -344,13 +343,13 @@ namespace tut  			gTOSReplyPump = 0; // clear the callback. -			gSavedSettings.declareBOOL("NoInventoryLibrary", FALSE, "", FALSE); -			gSavedSettings.declareBOOL("ConnectAsGod", FALSE, "", FALSE); -			gSavedSettings.declareBOOL("UseDebugMenus", FALSE, "", FALSE); -			gSavedSettings.declareBOOL("ForceMandatoryUpdate", FALSE, "", FALSE); -			gSavedSettings.declareString("ClientSettingsFile", "test_settings.xml", "", FALSE); -			gSavedSettings.declareString("NextLoginLocation", "", "", FALSE); -			gSavedSettings.declareBOOL("LoginLastLocation", FALSE, "", FALSE); +			gSavedSettings.declareBOOL("NoInventoryLibrary", FALSE, "", LLControlVariable::PERSIST_NO); +			gSavedSettings.declareBOOL("ConnectAsGod", FALSE, "", LLControlVariable::PERSIST_NO); +			gSavedSettings.declareBOOL("UseDebugMenus", FALSE, "", LLControlVariable::PERSIST_NO); +			gSavedSettings.declareBOOL("ForceMandatoryUpdate", FALSE, "", LLControlVariable::PERSIST_NO); +			gSavedSettings.declareString("ClientSettingsFile", "test_settings.xml", "", LLControlVariable::PERSIST_NO); +			gSavedSettings.declareString("NextLoginLocation", "", "", LLControlVariable::PERSIST_NO); +			gSavedSettings.declareBOOL("LoginLastLocation", FALSE, "", LLControlVariable::PERSIST_NO);  			LLSD authenticator = LLSD::emptyMap();  			LLSD identifier = LLSD::emptyMap(); diff --git a/indra/newview/tests/llsecapi_test.cpp b/indra/newview/tests/llsecapi_test.cpp index 703603e2db..d7e87ed52e 100755 --- a/indra/newview/tests/llsecapi_test.cpp +++ b/indra/newview/tests/llsecapi_test.cpp @@ -39,10 +39,10 @@  LLControlGroup::LLControlGroup(const std::string& name)  : LLInstanceTracker<LLControlGroup, std::string>(name) {}  LLControlGroup::~LLControlGroup() {} -BOOL LLControlGroup::declareString(const std::string& name, +LLControlVariable* LLControlGroup::declareString(const std::string& name,                                     const std::string& initial_val,                                     const std::string& comment, -                                   BOOL persist) {return TRUE;} +                                   LLControlVariable::ePersist persist) {return NULL;}  void LLControlGroup::setString(const std::string& name, const std::string& val){}  std::string LLControlGroup::getString(const std::string& name)  { diff --git a/indra/newview/tests/llsechandler_basic_test.cpp b/indra/newview/tests/llsechandler_basic_test.cpp index 0235400976..2a8dc15346 100755 --- a/indra/newview/tests/llsechandler_basic_test.cpp +++ b/indra/newview/tests/llsechandler_basic_test.cpp @@ -71,10 +71,10 @@ std::string gLastName;  LLControlGroup::LLControlGroup(const std::string& name)  : LLInstanceTracker<LLControlGroup, std::string>(name) {}  LLControlGroup::~LLControlGroup() {} -BOOL LLControlGroup::declareString(const std::string& name, +LLControlVariable* LLControlGroup::declareString(const std::string& name,                                     const std::string& initial_val,                                     const std::string& comment, -                                   BOOL persist) {return TRUE;} +                                   LLControlVariable::ePersist persist) {return NULL;}  void LLControlGroup::setString(const std::string& name, const std::string& val){}  std::string LLControlGroup::getString(const std::string& name)  { diff --git a/indra/newview/tests/llslurl_test.cpp b/indra/newview/tests/llslurl_test.cpp index 09343ef227..86229ad636 100755 --- a/indra/newview/tests/llslurl_test.cpp +++ b/indra/newview/tests/llslurl_test.cpp @@ -37,10 +37,10 @@  LLControlGroup::LLControlGroup(const std::string& name)  : LLInstanceTracker<LLControlGroup, std::string>(name) {}  LLControlGroup::~LLControlGroup() {} -BOOL LLControlGroup::declareString(const std::string& name, +LLControlVariable* LLControlGroup::declareString(const std::string& name,                                     const std::string& initial_val,                                     const std::string& comment, -                                   BOOL persist) {return TRUE;} +                                   LLControlVariable::ePersist persist) {return NULL;}  void LLControlGroup::setString(const std::string& name, const std::string& val){}  std::string gCmdLineLoginURI; diff --git a/indra/newview/tests/llviewerhelputil_test.cpp b/indra/newview/tests/llviewerhelputil_test.cpp index 710881d811..f6456a2839 100755 --- a/indra/newview/tests/llviewerhelputil_test.cpp +++ b/indra/newview/tests/llviewerhelputil_test.cpp @@ -49,10 +49,10 @@ static std::string gOS;  LLControlGroup::LLControlGroup(const std::string& name)  	: LLInstanceTracker<LLControlGroup, std::string>(name) {}  LLControlGroup::~LLControlGroup() {} -BOOL LLControlGroup::declareString(const std::string& name, +LLControlVariable* LLControlGroup::declareString(const std::string& name,  				   const std::string& initial_val,  				   const std::string& comment, -				   BOOL persist) {return TRUE;} +				   LLControlVariable::ePersist persist) {return NULL;}  void LLControlGroup::setString(const std::string& name, const std::string& val){}  std::string LLControlGroup::getString(const std::string& name)  { diff --git a/indra/newview/tests/llviewernetwork_test.cpp b/indra/newview/tests/llviewernetwork_test.cpp index a1e97ea17e..7ad7947ca4 100755 --- a/indra/newview/tests/llviewernetwork_test.cpp +++ b/indra/newview/tests/llviewernetwork_test.cpp @@ -37,10 +37,10 @@  LLControlGroup::LLControlGroup(const std::string& name)  : LLInstanceTracker<LLControlGroup, std::string>(name) {}  LLControlGroup::~LLControlGroup() {} -BOOL LLControlGroup::declareString(const std::string& name, +LLControlVariable* LLControlGroup::declareString(const std::string& name,                                     const std::string& initial_val,                                     const std::string& comment, -                                   BOOL persist) {return TRUE;} +                                   LLControlVariable::ePersist persist) {return NULL;}  void LLControlGroup::setString(const std::string& name, const std::string& val){}  std::string gCmdLineLoginURI; @@ -127,6 +127,7 @@ const char *gSampleGridFile =  	"      <array>"  	"        <string>myloginuri</string>"  	"      </array>" +	"      <key>update_query_url_base</key><string>https://update.secondlife.com/update</string>"  	"      <key>keyname</key><string>util.foobar.lindenlab.com</string>"  	"    </map>"  	"  </map>" @@ -185,6 +186,9 @@ namespace tut  		ensure_equals("id for agni",  					  std::string("Agni"),  					  LLGridManager::getInstance()->getGridId("util.agni.lindenlab.com")); +		ensure_equals("update url base for Agni", // relies on agni being the default +					  std::string("https://update.secondlife.com/update"), +					  LLGridManager::getInstance()->getUpdateServiceURL());  		ensure_equals("label for agni",  					  LLGridManager::getInstance()->getGridLabel("util.agni.lindenlab.com"),  					  std::string("Second Life Main Grid (Agni)")); @@ -256,6 +260,9 @@ namespace tut  		ensure_equals("id for agni",  					  LLGridManager::getInstance()->getGridId("util.agni.lindenlab.com"),  					  std::string("Agni")); +		ensure_equals("update url base for Agni", // relies on agni being the default +					  std::string("https://update.secondlife.com/update"), +					  LLGridManager::getInstance()->getUpdateServiceURL());  		ensure_equals("label for agni",  					  LLGridManager::getInstance()->getGridLabel("util.agni.lindenlab.com"),  					  std::string("Second Life Main Grid (Agni)")); @@ -384,6 +391,9 @@ namespace tut  		ensure_equals("getLoginPage",  					  LLGridManager::getInstance()->getLoginPage(),  					  std::string("http://viewer-login.agni.lindenlab.com/")); +		ensure_equals("update url base for Agni", // relies on agni being the default +					  std::string("https://update.secondlife.com/update"), +					  LLGridManager::getInstance()->getUpdateServiceURL());  		ensure("Is Agni a production grid", LLGridManager::getInstance()->isInProductionGrid());  		std::vector<std::string> uris;  		LLGridManager::getInstance()->getLoginURIs(uris); diff --git a/indra/newview/tests/llxmlrpclistener_test.cpp b/indra/newview/tests/llxmlrpclistener_test.cpp index 711c2a3d51..20f913b670 100755 --- a/indra/newview/tests/llxmlrpclistener_test.cpp +++ b/indra/newview/tests/llxmlrpclistener_test.cpp @@ -62,8 +62,8 @@ namespace tut              // These variables are required by machinery used by              // LLXMLRPCTransaction. The values reflect reality for this test              // executable; hopefully these values are correct. -            gSavedSettings.declareBOOL("BrowserProxyEnabled", FALSE, "", FALSE); // don't persist -            gSavedSettings.declareBOOL("NoVerifySSLCert", TRUE, "", FALSE); // don't persist +            gSavedSettings.declareBOOL("BrowserProxyEnabled", FALSE, "", LLControlVariable::PERSIST_NO); // don't persist +            gSavedSettings.declareBOOL("NoVerifySSLCert", TRUE, "", LLControlVariable::PERSIST_NO); // don't persist          }          // LLEventPump listener signature diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 5e08e54b7c..19863dd845 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -34,9 +34,15 @@ import tarfile  import time  import random  viewer_dir = os.path.dirname(__file__) -# add llmanifest library to our path so we don't have to muck with PYTHONPATH -sys.path.append(os.path.join(viewer_dir, '../lib/python/indra/util')) -from llmanifest import LLManifest, main, proper_windows_path, path_ancestors +# Add indra/lib/python to our path so we don't have to muck with PYTHONPATH. +# Put it FIRST because some of our build hosts have an ancient install of +# indra.util.llmanifest under their system Python! +sys.path.insert(0, os.path.join(viewer_dir, os.pardir, "lib", "python")) +from indra.util.llmanifest import LLManifest, main, proper_windows_path, path_ancestors +try: +    from llbase import llsd +except ImportError: +    from indra.base import llsd  class ViewerManifest(LLManifest):      def is_packaging_viewer(self): @@ -65,13 +71,13 @@ class ViewerManifest(LLManifest):                  # include the entire shaders directory recursively                  self.path("shaders")                  # include the extracted list of contributors -                contributor_names = self.extract_names("../../doc/contributions.txt") -                self.put_in_file(contributor_names, "contributors.txt") -                self.file_list.append(["../../doc/contributions.txt",self.dst_path_of("contributors.txt")]) +                contributions_path = "../../doc/contributions.txt" +                contributor_names = self.extract_names(contributions_path) +                self.put_in_file(contributor_names, "contributors.txt", src=contributions_path)                  # include the extracted list of translators -                translator_names = self.extract_names("../../doc/translations.txt") -                self.put_in_file(translator_names, "translators.txt") -                self.file_list.append(["../../doc/translations.txt",self.dst_path_of("translators.txt")]) +                translations_path = "../../doc/translations.txt" +                translator_names = self.extract_names(translations_path) +                self.put_in_file(translator_names, "translators.txt", src=translations_path)                  # include the list of Lindens (if any)                  #   see https://wiki.lindenlab.com/wiki/Generated_Linden_Credits                  linden_names_path = os.getenv("LINDEN_CREDITS") @@ -85,10 +91,9 @@ class ViewerManifest(LLManifest):                      else:                           # all names should be one line, but the join below also converts to a string                          linden_names = ', '.join(linden_file.readlines()) -                        self.put_in_file(linden_names, "lindens.txt") +                        self.put_in_file(linden_names, "lindens.txt", src=linden_names_path)                          linden_file.close()                          print "Linden names extracted from '%s'" % linden_names_path -                        self.file_list.append([linden_names_path,self.dst_path_of("lindens.txt")])                  # ... and the entire windlight directory                  self.path("windlight") @@ -99,6 +104,27 @@ class ViewerManifest(LLManifest):                      self.path("dictionaries")                      self.end_prefix(pkgdir) +                # CHOP-955: If we have "sourceid" in the build process +                # environment, generate it into settings_install.xml. +                try: +                    sourceid = os.environ["sourceid"] +                except KeyError: +                    # no sourceid, no settings_install.xml file +                    pass +                else: +                    if sourceid: +                        # Single-entry subset of the LLSD content of settings.xml +                        content = dict(sourceid=dict(Comment='Identify referring agency to Linden web servers', +                                                     Persist=1, +                                                     Type='String', +                                                     Value=sourceid)) +                        # put_in_file(src=) need not be an actual pathname; it +                        # only needs to be non-empty +                        settings_install = self.put_in_file(llsd.format_pretty_xml(content), +                                                            "settings_install.xml", +                                                            src="environment") +                        print "Put sourceid '%s' in %s" % (sourceid, settings_install) +                  self.end_prefix("app_settings")              if self.prefix(src="character"): @@ -196,24 +222,26 @@ class ViewerManifest(LLManifest):          """ Convenience function that returns the command-line flags          for the grid""" -        # Set command line flags relating to the target grid -        grid_flags = '' -        if not self.default_grid(): -            grid_flags = "--grid %(grid)s "\ -                         "--helperuri http://preview-%(grid)s.secondlife.com/helpers/" %\ -                           {'grid':self.grid()} - -        # Deal with settings  -        setting_flags = '' -        if not self.default_channel() or not self.default_grid(): -            if self.default_grid(): -                setting_flags = '--settings settings_%s.xml'\ -                                % self.channel_lowerword() -            else: -                setting_flags = '--settings settings_%s_%s.xml'\ -                                % (self.grid(), self.channel_lowerword()) -                                                 -        return " ".join((grid_flags, setting_flags)).strip() +        # The original role of this method seems to have been to build a +        # grid-specific viewer: one that would, on launch, preselect a +        # particular grid. (Apparently that dates back to when the protocol +        # between viewer and simulator required them to be updated in +        # lockstep, so that "the beta grid" required "a beta viewer.") But +        # those viewer command-line switches no longer work without tweaking +        # user_settings/grids.xml. In fact, going forward, it's unclear what +        # use case that would address. + +        # This method also set a channel-specific (or grid-and-channel- +        # specific) user_settings/settings_something.xml file. It has become +        # clear that saving user settings in a channel-specific file causes +        # more problems (confusion) than it solves, so we've discontinued that. + +        # In fact we now avoid forcing viewer command-line switches at all, +        # instead introducing a settings_install.xml file. Command-line +        # switches don't aggregate well; for instance the generated --channel +        # switch actually prevented the user specifying --channel on the +        # command line. Settings files have well-defined override semantics. +        return None      def extract_names(self,src):          try: @@ -530,8 +558,7 @@ class WindowsManifest(ViewerManifest):              'final_exe' : self.final_exe(),              'grid':self.args['grid'],              'grid_caps':self.args['grid'].upper(), -            # escape quotes becase NSIS doesn't handle them well -            'flags':self.flags_list().replace('"', '$\\"'), +            'flags':'',              'channel':self.channel(),              'channel_oneword':self.channel_oneword(),              'channel_unique':self.channel_unique(), @@ -759,9 +786,6 @@ class DarwinManifest(ViewerManifest):                      self.end_prefix("llplugin") -                # command line arguments for connecting to the proper grid -                self.put_in_file(self.flags_list(), 'arguments.txt') -                  self.end_prefix("Resources")              self.end_prefix("Contents") @@ -807,10 +831,6 @@ class DarwinManifest(ViewerManifest):                                   'bundle': self.get_dst_prefix()                  }) -        channel_standin = 'Second Life Viewer'  # hah, our default channel is not usable on its own -        if not self.default_channel(): -            channel_standin = self.channel() -          imagename="SecondLife_" + '_'.join(self.args['version'])          # MBW -- If the mounted volume name changes, it breaks the .DS_Store's background image and icon positioning. @@ -928,9 +948,6 @@ class LinuxManifest(ViewerManifest):              self.path("install.sh")              self.end_prefix("linux_tools") -        # Create an appropriate gridargs.dat for this package, denoting required grid. -        self.put_in_file(self.flags_list(), 'etc/gridargs.dat') -          if self.prefix(src="", dst="bin"):              self.path("secondlife-bin","do-not-directly-run-secondlife-bin")              self.path("../linux_crash_logger/linux-crash-logger","linux-crash-logger.bin") diff --git a/indra/viewer_components/updater/llupdatechecker.cpp b/indra/viewer_components/updater/llupdatechecker.cpp index 0b105cc1b6..3e170e44f4 100755 --- a/indra/viewer_components/updater/llupdatechecker.cpp +++ b/indra/viewer_components/updater/llupdatechecker.cpp @@ -62,8 +62,7 @@ LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client):  } -void LLUpdateChecker::checkVersion(std::string const & hostUrl,  -								   std::string const & servicePath, +void LLUpdateChecker::checkVersion(std::string const & urlBase,   								   std::string const & channel,  								   std::string const & version,  								   std::string const & platform, @@ -71,7 +70,7 @@ void LLUpdateChecker::checkVersion(std::string const & hostUrl,  								   unsigned char       uniqueid[MD5HEX_STR_SIZE],  								   bool                willing_to_test)  { -	mImplementation->checkVersion(hostUrl, servicePath, channel, version, platform, platform_version, uniqueid, willing_to_test); +	mImplementation->checkVersion(urlBase, channel, version, platform, platform_version, uniqueid, willing_to_test);  } @@ -98,8 +97,7 @@ LLUpdateChecker::Implementation::~Implementation()  } -void LLUpdateChecker::Implementation::checkVersion(std::string const & hostUrl,  -												   std::string const & servicePath, +void LLUpdateChecker::Implementation::checkVersion(std::string const & urlBase,   												   std::string const & channel,  												   std::string const & version,  												   std::string const & platform, @@ -111,8 +109,7 @@ void LLUpdateChecker::Implementation::checkVersion(std::string const & hostUrl,  	{  		mInProgress = true; -		mHostUrl     	 = hostUrl; -		mServicePath 	 = servicePath; +		mUrlBase     	 = urlBase;  		mChannel     	 = channel;  		mVersion     	 = version;  		mPlatform        = platform; @@ -122,7 +119,7 @@ void LLUpdateChecker::Implementation::checkVersion(std::string const & hostUrl,  		mProtocol = sProtocolVersion; -		std::string checkUrl = buildUrl(hostUrl, servicePath, channel, version, platform, platform_version, uniqueid, willing_to_test); +		std::string checkUrl = buildUrl(urlBase, channel, version, platform, platform_version, uniqueid, willing_to_test);  		LL_INFOS("UpdaterService") << "checking for updates at " << checkUrl << LL_ENDL;  		mHttpClient.get(checkUrl, this); @@ -152,11 +149,40 @@ void LLUpdateChecker::Implementation::completed(U32 status,  			server_error += content["error_text"].asString();  		} -		LL_WARNS("UpdaterService") << "response error " << status -								   << " " << reason -								   << " (" << server_error << ")" -								   << LL_ENDL; -		mClient.error(reason); +		if (status == 404) +		{ +			if (mProtocol == sProtocolVersion) +			{ +				mProtocol = sLegacyProtocolVersion; +				std::string retryUrl = buildUrl(mUrlBase, mChannel, mVersion, mPlatform, mPlatformVersion, mUniqueId, mWillingToTest); + +				LL_WARNS("UpdaterService") +					<< "update response using " << sProtocolVersion +					<< " was HTTP 404 (" << server_error +					<< "); retry with legacy protocol " << mProtocol +					<< "\n at " << retryUrl +					<< LL_ENDL; +	 +				mHttpClient.get(retryUrl, this); +			} +			else +			{ +				LL_WARNS("UpdaterService") +					<< "update response using " << sLegacyProtocolVersion +					<< " was 404 (" << server_error +					<< "); request failed" +					<< LL_ENDL; +				mClient.error(reason); +			} +		} +		else +		{ +			LL_WARNS("UpdaterService") << "response error " << status +									   << " " << reason +									   << " (" << server_error << ")" +									   << LL_ENDL; +			mClient.error(reason); +		}  	}  	else  	{ @@ -173,8 +199,7 @@ void LLUpdateChecker::Implementation::error(U32 status, const std::string & reas  } -std::string LLUpdateChecker::Implementation::buildUrl(std::string const & hostUrl,  -													  std::string const & servicePath, +std::string LLUpdateChecker::Implementation::buildUrl(std::string const & urlBase,   													  std::string const & channel,  													  std::string const & version,  													  std::string const & platform, @@ -183,7 +208,6 @@ std::string LLUpdateChecker::Implementation::buildUrl(std::string const & hostUr  													  bool                willing_to_test)  {	  	LLSD path; -	path.append(servicePath);  	path.append(mProtocol);  	path.append(channel);  	path.append(version); @@ -191,5 +215,5 @@ std::string LLUpdateChecker::Implementation::buildUrl(std::string const & hostUr  	path.append(platform_version);  	path.append(willing_to_test ? "testok" : "testno");  	path.append((char*)uniqueid); -	return LLURI::buildHTTP(hostUrl, path).asString(); +	return LLURI::buildHTTP(urlBase, path).asString();  } diff --git a/indra/viewer_components/updater/llupdatechecker.h b/indra/viewer_components/updater/llupdatechecker.h index 8e85587490..4244007340 100755 --- a/indra/viewer_components/updater/llupdatechecker.h +++ b/indra/viewer_components/updater/llupdatechecker.h @@ -43,8 +43,7 @@ public:  	public:  		Implementation(Client & client);  		~Implementation(); -		void checkVersion(std::string const & hostUrl,  -						  std::string const & servicePath, +		void checkVersion(std::string const & urlBase,   						  std::string const & channel,  						  std::string const & version,  						  std::string const & platform, @@ -68,16 +67,14 @@ public:  		LLHTTPClient mHttpClient;  		bool         mInProgress;  		std::string   mVersion; -		std::string   mHostUrl; -		std::string   mServicePath; +		std::string   mUrlBase;  		std::string   mChannel;  		std::string   mPlatform;  		std::string   mPlatformVersion;  		unsigned char mUniqueId[MD5HEX_STR_SIZE];  		bool          mWillingToTest; -		std::string buildUrl(std::string const & hostUrl,  -							 std::string const & servicePath, +		std::string buildUrl(std::string const & urlBase,   							 std::string const & channel,  							 std::string const & version,  							 std::string const & platform, @@ -95,8 +92,7 @@ public:  	LLUpdateChecker(Client & client);  	// Check status of current app on the given host for the channel and version provided. -	void checkVersion(std::string const & hostUrl,  -					  std::string const & servicePath, +	void checkVersion(std::string const & urlBase,   					  std::string const & channel,  					  std::string const & version,  					  std::string const & platform, diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp index 1bd9fa4fc0..16950e1d62 100755 --- a/indra/viewer_components/updater/llupdaterservice.cpp +++ b/indra/viewer_components/updater/llupdaterservice.cpp @@ -38,6 +38,7 @@  #include "lldir.h"  #include "llsdserialize.h"  #include "llfile.h" +#include "llviewernetwork.h"  #if LL_WINDOWS  #pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally @@ -93,8 +94,6 @@ class LLUpdaterServiceImpl :  	static const std::string sListenerName;  	std::string   mProtocolVersion; -	std::string   mUrl; -	std::string   mPath;  	std::string   mChannel;  	std::string   mVersion;  	std::string   mPlatform; @@ -120,9 +119,7 @@ public:  	LLUpdaterServiceImpl();  	virtual ~LLUpdaterServiceImpl(); -	void initialize(const std::string& 	url,  -					const std::string& 	path, -					const std::string& 	channel, +	void initialize(const std::string& 	channel,  					const std::string& 	version,  					const std::string&  platform,  					const std::string&  platform_version, @@ -183,9 +180,7 @@ LLUpdaterServiceImpl::~LLUpdaterServiceImpl()  	LLEventPumps::instance().obtain("mainloop").stopListening(sListenerName);  } -void LLUpdaterServiceImpl::initialize(const std::string&  url,  -									  const std::string&  path, -									  const std::string&  channel, +void LLUpdaterServiceImpl::initialize(const std::string&  channel,  									  const std::string&  version,  									  const std::string&  platform,  									  const std::string&  platform_version, @@ -198,8 +193,6 @@ void LLUpdaterServiceImpl::initialize(const std::string&  url,  										   "while updater is running.");  	} -	mUrl = url; -	mPath = path;  	mChannel = channel;  	mVersion = version;  	mPlatform = platform; @@ -207,8 +200,6 @@ void LLUpdaterServiceImpl::initialize(const std::string&  url,  	memcpy(mUniqueId, uniqueid, MD5HEX_STR_SIZE);  	mWillingToTest = willing_to_test;  	LL_DEBUGS("UpdaterService") -		<< "\n  url: " << mUrl -		<< "\n  path: " << mPath  		<< "\n  channel: " << mChannel  		<< "\n  version: " << mVersion  		<< "\n  uniqueid: " << mUniqueId @@ -228,7 +219,7 @@ void LLUpdaterServiceImpl::setBandwidthLimit(U64 bytesPerSecond)  void LLUpdaterServiceImpl::startChecking(bool install_if_ready)  { -	if(mUrl.empty() || mChannel.empty() || mVersion.empty()) +	if(mChannel.empty() || mVersion.empty())  	{  		throw LLUpdaterService::UsageError("Set params before call to "  			"LLUpdaterService::startCheck()."); @@ -415,7 +406,7 @@ void LLUpdaterServiceImpl::response(LLSD const & content)  		setState(LLUpdaterService::UP_TO_DATE);  	} -	else +	else if ( content.isMap() && content.has("url") )  	{  		// there is an update available...  		stopTimer(); @@ -439,6 +430,12 @@ void LLUpdaterServiceImpl::response(LLSD const & content)  			<< LL_ENDL;  		mUpdateDownloader.download(url, content["hash"].asString(), mNewChannel, mNewVersion, more_info, required);  	} +	else +	{ +		LL_WARNS("UpdaterService") << "Invalid update query response ignored; retry in " +								   << mCheckPeriod << " seconds" << LL_ENDL; +		restartTimer(mCheckPeriod); +	}  }  void LLUpdaterServiceImpl::downloadComplete(LLSD const & data)  @@ -565,8 +562,26 @@ bool LLUpdaterServiceImpl::onMainLoop(LLSD const & event)  		}  		else  		{ -			mUpdateChecker.checkVersion(mUrl, mPath, mChannel, mVersion, mPlatform, mPlatformVersion, mUniqueId, mWillingToTest); -			setState(LLUpdaterService::CHECKING_FOR_UPDATE); +			std::string query_url = LLGridManager::getInstance()->getUpdateServiceURL(); +			if ( !query_url.empty() ) +			{ +				mUpdateChecker.checkVersion(query_url, mChannel, mVersion, +											mPlatform, mPlatformVersion, mUniqueId, +											mWillingToTest); +				setState(LLUpdaterService::CHECKING_FOR_UPDATE); +			} +			else +			{ +				LL_WARNS("UpdaterService") +					<< "No updater service defined for grid '" << LLGridManager::getInstance()->getGrid() +					<< "' will check again in " << mCheckPeriod << " seconds" +					<< LL_ENDL; +				// Because the grid can be changed after the viewer is started (when the first check takes place) +				// but before the user logs in, the next check may be on a different grid, so set the retry timer +				// even though this check did not happen.  The default time is once an hour, and if we're not +				// doing the check anyway the performance impact is completely insignificant. +				restartTimer(mCheckPeriod); +			}  		}  	}   	else  @@ -610,9 +625,7 @@ LLUpdaterService::~LLUpdaterService()  {  } -void LLUpdaterService::initialize(const std::string& url,  -								  const std::string& path, -								  const std::string& channel, +void LLUpdaterService::initialize(const std::string& channel,  								  const std::string& version,  								  const std::string& platform,  								  const std::string& platform_version, @@ -620,7 +633,7 @@ void LLUpdaterService::initialize(const std::string& url,  								  const bool&         willing_to_test  )  { -	mImpl->initialize(url, path, channel, version, platform, platform_version, uniqueid, willing_to_test); +	mImpl->initialize(channel, version, platform, platform_version, uniqueid, willing_to_test);  }  void LLUpdaterService::setCheckPeriod(unsigned int seconds) diff --git a/indra/viewer_components/updater/llupdaterservice.h b/indra/viewer_components/updater/llupdaterservice.h index 982f99b861..0ddf24935b 100755 --- a/indra/viewer_components/updater/llupdaterservice.h +++ b/indra/viewer_components/updater/llupdaterservice.h @@ -71,9 +71,7 @@ public:  	LLUpdaterService();  	~LLUpdaterService(); -	void initialize(const std::string& 	url,  -				    const std::string& 	path, -				    const std::string& 	channel, +	void initialize(const std::string& 	channel,  				    const std::string& 	version,  					const std::string&  platform,  					const std::string&  platform_version, diff --git a/indra/viewer_components/updater/scripts/linux/update_install b/indra/viewer_components/updater/scripts/linux/update_install index a9df9042fd..03089f192e 100755 --- a/indra/viewer_components/updater/scripts/linux/update_install +++ b/indra/viewer_components/updater/scripts/linux/update_install @@ -69,8 +69,11 @@ then # zenity on PATH and is executable           # clear any previous message           clear_message           # put up a new zenity box and capture its pid -         "$zenpath" --info --title "Second Life Viewer Updater" \ -                    --width=320 --height=120 --text="$*" & +##       "$zenpath" --info --title "Second Life Viewer Updater" \ +##                  --width=320 --height=120 --text="$*" & +         # MAINT-2333: use bouncing progress bar +         "$zenpath" --progress --pulsate --no-cancel --title "Second Life Viewer Updater" \ +                    --width=320 --height=120 --text "$*" </dev/null &           statuspid=$!       } diff --git a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp index 4812272ebc..759e41ef4c 100755 --- a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp +++ b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp @@ -44,8 +44,7 @@  *****************************************************************************/  LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client)  {} -void LLUpdateChecker::checkVersion(std::string const & hostUrl,  -								   std::string const & servicePath, +void LLUpdateChecker::checkVersion(std::string const & urlBase,   								   std::string const & channel,  								   std::string const & version,  								   std::string const & platform, @@ -91,6 +90,21 @@ bool LLDir::setCacheDir(const std::string &path){ return true; }  void LLDir::dumpCurrentDirectories() {}  void LLDir::updatePerAccountChatLogsDir() {} +#include "llviewernetwork.h" +LLGridManager::LLGridManager() : +	mGrid("test.grid.lindenlab.com"), +	mIsInProductionGrid(false) +{ +} +std::string LLGridManager::getUpdateServiceURL() +{ +	return "https://update.secondlife.com/update"; +} +LLGridManager::~LLGridManager() +{ +} + +  std::string LLDir::getExpandedFilename(ELLPath location,   									   const std::string &filename) const   { @@ -179,10 +193,10 @@ namespace tut  		try  		{  			unsigned char id1[MD5HEX_STR_SIZE] = "11111111111111111111111111111111"; -			updater.initialize(test_url, "update" ,test_channel, test_version, "win", "1.2.3", id1, true); +			updater.initialize(test_channel, test_version, "win", "1.2.3", id1, true);  			updater.startChecking();  			unsigned char id2[MD5HEX_STR_SIZE] = "22222222222222222222222222222222"; -			updater.initialize("other_url", "update", test_channel, test_version, "win", "4.5.6", id2, true); +			updater.initialize(test_channel, test_version, "win", "4.5.6", id2, true);  		}  		catch(LLUpdaterService::UsageError)  		{ @@ -197,7 +211,7 @@ namespace tut          DEBUG;  		LLUpdaterService updater;  		unsigned char id[MD5HEX_STR_SIZE] = "33333333333333333333333333333333"; -		updater.initialize(test_url, "update", test_channel, test_version, "win", "7.8.9", id, true); +		updater.initialize(test_channel, test_version, "win", "7.8.9", id, true);  		updater.startChecking();  		ensure(updater.isChecking());  		updater.stopChecking(); | 
