Skip to content
Snippets Groups Projects
llfloaterpreference.cpp 116 KiB
Newer Older
  • Learn to ignore specific revisions
  • James Cook's avatar
    James Cook committed
    /** 
     * @file llfloaterpreference.cpp
    
     * @brief Global preferences with and without persistence.
    
    James Cook's avatar
    James Cook committed
     *
    
     * $LicenseInfo:firstyear=2002&license=viewerlgpl$
    
     * Second Life Viewer Source Code
    
     * Copyright (C) 2010, 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$
    
    James Cook's avatar
    James Cook committed
     */
    
    /*
     * App-wide preferences.  Note that these are not per-user,
     * because we need to load many preferences before we have
     * a login name.
     */
    
    #include "llviewerprecompiledheaders.h"
    
    #include "llfloaterpreference.h"
    
    #include "message.h"
    
    #include "llcheckboxctrl.h"
    
    #include "lldirpicker.h"
    
    #include "llfeaturemanager.h"
    #include "llfocusmgr.h"
    
    #include "llfloaterreg.h"
    
    James Cook's avatar
    James Cook committed
    #include "llfloaterabout.h"
    
    #include "llfloatersidepanelcontainer.h"
    
    #include "llkeyboard.h"
    #include "llmodaldialog.h"
    
    #include "llnotificationtemplate.h"
    
    #include "llpanelvoicedevicesettings.h"
    
    #include "llradiogroup.h"
    
    Steven Bennetts's avatar
    Steven Bennetts committed
    #include "llsearchcombobox.h"
    
    #include "llscrolllistctrl.h"
    #include "llscrolllistitem.h"
    #include "llsliderctrl.h"
    #include "lltabcontainer.h"
    
    James Cook's avatar
    James Cook committed
    #include "llviewercontrol.h"
    
    #include "llviewercamera.h"
    
    #include "llviewereventrecorder.h"
    
    #include "llviewermessage.h"
    
    #include "llviewerwindow.h"
    
    #include "llviewershadermgr.h"
    
    #include "llvotree.h"
    #include "llvosky.h"
    
    // linden library includes
    
    #include "llavatarnamecache.h"
    
    #include "llerror.h"
    #include "llfontgl.h"
    #include "llrect.h"
    #include "llstring.h"
    
    // project includes
    
    #include "llbutton.h"
    #include "llflexibleobject.h"
    #include "lllineeditor.h"
    #include "llresmgr.h"
    #include "llspinctrl.h"
    #include "llstartup.h"
    #include "lltextbox.h"
    #include "llui.h"
    #include "llviewerobjectlist.h"
    #include "llvoavatar.h"
    #include "llvovolume.h"
    #include "llwindow.h"
    #include "llworld.h"
    #include "pipeline.h"
    #include "lluictrlfactory.h"
    
    #include "llviewermedia.h"
    #include "llpluginclassmedia.h"
    
    Steven Bennetts's avatar
    Steven Bennetts committed
    #include "llteleporthistorystorage.h"
    
    #include "llproxy.h"
    
    #include "lllogininstance.h"        // to check if logged in yet
    
    #include "llpresetsmanager.h"
    
    #include "llviewercontrol.h"
    
    #include "llpresetsmanager.h"
    
    #include "llfeaturemanager.h"
    
    Paul ProductEngine's avatar
    Paul ProductEngine committed
    const F32 BANDWIDTH_UPDATER_TIMEOUT = 0.5f;
    
    char const* const VISIBILITY_DEFAULT = "default";
    char const* const VISIBILITY_HIDDEN = "hidden";
    
    //control value for middle mouse as talk2push button
    
    const static std::string MIDDLE_MOUSE_CV = "MiddleMouse"; // for voice client and redability
    const static std::string MOUSE_BUTTON_4_CV = "MouseButton4";
    const static std::string MOUSE_BUTTON_5_CV = "MouseButton5";
    
    /// This must equal the maximum value set for the IndirectMaxComplexity slider in panel_preferences_graphics1.xml
    static const U32 INDIRECT_MAX_ARC_OFF = 101; // all the way to the right == disabled
    static const U32 MIN_INDIRECT_ARC_LIMIT = 1; // must match minimum of IndirectMaxComplexity in panel_preferences_graphics1.xml
    static const U32 MAX_INDIRECT_ARC_LIMIT = INDIRECT_MAX_ARC_OFF-1; // one short of all the way to the right...
    
    /// These are the effective range of values for RenderAvatarMaxComplexity
    static const F32 MIN_ARC_LIMIT =  20000.0f;
    
    static const F32 MAX_ARC_LIMIT = 350000.0f;
    
    static const F32 MIN_ARC_LOG = log(MIN_ARC_LIMIT);
    static const F32 MAX_ARC_LOG = log(MAX_ARC_LIMIT);
    static const F32 ARC_LIMIT_MAP_SCALE = (MAX_ARC_LOG - MIN_ARC_LOG) / (MAX_INDIRECT_ARC_LIMIT - MIN_INDIRECT_ARC_LIMIT);
    
    
    struct LabelDef : public LLInitParam::Block<LabelDef>
    {
        Mandatory<std::string> name;
        Mandatory<std::string> value;
    
        LabelDef()
            : name("name"),
            value("value")
        {}
    };
    
    struct LabelTable : public LLInitParam::Block<LabelTable>
    {
        Multiple<LabelDef> labels;
        LabelTable()
            : labels("label")
        {}
    };
    
    
    // Filters for LLSetKeyBindDialog
    static const U32 ALLOW_MOUSE = 1;
    static const U32 ALLOW_MASK_MOUSE = 2;
    static const U32 ALLOW_KEYS = 4; //keyboard
    static const U32 ALLOW_MASK_KEYS = 8;
    static const U32 ALLOW_MASKS = 16;
    
    static const U32 CAN_IGNORE_MASKS = 32; // For example W (aka Forward) should work regardless of SHIFT being pressed
    
    static const U32 DEFAULT_KEY_FILTER = ALLOW_MOUSE | ALLOW_MASK_MOUSE | ALLOW_KEYS | ALLOW_MASK_KEYS | CAN_IGNORE_MASKS;
    
    
    class LLSetKeyBindDialog : public LLModalDialog
    
    	LLSetKeyBindDialog(const LLSD& key);
    	~LLSetKeyBindDialog();
    
    
    	/*virtual*/ BOOL postBuild();
    
    	/*virtual*/ void onClose(bool app_quiting);
    
    
    	void setParent(LLPanelPreferenceControls* parent, U32 key_mask = DEFAULT_KEY_FILTER);
    
    
    	BOOL handleKeyHere(KEY key, MASK mask);
    
    	BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down);
    
    	static void onCancel(void* user_data);
    
    	static void onBlank(void* user_data);
    	static void onDefault(void* user_data);
    
    
    	LLPanelPreferenceControls* pParent;
    	LLCheckBoxCtrl* pCheckBox;
    
    LLSetKeyBindDialog::LLSetKeyBindDialog(const LLSD& key)
    
    	pParent(NULL),
    
    	mKeyMask(DEFAULT_KEY_FILTER)
    
    LLSetKeyBindDialog::~LLSetKeyBindDialog()
    {
    }
    
    
    BOOL LLSetKeyBindDialog::postBuild()
    
    James Cook's avatar
    James Cook committed
    {
    
    	childSetAction("SetEmpty", onBlank, this);
    	childSetAction("Default", onDefault, this);
    
    	childSetAction("Cancel", onCancel, this);
    	getChild<LLUICtrl>("Cancel")->setFocus(TRUE);
    
    
    	pCheckBox = getChild<LLCheckBoxCtrl>("ignore_masks");
    
    
    	gFocusMgr.setKeystrokesOnly(TRUE);
    	
    	return TRUE;
    
    //virtual
    void LLSetKeyBindDialog::onClose(bool app_quiting)
    {
        pParent = NULL;
        LLModalDialog::onClose(app_quiting);
    }
    
    
    void LLSetKeyBindDialog::setParent(LLPanelPreferenceControls* parent, U32 key_mask)
    {
    
        pParent = parent;
    
        mKeyMask = key_mask;
    
        LLTextBase *text_ctrl = getChild<LLTextBase>("descritption");
    
        std::string input;
        if ((key_mask & ALLOW_MOUSE) != 0)
        {
            input = getString("mouse");
        }
        if ((key_mask & ALLOW_KEYS) != 0)
        {
            if (!input.empty())
            {
                input += ", ";
            }
            input += getString("keyboard");
        }
        text_ctrl->setTextArg("[INPUT]", input);
    
    
        bool can_ignore_masks = (key_mask & CAN_IGNORE_MASKS) != 0;
        pCheckBox->setVisible(can_ignore_masks);
        pCheckBox->setValue(false);
    
    BOOL LLSetKeyBindDialog::handleKeyHere(KEY key, MASK mask)
    
    James Cook's avatar
    James Cook committed
    {
    
    	BOOL result = TRUE;
    
        if ((key == 'Q' && mask == MASK_CONTROL)
            || key == KEY_ESCAPE)
        {
            closeFloater();
            return true;
        }
    
    
        if (key == KEY_DELETE)
        {
            if (pParent)
            {
                pParent->onSetKeyBind(CLICK_NONE, KEY_NONE, MASK_NONE, false);
            }
            closeFloater();
            return true;
        }
    
    
        // forbidden keys
        if (key == KEY_NONE
            || key == KEY_RETURN
            || key == KEY_BACKSPACE)
    
    andreykproductengine's avatar
    andreykproductengine committed
        {
            return false;
        }
    
    
        if ((mKeyMask & ALLOW_MASKS) == 0
            && (key == KEY_CONTROL || key == KEY_SHIFT || key == KEY_ALT))
        {
            // mask by themself are not allowed
            return false;
        }
        else if ((mKeyMask & ALLOW_KEYS) == 0)
        {
            // basic keys not allowed
            return false;
        }
        else if ((mKeyMask & ALLOW_MASK_KEYS) == 0 && mask != 0)
        {
            // masked keys not allowed
            return false;
    
    	if (pParent)
    
            pParent->onSetKeyBind(CLICK_NONE, key, mask, pCheckBox->getValue().asBoolean());
    
    	closeFloater();
    	return result;
    
    James Cook's avatar
    James Cook committed
    
    
    BOOL LLSetKeyBindDialog::handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down)
    
    andreykproductengine's avatar
    andreykproductengine committed
    
        if (clicktype == CLICK_LEFT)
        {
    
            // try handling buttons first
    
    andreykproductengine's avatar
    andreykproductengine committed
            if (down)
            {
                result = LLView::handleMouseDown(x, y, mask);
            }
            else
            {
                result = LLView::handleMouseUp(x, y, mask);
            }
        }
    
    
        if (!result
            && ((mKeyMask & ALLOW_MOUSE) != 0)
            && (clicktype != CLICK_RIGHT || mask != 0) // reassigning menu button is not supported
            && ((mKeyMask & ALLOW_MASK_MOUSE) != 0 || mask == 0))
    
            if (pParent)
    
                pParent->onSetKeyBind(clicktype, KEY_NONE, mask, pCheckBox->getValue().asBoolean());
    
        {
            result = LLMouseHandler::handleAnyMouseClick(x, y, mask, clicktype, down);
        }
    
        return result;
    }
    
    
    void LLSetKeyBindDialog::onCancel(void* user_data)
    
        LLSetKeyBindDialog* self = (LLSetKeyBindDialog*)user_data;
    
    	self->closeFloater();
    
    James Cook's avatar
    James Cook committed
    
    
    //static
    void LLSetKeyBindDialog::onBlank(void* user_data)
    {
        LLSetKeyBindDialog* self = (LLSetKeyBindDialog*)user_data;
        // tmp needs 'no key' button
    
        if (self->pParent)
    
            self->pParent->onSetKeyBind(CLICK_NONE, KEY_NONE, MASK_NONE, false);
    
        }
        self->closeFloater();
    }
    
    //static
    void LLSetKeyBindDialog::onDefault(void* user_data)
    {
        LLSetKeyBindDialog* self = (LLSetKeyBindDialog*)user_data;
        // tmp needs 'no key' button
    
        if (self->pParent)
    
            self->pParent->onDefaultKeyBind();
    
    James Cook's avatar
    James Cook committed
    
    
    // helper functions for getting/freeing the web browser media
    // if creating/destroying these is too slow, we'll need to create
    // a static member and update all our static callbacks
    
    James Cook's avatar
    James Cook committed
    
    
    void handleNameTagOptionChanged(const LLSD& newvalue);	
    void handleDisplayNamesOptionChanged(const LLSD& newvalue);	
    
    bool callback_clear_browser_cache(const LLSD& notification, const LLSD& response);
    
    bool callback_clear_cache(const LLSD& notification, const LLSD& response);
    
    James Cook's avatar
    James Cook committed
    
    
    //bool callback_skip_dialogs(const LLSD& notification, const LLSD& response, LLFloaterPreference* floater);
    //bool callback_reset_dialogs(const LLSD& notification, const LLSD& response, LLFloaterPreference* floater);
    
    James Cook's avatar
    James Cook committed
    
    
    void fractionFromDecimal(F32 decimal_val, S32& numerator, S32& denominator);
    
    
    bool callback_clear_cache(const LLSD& notification, const LLSD& response)
    {
    
    	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
    	if ( option == 0 ) // YES
    	{
    		// flag client texture cache for clearing next time the client runs
    		gSavedSettings.setBOOL("PurgeCacheOnNextStartup", TRUE);
    		LLNotificationsUtil::add("CacheWillClear");
    	}
    
    	return false;
    
    bool callback_clear_browser_cache(const LLSD& notification, const LLSD& response)
    {
    
    	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
    	if ( option == 0 ) // YES
    	{
    		// clean web
    
    		LLViewerMedia::getInstance()->clearAllCaches();
    		LLViewerMedia::getInstance()->clearAllCookies();
    
    		
    		// clean nav bar history
    		LLNavigationBar::getInstance()->clearHistoryCache();
    		
    		// flag client texture cache for clearing next time the client runs
    		gSavedSettings.setBOOL("PurgeCacheOnNextStartup", TRUE);
    		LLNotificationsUtil::add("CacheWillClear");
    
    		LLSearchHistory::getInstance()->clearHistory();
    		LLSearchHistory::getInstance()->save();
    		LLSearchComboBox* search_ctrl = LLNavigationBar::getInstance()->getChild<LLSearchComboBox>("search_combo_box");
    		search_ctrl->clearHistory();
    
    		LLTeleportHistoryStorage::getInstance()->purgeItems();
    		LLTeleportHistoryStorage::getInstance()->save();
    	}
    	
    	return false;
    
    void handleNameTagOptionChanged(const LLSD& newvalue)
    {
    
    	LLAvatarNameCache::getInstance()->setUseUsernames(gSavedSettings.getBOOL("NameTagShowUsernames"));
    
    	LLVOAvatar::invalidateNameTags();
    
    James Cook's avatar
    James Cook committed
    
    
    void handleDisplayNamesOptionChanged(const LLSD& newvalue)
    {
    
    	LLAvatarNameCache::getInstance()->setUseDisplayNames(newvalue.asBoolean());
    
    	LLVOAvatar::invalidateNameTags();
    
    void handleAppearanceCameraMovementChanged(const LLSD& newvalue)
    {
    
    	if(!newvalue.asBoolean() && gAgentCamera.getCameraMode() == CAMERA_MODE_CUSTOMIZE_AVATAR)
    	{
    		gAgentCamera.changeCameraToDefault();
    		gAgentCamera.resetView();
    	}
    
    void fractionFromDecimal(F32 decimal_val, S32& numerator, S32& denominator)
    {
    
    	numerator = 0;
    	denominator = 0;
    	for (F32 test_denominator = 1.f; test_denominator < 30.f; test_denominator += 1.f)
    	{
    		if (fmodf((decimal_val * test_denominator) + 0.01f, 1.f) < 0.02f)
    		{
    			numerator = ll_round(decimal_val * test_denominator);
    			denominator = ll_round(test_denominator);
    			break;
    		}
    	}
    
    // static
    std::string LLFloaterPreference::sSkin = "";
    //////////////////////////////////////////////
    // LLFloaterPreference
    
    LLFloaterPreference::LLFloaterPreference(const LLSD& key)
    
    	: LLFloater(key),
    	mGotPersonalInfo(false),
    	mOriginalIMViaEmail(false),
    	mLanguageChanged(false),
    	mAvatarDataInitialized(false),
    	mClickActionDirty(false)
    {
    	LLConversationLog::instance().addObserver(this);
    
    	//Build Floater is now Called from 	LLFloaterReg::add("preferences", "floater_preferences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreference>);
    	
    	static bool registered_dialog = false;
    	if (!registered_dialog)
    	{
    
    		LLFloaterReg::add("keybind_dialog", "floater_select_key.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLSetKeyBindDialog>);
    
    		registered_dialog = true;
    	}
    	
    	mCommitCallbackRegistrar.add("Pref.Cancel",				boost::bind(&LLFloaterPreference::onBtnCancel, this, _2));
    	mCommitCallbackRegistrar.add("Pref.OK",					boost::bind(&LLFloaterPreference::onBtnOK, this, _2));
    	
    	mCommitCallbackRegistrar.add("Pref.ClearCache",				boost::bind(&LLFloaterPreference::onClickClearCache, this));
    	mCommitCallbackRegistrar.add("Pref.WebClearCache",			boost::bind(&LLFloaterPreference::onClickBrowserClearCache, this));
    	mCommitCallbackRegistrar.add("Pref.SetCache",				boost::bind(&LLFloaterPreference::onClickSetCache, this));
    	mCommitCallbackRegistrar.add("Pref.ResetCache",				boost::bind(&LLFloaterPreference::onClickResetCache, this));
    	mCommitCallbackRegistrar.add("Pref.ClickSkin",				boost::bind(&LLFloaterPreference::onClickSkin, this,_1, _2));
    	mCommitCallbackRegistrar.add("Pref.SelectSkin",				boost::bind(&LLFloaterPreference::onSelectSkin, this));
    	mCommitCallbackRegistrar.add("Pref.VoiceSetKey",			boost::bind(&LLFloaterPreference::onClickSetKey, this));
    	mCommitCallbackRegistrar.add("Pref.VoiceSetMiddleMouse",	boost::bind(&LLFloaterPreference::onClickSetMiddleMouse, this));
    	mCommitCallbackRegistrar.add("Pref.SetSounds",				boost::bind(&LLFloaterPreference::onClickSetSounds, this));
    	mCommitCallbackRegistrar.add("Pref.ClickEnablePopup",		boost::bind(&LLFloaterPreference::onClickEnablePopup, this));
    	mCommitCallbackRegistrar.add("Pref.ClickDisablePopup",		boost::bind(&LLFloaterPreference::onClickDisablePopup, this));	
    	mCommitCallbackRegistrar.add("Pref.LogPath",				boost::bind(&LLFloaterPreference::onClickLogPath, this));
    	mCommitCallbackRegistrar.add("Pref.RenderExceptions",       boost::bind(&LLFloaterPreference::onClickRenderExceptions, this));
    	mCommitCallbackRegistrar.add("Pref.HardwareDefaults",		boost::bind(&LLFloaterPreference::setHardwareDefaults, this));
    	mCommitCallbackRegistrar.add("Pref.AvatarImpostorsEnable",	boost::bind(&LLFloaterPreference::onAvatarImpostorsEnable, this));
    	mCommitCallbackRegistrar.add("Pref.UpdateIndirectMaxComplexity",	boost::bind(&LLFloaterPreference::updateMaxComplexity, this));
    
        mCommitCallbackRegistrar.add("Pref.RenderOptionUpdate",     boost::bind(&LLFloaterPreference::onRenderOptionEnable, this));
    
    	mCommitCallbackRegistrar.add("Pref.WindowedMod",			boost::bind(&LLFloaterPreference::onCommitWindowedMode, this));
    	mCommitCallbackRegistrar.add("Pref.UpdateSliderText",		boost::bind(&LLFloaterPreference::refreshUI,this));
    	mCommitCallbackRegistrar.add("Pref.QualityPerformance",		boost::bind(&LLFloaterPreference::onChangeQuality, this, _2));
    	mCommitCallbackRegistrar.add("Pref.applyUIColor",			boost::bind(&LLFloaterPreference::applyUIColor, this ,_1, _2));
    	mCommitCallbackRegistrar.add("Pref.getUIColor",				boost::bind(&LLFloaterPreference::getUIColor, this ,_1, _2));
    	mCommitCallbackRegistrar.add("Pref.MaturitySettings",		boost::bind(&LLFloaterPreference::onChangeMaturity, this));
    	mCommitCallbackRegistrar.add("Pref.BlockList",				boost::bind(&LLFloaterPreference::onClickBlockList, this));
    	mCommitCallbackRegistrar.add("Pref.Proxy",					boost::bind(&LLFloaterPreference::onClickProxySettings, this));
    	mCommitCallbackRegistrar.add("Pref.TranslationSettings",	boost::bind(&LLFloaterPreference::onClickTranslationSettings, this));
    	mCommitCallbackRegistrar.add("Pref.AutoReplace",            boost::bind(&LLFloaterPreference::onClickAutoReplace, this));
    	mCommitCallbackRegistrar.add("Pref.PermsDefault",           boost::bind(&LLFloaterPreference::onClickPermsDefault, this));
    
    	mCommitCallbackRegistrar.add("Pref.RememberedUsernames",    boost::bind(&LLFloaterPreference::onClickRememberedUsernames, this));
    
    	mCommitCallbackRegistrar.add("Pref.SpellChecker",           boost::bind(&LLFloaterPreference::onClickSpellChecker, this));
    	mCommitCallbackRegistrar.add("Pref.Advanced",				boost::bind(&LLFloaterPreference::onClickAdvanced, this));
    
    	sSkin = gSavedSettings.getString("SkinCurrent");
    
    	mCommitCallbackRegistrar.add("Pref.ClickActionChange",		boost::bind(&LLFloaterPreference::onClickActionChange, this));
    
    	gSavedSettings.getControl("NameTagShowUsernames")->getCommitSignal()->connect(boost::bind(&handleNameTagOptionChanged,  _2));	
    	gSavedSettings.getControl("NameTagShowFriends")->getCommitSignal()->connect(boost::bind(&handleNameTagOptionChanged,  _2));	
    	gSavedSettings.getControl("UseDisplayNames")->getCommitSignal()->connect(boost::bind(&handleDisplayNamesOptionChanged,  _2));
    
    	gSavedSettings.getControl("AppearanceCameraMovement")->getCommitSignal()->connect(boost::bind(&handleAppearanceCameraMovementChanged,  _2));
    
    	LLAvatarPropertiesProcessor::getInstance()->addObserver( gAgent.getID(), this );
    
    	mCommitCallbackRegistrar.add("Pref.ClearLog",				boost::bind(&LLConversationLog::onClearLog, &LLConversationLog::instance()));
    	mCommitCallbackRegistrar.add("Pref.DeleteTranscripts",      boost::bind(&LLFloaterPreference::onDeleteTranscripts, this));
    
    	mCommitCallbackRegistrar.add("UpdateFilter", boost::bind(&LLFloaterPreference::onUpdateFilterTerm, this, false)); // <FS:ND/> Hook up for filtering
    
    void LLFloaterPreference::processProperties( void* pData, EAvatarProcessorType type )
    {
    
    	if ( APT_PROPERTIES == type )
    	{
    		const LLAvatarData* pAvatarData = static_cast<const LLAvatarData*>( pData );
    		if (pAvatarData && (gAgent.getID() == pAvatarData->avatar_id) && (pAvatarData->avatar_id != LLUUID::null))
    		{
    			storeAvatarProperties( pAvatarData );
    			processProfileProperties( pAvatarData );
    		}
    	}	
    
    void LLFloaterPreference::storeAvatarProperties( const LLAvatarData* pAvatarData )
    {
    
    	if (LLStartUp::getStartupState() == STATE_STARTED)
    	{
    		mAvatarProperties.avatar_id		= pAvatarData->avatar_id;
    		mAvatarProperties.image_id		= pAvatarData->image_id;
    		mAvatarProperties.fl_image_id   = pAvatarData->fl_image_id;
    		mAvatarProperties.about_text	= pAvatarData->about_text;
    		mAvatarProperties.fl_about_text = pAvatarData->fl_about_text;
    		mAvatarProperties.profile_url   = pAvatarData->profile_url;
    		mAvatarProperties.flags		    = pAvatarData->flags;
    		mAvatarProperties.allow_publish	= pAvatarData->flags & AVATAR_ALLOW_PUBLISH;
    
    		mAvatarDataInitialized = true;
    	}
    
    void LLFloaterPreference::processProfileProperties(const LLAvatarData* pAvatarData )
    {
    
    	getChild<LLUICtrl>("online_searchresults")->setValue( (bool)(pAvatarData->flags & AVATAR_ALLOW_PUBLISH) );	
    
    void LLFloaterPreference::saveAvatarProperties( void )
    {
    
    	const BOOL allowPublish = getChild<LLUICtrl>("online_searchresults")->getValue();
    
    	if (allowPublish)
    	{
    		mAvatarProperties.flags |= AVATAR_ALLOW_PUBLISH;
    	}
    
    	//
    	// NOTE: We really don't want to send the avatar properties unless we absolutely
    	//       need to so we can avoid the accidental profile reset bug, so, if we're
    	//       logged in, the avatar data has been initialized and we have a state change
    	//       for the "allow publish" flag, then set the flag to its new value and send
    	//       the properties update.
    	//
    	// NOTE: The only reason we can not remove this update altogether is because of the
    	//       "allow publish" flag, the last remaining profile setting in the viewer
    	//       that doesn't exist in the web profile.
    	//
    	if ((LLStartUp::getStartupState() == STATE_STARTED) && mAvatarDataInitialized && (allowPublish != mAvatarProperties.allow_publish))
    	{
    		mAvatarProperties.allow_publish = allowPublish;
    
    		LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesUpdate( &mAvatarProperties );
    	}
    
    BOOL LLFloaterPreference::postBuild()
    {
    
    	gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLFloaterIMSessionTab::processChatHistoryStyleUpdate, false));
    
    	gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLViewerChat::signalChatFontChanged));
    
    	gSavedSettings.getControl("ChatBubbleOpacity")->getSignal()->connect(boost::bind(&LLFloaterPreference::onNameTagOpacityChange, this, _2));
    
    	gSavedSettings.getControl("PreferredMaturity")->getSignal()->connect(boost::bind(&LLFloaterPreference::onChangeMaturity, this));
    
    	gSavedPerAccountSettings.getControl("ModelUploadFolder")->getSignal()->connect(boost::bind(&LLFloaterPreference::onChangeModelFolder, this));
    	gSavedPerAccountSettings.getControl("TextureUploadFolder")->getSignal()->connect(boost::bind(&LLFloaterPreference::onChangeTextureFolder, this));
    	gSavedPerAccountSettings.getControl("SoundUploadFolder")->getSignal()->connect(boost::bind(&LLFloaterPreference::onChangeSoundFolder, this));
    	gSavedPerAccountSettings.getControl("AnimationUploadFolder")->getSignal()->connect(boost::bind(&LLFloaterPreference::onChangeAnimationFolder, this));
    
    	LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core");
    	if (!tabcontainer->selectTab(gSavedSettings.getS32("LastPrefTab")))
    		tabcontainer->selectFirstTab();
    
    	getChild<LLUICtrl>("cache_location")->setEnabled(FALSE); // make it read-only but selectable (STORM-227)
    	std::string cache_location = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "");
    	setCacheLocation(cache_location);
    
    	getChild<LLUICtrl>("log_path_string")->setEnabled(FALSE); // make it read-only but selectable
    
    	getChild<LLComboBox>("language_combobox")->setCommitCallback(boost::bind(&LLFloaterPreference::onLanguageChange, this));
    
    	getChild<LLComboBox>("FriendIMOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"FriendIMOptions"));
    	getChild<LLComboBox>("NonFriendIMOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"NonFriendIMOptions"));
    	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)
    	{
    		gSavedPerAccountSettings.setString("DoNotDisturbModeResponse", LLTrans::getString("DoNotDisturbModeResponseDefault"));
    	}
    
    	// set 'enable' property for 'Clear log...' button
    	changed();
    
    	LLLogChat::getInstance()->setSaveHistorySignal(boost::bind(&LLFloaterPreference::onLogChatHistorySaved, this));
    
    	LLSliderCtrl* fov_slider = getChild<LLSliderCtrl>("camera_fov");
    	fov_slider->setMinValue(LLViewerCamera::getInstance()->getMinView());
    	fov_slider->setMaxValue(LLViewerCamera::getInstance()->getMaxView());
    
    	
    	// Hook up and init for filtering
    	mFilterEdit = getChild<LLSearchEditor>("search_prefs_edit");
    	mFilterEdit->setKeystrokeCallback(boost::bind(&LLFloaterPreference::onUpdateFilterTerm, this, false));
    
    	// Load and assign label for 'default language'
    	std::string user_filename = gDirUtilp->getExpandedFilename(LL_PATH_DEFAULT_SKIN, "default_languages.xml");
    	std::map<std::string, std::string> labels;
    	if (loadFromFilename(user_filename, labels))
    	{
    		std::string system_lang = gSavedSettings.getString("SystemLanguage");
    		std::map<std::string, std::string>::iterator iter = labels.find(system_lang);
    		if (iter != labels.end())
    		{
    			getChild<LLComboBox>("language_combobox")->add(iter->second, LLSD("default"), ADD_TOP, true);
    		}
    		else
    		{
    			LL_WARNS() << "Language \"" << system_lang << "\" is not in default_languages.xml" << LL_ENDL;
    			getChild<LLComboBox>("language_combobox")->add("System default", LLSD("default"), ADD_TOP, true);
    		}
    	}
    	else
    	{
    		LL_WARNS() << "Failed to load labels from " << user_filename << ". Using default." << LL_ENDL;
    		getChild<LLComboBox>("language_combobox")->add("System default", LLSD("default"), ADD_TOP, true);
    	}
    
    	return TRUE;
    
    void LLFloaterPreference::updateDeleteTranscriptsButton()
    {
    
    	std::vector<std::string> list_of_transcriptions_file_names;
    	LLLogChat::getListOfTranscriptFiles(list_of_transcriptions_file_names);
    	getChild<LLButton>("delete_transcripts")->setEnabled(list_of_transcriptions_file_names.size() > 0);
    
    void LLFloaterPreference::onDoNotDisturbResponseChanged()
    
    	// set "DoNotDisturbResponseChanged" TRUE if user edited message differs from default, FALSE otherwise
    	bool response_changed_flag =
    			LLTrans::getString("DoNotDisturbModeResponseDefault")
    					!= getChild<LLUICtrl>("do_not_disturb_response")->getValue().asString();
    
    	gSavedPerAccountSettings.setBOOL("DoNotDisturbResponseChanged", response_changed_flag );
    
    LLFloaterPreference::~LLFloaterPreference()
    {
    
    	LLConversationLog::instance().removeObserver(this);
    
    void LLFloaterPreference::draw()
    {
    
    	BOOL has_first_selected = (getChildRef<LLScrollListCtrl>("disabled_popups").getFirstSelected()!=NULL);
    	gSavedSettings.setBOOL("FirstSelectedDisabledPopups", has_first_selected);
    	
    	has_first_selected = (getChildRef<LLScrollListCtrl>("enabled_popups").getFirstSelected()!=NULL);
    	gSavedSettings.setBOOL("FirstSelectedEnabledPopups", has_first_selected);
    	
    	LLFloater::draw();
    
    void LLFloaterPreference::saveSettings()
    {
    
    	LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core");
    	child_list_t::const_iterator iter = tabcontainer->getChildList()->begin();
    	child_list_t::const_iterator end = tabcontainer->getChildList()->end();
    	for ( ; iter != end; ++iter)
    	{
    		LLView* view = *iter;
    		LLPanelPreference* panel = dynamic_cast<LLPanelPreference*>(view);
    		if (panel)
    			panel->saveSettings();
    	}
    }	
    
    void LLFloaterPreference::apply()
    {
    
    	LLAvatarPropertiesProcessor::getInstance()->addObserver( gAgent.getID(), this );
    	
    	LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core");
    	if (sSkin != gSavedSettings.getString("SkinCurrent"))
    	{
    		LLNotificationsUtil::add("ChangeSkin");
    		refreshSkin(this);
    	}
    	// Call apply() on all panels that derive from LLPanelPreference
    	for (child_list_t::const_iterator iter = tabcontainer->getChildList()->begin();
    		 iter != tabcontainer->getChildList()->end(); ++iter)
    	{
    		LLView* view = *iter;
    		LLPanelPreference* panel = dynamic_cast<LLPanelPreference*>(view);
    		if (panel)
    			panel->apply();
    	}
    	
    	gViewerWindow->requestResolutionUpdate(); // for UIScaleFactor
    
    	LLSliderCtrl* fov_slider = getChild<LLSliderCtrl>("camera_fov");
    	fov_slider->setMinValue(LLViewerCamera::getInstance()->getMinView());
    	fov_slider->setMaxValue(LLViewerCamera::getInstance()->getMaxView());
    	
    	std::string cache_location = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "");
    	setCacheLocation(cache_location);
    	
    
    	LLViewerMedia::getInstance()->setCookiesEnabled(getChild<LLUICtrl>("cookies_enabled")->getValue());
    
    	
    	if (hasChild("web_proxy_enabled", TRUE) &&hasChild("web_proxy_editor", TRUE) && hasChild("web_proxy_port", TRUE))
    	{
    		bool proxy_enable = getChild<LLUICtrl>("web_proxy_enabled")->getValue();
    		std::string proxy_address = getChild<LLUICtrl>("web_proxy_editor")->getValue();
    		int proxy_port = getChild<LLUICtrl>("web_proxy_port")->getValue();
    
    		LLViewerMedia::getInstance()->setProxyConfig(proxy_enable, proxy_address, proxy_port);
    
    	}
    	
    	if (mGotPersonalInfo)
    	{ 
    		bool new_im_via_email = getChild<LLUICtrl>("send_im_to_email")->getValue().asBoolean();
    		bool new_hide_online = getChild<LLUICtrl>("online_visibility")->getValue().asBoolean();		
    	
    		if ((new_im_via_email != mOriginalIMViaEmail)
    			||(new_hide_online != mOriginalHideOnlineStatus))
    		{
    			// This hack is because we are representing several different 	 
    			// possible strings with a single checkbox. Since most users 	 
    			// can only select between 2 values, we represent it as a 	 
    			// checkbox. This breaks down a little bit for liaisons, but 	 
    			// works out in the end. 	 
    			if (new_hide_online != mOriginalHideOnlineStatus)
    			{
    				if (new_hide_online) mDirectoryVisibility = VISIBILITY_HIDDEN;
    				else mDirectoryVisibility = VISIBILITY_DEFAULT;
    			 //Update showonline value, otherwise multiple applys won't work
    				mOriginalHideOnlineStatus = new_hide_online;
    			}
    			gAgent.sendAgentUpdateUserInfo(new_im_via_email,mDirectoryVisibility);
    		}
    	}
    
    	saveAvatarProperties();
    
    	if (mClickActionDirty)
    	{
    		updateClickActionSettings();
    		mClickActionDirty = false;
    	}
    
    }
    
    void LLFloaterPreference::cancel()
    {
    
    	LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core");
    	// Call cancel() on all panels that derive from LLPanelPreference
    	for (child_list_t::const_iterator iter = tabcontainer->getChildList()->begin();
    		iter != tabcontainer->getChildList()->end(); ++iter)
    	{
    		LLView* view = *iter;
    		LLPanelPreference* panel = dynamic_cast<LLPanelPreference*>(view);
    		if (panel)
    			panel->cancel();
    	}
    	// hide joystick pref floater
    	LLFloaterReg::hideInstance("pref_joystick");
    
    	// hide translation settings floater
    	LLFloaterReg::hideInstance("prefs_translation");
    	
    	// hide autoreplace settings floater
    	LLFloaterReg::hideInstance("prefs_autoreplace");
    	
    	// hide spellchecker settings folder
    	LLFloaterReg::hideInstance("prefs_spellchecker");
    
    	// hide advanced graphics floater
    	LLFloaterReg::hideInstance("prefs_graphics_advanced");
    	
    	// reverts any changes to current skin
    	gSavedSettings.setString("SkinCurrent", sSkin);
    
    	if (mClickActionDirty)
    	{
    		updateClickActionControls();
    		mClickActionDirty = false;
    	}
    
    	LLFloaterPreferenceProxy * advanced_proxy_settings = LLFloaterReg::findTypedInstance<LLFloaterPreferenceProxy>("prefs_proxy");
    	if (advanced_proxy_settings)
    	{
    		advanced_proxy_settings->cancel();
    	}
    	//Need to reload the navmesh if the pathing console is up
    	LLHandle<LLFloaterPathfindingConsole> pathfindingConsoleHandle = LLFloaterPathfindingConsole::getInstanceHandle();
    	if ( !pathfindingConsoleHandle.isDead() )
    	{
    		LLFloaterPathfindingConsole* pPathfindingConsole = pathfindingConsoleHandle.get();
    		pPathfindingConsole->onRegionBoundaryCross();
    	}
    
    	if (!mSavedGraphicsPreset.empty())
    	{
    		gSavedSettings.setString("PresetGraphicActive", mSavedGraphicsPreset);
    		LLPresetsManager::getInstance()->triggerChangeSignal();
    	}
    
    }
    
    void LLFloaterPreference::onOpen(const LLSD& key)
    {
    
    	// this variable and if that follows it are used to properly handle do not disturb mode response message
    	static bool initialized = FALSE;
    	// if user is logged in and we haven't initialized do not disturb mode response yet, do it
    	if (!initialized && LLStartUp::getStartupState() == STATE_STARTED)
    	{
    		// Special approach is used for do not disturb response localization, because "DoNotDisturbModeResponse" is
    		// in non-localizable xml, and also because it may be changed by user and in this case it shouldn't be localized.
    		// To keep track of whether do not disturb response is default or changed by user additional setting DoNotDisturbResponseChanged
    		// was added into per account settings.
    
    		// initialization should happen once,so setting variable to TRUE
    		initialized = TRUE;
    		// this connection is needed to properly set "DoNotDisturbResponseChanged" setting when user makes changes in
    		// do not disturb response message.
    		gSavedPerAccountSettings.getControl("DoNotDisturbModeResponse")->getSignal()->connect(boost::bind(&LLFloaterPreference::onDoNotDisturbResponseChanged, this));
    	}
    	gAgent.sendAgentUserInfoRequest();
    
    	/////////////////////////// From LLPanelGeneral //////////////////////////
    	// if we have no agent, we can't let them choose anything
    	// if we have an agent, then we only let them choose if they have a choice
    	bool can_choose_maturity =
    		gAgent.getID().notNull() &&
    		(gAgent.isMature() || gAgent.isGodlike());
    	
    	LLComboBox* maturity_combo = getChild<LLComboBox>("maturity_desired_combobox");
    	LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest( gAgent.getID() );
    	if (can_choose_maturity)
    	{		
    		// if they're not adult or a god, they shouldn't see the adult selection, so delete it
    		if (!gAgent.isAdult() && !gAgent.isGodlikeWithoutAdminMenuFakery())
    		{
    			// we're going to remove the adult entry from the combo
    			LLScrollListCtrl* maturity_list = maturity_combo->findChild<LLScrollListCtrl>("ComboBox");
    			if (maturity_list)
    			{
    				maturity_list->deleteItems(LLSD(SIM_ACCESS_ADULT));
    			}
    		}
    		getChildView("maturity_desired_combobox")->setEnabled( true);
    		getChildView("maturity_desired_textbox")->setVisible( false);
    	}
    	else
    	{
    		getChild<LLUICtrl>("maturity_desired_textbox")->setValue(maturity_combo->getSelectedItemLabel());
    		getChildView("maturity_desired_combobox")->setEnabled( false);
    	}
    
    	// Forget previous language changes.
    	mLanguageChanged = false;
    
    	// Display selected maturity icons.
    	onChangeMaturity();
    
    	onChangeModelFolder();
    	onChangeTextureFolder();
    	onChangeSoundFolder();
    	onChangeAnimationFolder();
    
    	// Load (double-)click to walk/teleport settings.
    	updateClickActionControls();
    	
    	// Enabled/disabled popups, might have been changed by user actions
    	// while preferences floater was closed.
    	buildPopupLists();
    
    
    	//get the options that were checked
    	onNotificationsChange("FriendIMOptions");
    	onNotificationsChange("NonFriendIMOptions");
    	onNotificationsChange("ConferenceIMOptions");
    	onNotificationsChange("GroupChatOptions");
    	onNotificationsChange("NearbyChatOptions");
    	onNotificationsChange("ObjectIMOptions");
    
    	LLPanelLogin::setAlwaysRefresh(true);
    	refresh();
    	
    	// Make sure the current state of prefs are saved away when
    	// when the floater is opened.  That will make cancel do its
    	// job
    	saveSettings();
    
    	// Make sure there is a default preference file
    	LLPresetsManager::getInstance()->createMissingDefault(PRESETS_CAMERA);
    	LLPresetsManager::getInstance()->createMissingDefault(PRESETS_GRAPHIC);
    
    	bool started = (LLStartUp::getStartupState() == STATE_STARTED);
    
    	LLButton* load_btn = findChild<LLButton>("PrefLoadButton");
    	LLButton* save_btn = findChild<LLButton>("PrefSaveButton");
    	LLButton* delete_btn = findChild<LLButton>("PrefDeleteButton");
    	LLButton* exceptions_btn = findChild<LLButton>("RenderExceptionsButton");
    
    	if (load_btn && save_btn && delete_btn && exceptions_btn)
    	{
    		load_btn->setEnabled(started);
    		save_btn->setEnabled(started);
    		delete_btn->setEnabled(started);
    		exceptions_btn->setEnabled(started);
    	}
    
    
        collectSearchableItems();
    	if (!mFilterEdit->getText().empty())
    	{
    		mFilterEdit->setText(LLStringExplicit(""));
    		onUpdateFilterTerm(true);
    	}
    
    void LLFloaterPreference::onRenderOptionEnable()
    
    	refreshEnabledGraphics();
    
    void LLFloaterPreferenceGraphicsAdvanced::onRenderOptionEnable()
    
    {
    	LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences");
    	if (instance)
    	{
    		instance->refresh();
    	}
    
    	refreshEnabledGraphics();
    }
    
    
    void LLFloaterPreferenceGraphicsAdvanced::onAdvancedAtmosphericsEnable()
    
    	LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences");
    	if (instance)
    	{
    		instance->refresh();
    	}