/** * @file llfloaterpreference.cpp * @brief Global preferences with and without persistence. * * $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$ */ /* * 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 "llfloaterautoreplacesettings.h" #include "llagent.h" #include "llagentcamera.h" #include "llcheckboxctrl.h" #include "llcolorswatch.h" #include "llcombobox.h" #include "llcommandhandler.h" #include "lldirpicker.h" #include "lleventtimer.h" #include "llfeaturemanager.h" #include "llfocusmgr.h" //#include "llfirstuse.h" #include "llfloaterreg.h" #include "llfloaterabout.h" #include "llfavoritesbar.h" #include "llfloaterhardwaresettings.h" #include "llfloatersidepanelcontainer.h" #include "llfloaterimsession.h" #include "llkeyboard.h" #include "llmodaldialog.h" #include "llnavigationbar.h" #include "llfloaterimnearbychat.h" #include "llnotifications.h" #include "llnotificationsutil.h" #include "llnotificationtemplate.h" #include "llpanellogin.h" #include "llpanelvoicedevicesettings.h" #include "llradiogroup.h" #include "llsearchcombobox.h" #include "llsky.h" #include "llscrolllistctrl.h" #include "llscrolllistitem.h" #include "llsliderctrl.h" #include "lltabcontainer.h" #include "lltrans.h" #include "llviewercontrol.h" #include "llviewercamera.h" #include "llviewerwindow.h" #include "llviewermessage.h" #include "llviewershadermgr.h" #include "llviewerthrottle.h" #include "llvoavatarself.h" #include "llvotree.h" #include "llvosky.h" #include "llfloaterpathfindingconsole.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" #include "llteleporthistorystorage.h" #include "llproxy.h" #include "llweb.h" #include "lllogininstance.h" // to check if logged in yet #include "llsdserialize.h" 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"; class LLVoiceSetKeyDialog : public LLModalDialog { public: LLVoiceSetKeyDialog(const LLSD& key); ~LLVoiceSetKeyDialog(); /*virtual*/ BOOL postBuild(); void setParent(LLFloaterPreference* parent) { mParent = parent; } BOOL handleKeyHere(KEY key, MASK mask); static void onCancel(void* user_data); private: LLFloaterPreference* mParent; }; LLVoiceSetKeyDialog::LLVoiceSetKeyDialog(const LLSD& key) : LLModalDialog(key), mParent(NULL) { } //virtual BOOL LLVoiceSetKeyDialog::postBuild() { childSetAction("Cancel", onCancel, this); getChild("Cancel")->setFocus(TRUE); gFocusMgr.setKeystrokesOnly(TRUE); return TRUE; } LLVoiceSetKeyDialog::~LLVoiceSetKeyDialog() { } BOOL LLVoiceSetKeyDialog::handleKeyHere(KEY key, MASK mask) { BOOL result = TRUE; if (key == 'Q' && mask == MASK_CONTROL) { result = FALSE; } else if (mParent) { mParent->setKey(key); } closeFloater(); return result; } //static void LLVoiceSetKeyDialog::onCancel(void* user_data) { LLVoiceSetKeyDialog* self = (LLVoiceSetKeyDialog*)user_data; self->closeFloater(); } // global functions // 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 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); //bool callback_skip_dialogs(const LLSD& notification, const LLSD& response, LLFloaterPreference* floater); //bool callback_reset_dialogs(const LLSD& notification, const LLSD& response, LLFloaterPreference* floater); 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::clearAllCaches(); LLViewerMedia::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("search_combo_box"); search_ctrl->clearHistory(); LLTeleportHistoryStorage::getInstance()->purgeItems(); LLTeleportHistoryStorage::getInstance()->save(); } return false; } void handleNameTagOptionChanged(const LLSD& newvalue) { LLAvatarNameCache::setUseUsernames(gSavedSettings.getBOOL("NameTagShowUsernames")); LLVOAvatar::invalidateNameTags(); } void handleDisplayNamesOptionChanged(const LLSD& newvalue) { LLAvatarNameCache::setUseDisplayNames(newvalue.asBoolean()); LLVOAvatar::invalidateNameTags(); } void handleAppearanceCameraMovementChanged(const LLSD& newvalue) { if(!newvalue.asBoolean() && gAgentCamera.getCameraMode() == CAMERA_MODE_CUSTOMIZE_AVATAR) { gAgentCamera.changeCameraToDefault(); gAgentCamera.resetView(); } } /*bool callback_skip_dialogs(const LLSD& notification, const LLSD& response, LLFloaterPreference* floater) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (0 == option && floater ) { if ( floater ) { floater->setAllIgnored(); // LLFirstUse::disableFirstUse(); floater->buildPopupLists(); } } return false; } bool callback_reset_dialogs(const LLSD& notification, const LLSD& response, LLFloaterPreference* floater) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if ( 0 == option && floater ) { if ( floater ) { floater->resetAllIgnored(); //LLFirstUse::resetFirstUse(); floater->buildPopupLists(); } } return false; } */ 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); static bool registered_dialog = false; if (!registered_dialog) { LLFloaterReg::add("voice_set_key", "floater_select_key.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); registered_dialog = true; } mCommitCallbackRegistrar.add("Pref.Apply", boost::bind(&LLFloaterPreference::onBtnApply, this)); mCommitCallbackRegistrar.add("Pref.Cancel", boost::bind(&LLFloaterPreference::onBtnCancel, this)); mCommitCallbackRegistrar.add("Pref.OK", boost::bind(&LLFloaterPreference::onBtnOK, this)); 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.HardwareSettings", boost::bind(&LLFloaterPreference::onOpenHardwareSettings, this)); mCommitCallbackRegistrar.add("Pref.HardwareDefaults", boost::bind(&LLFloaterPreference::setHardwareDefaults, this)); mCommitCallbackRegistrar.add("Pref.VertexShaderEnable", boost::bind(&LLFloaterPreference::onVertexShaderEnable, this)); mCommitCallbackRegistrar.add("Pref.EnhancedSkeletonEnable", boost::bind(&LLFloaterPreference::onEnhancedSkeletonEnable, this, _1)); 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.SpellChecker", boost::bind(&LLFloaterPreference::onClickSpellChecker, 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)); } void LLFloaterPreference::processProperties( void* pData, EAvatarProcessorType type ) { if ( APT_PROPERTIES == type ) { const LLAvatarData* pAvatarData = static_cast( 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("online_searchresults")->setValue( (bool)(pAvatarData->flags & AVATAR_ALLOW_PUBLISH) ); } void LLFloaterPreference::saveAvatarProperties( void ) { const BOOL allowPublish = getChild("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)); LLTabContainer* tabcontainer = getChild("pref core"); if (!tabcontainer->selectTab(gSavedSettings.getS32("LastPrefTab"))) tabcontainer->selectFirstTab(); getChild("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("log_path_string")->setEnabled(FALSE); // make it read-only but selectable getChild("language_combobox")->setCommitCallback(boost::bind(&LLFloaterPreference::onLanguageChange, this)); getChild("FriendIMOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"FriendIMOptions")); getChild("NonFriendIMOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"NonFriendIMOptions")); getChild("ConferenceIMOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"ConferenceIMOptions")); getChild("GroupChatOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"GroupChatOptions")); getChild("NearbyChatOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"NearbyChatOptions")); getChild("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::setSaveHistorySignal(boost::bind(&LLFloaterPreference::onLogChatHistorySaved, this)); LLSliderCtrl* fov_slider = getChild("camera_fov"); fov_slider->setMinValue(LLViewerCamera::getInstance()->getMinView()); fov_slider->setMaxValue(LLViewerCamera::getInstance()->getMaxView()); return TRUE; } void LLFloaterPreference::updateDeleteTranscriptsButton() { std::vector list_of_transcriptions_file_names; LLLogChat::getListOfTranscriptFiles(list_of_transcriptions_file_names); getChild("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("do_not_disturb_response")->getValue().asString(); gSavedPerAccountSettings.setBOOL("DoNotDisturbResponseChanged", response_changed_flag ); } LLFloaterPreference::~LLFloaterPreference() { // clean up user data LLComboBox* ctrl_window_size = getChild("windowsize combo"); for (S32 i = 0; i < ctrl_window_size->getItemCount(); i++) { ctrl_window_size->setCurrentByIndex(i); } LLConversationLog::instance().removeObserver(this); } void LLFloaterPreference::draw() { BOOL has_first_selected = (getChildRef("disabled_popups").getFirstSelected()!=NULL); gSavedSettings.setBOOL("FirstSelectedDisabledPopups", has_first_selected); has_first_selected = (getChildRef("enabled_popups").getFirstSelected()!=NULL); gSavedSettings.setBOOL("FirstSelectedEnabledPopups", has_first_selected); LLFloater::draw(); } void LLFloaterPreference::saveSettings() { LLTabContainer* tabcontainer = getChild("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(view); if (panel) panel->saveSettings(); } } void LLFloaterPreference::apply() { LLAvatarPropertiesProcessor::getInstance()->addObserver( gAgent.getID(), this ); LLTabContainer* tabcontainer = getChild("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(view); if (panel) panel->apply(); } // hardware menu apply LLFloaterHardwareSettings* hardware_settings = LLFloaterReg::getTypedInstance("prefs_hardware_settings"); if (hardware_settings) { hardware_settings->apply(); } gViewerWindow->requestResolutionUpdate(); // for UIScaleFactor LLSliderCtrl* fov_slider = getChild("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::setCookiesEnabled(getChild("cookies_enabled")->getValue()); if (hasChild("web_proxy_enabled", TRUE) &&hasChild("web_proxy_editor", TRUE) && hasChild("web_proxy_port", TRUE)) { bool proxy_enable = getChild("web_proxy_enabled")->getValue(); std::string proxy_address = getChild("web_proxy_editor")->getValue(); int proxy_port = getChild("web_proxy_port")->getValue(); LLViewerMedia::setProxyConfig(proxy_enable, proxy_address, proxy_port); } if (mGotPersonalInfo) { bool new_im_via_email = getChild("send_im_to_email")->getValue().asBoolean(); bool new_hide_online = getChild("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("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(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"); // cancel hardware menu LLFloaterHardwareSettings* hardware_settings = LLFloaterReg::getTypedInstance("prefs_hardware_settings"); if (hardware_settings) { hardware_settings->cancel(); } // reverts any changes to current skin gSavedSettings.setString("SkinCurrent", sSkin); if (mClickActionDirty) { updateClickActionControls(); mClickActionDirty = false; } LLFloaterPreferenceProxy * advanced_proxy_settings = LLFloaterReg::findTypedInstance("prefs_proxy"); if (advanced_proxy_settings) { advanced_proxy_settings->cancel(); } //Need to reload the navmesh if the pathing console is up LLHandle pathfindingConsoleHandle = LLFloaterPathfindingConsole::getInstanceHandle(); if ( !pathfindingConsoleHandle.isDead() ) { LLFloaterPathfindingConsole* pPathfindingConsole = pathfindingConsoleHandle.get(); pPathfindingConsole->onRegionBoundaryCross(); } } 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("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("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("maturity_desired_textbox")->setValue(maturity_combo->getSelectedItemLabel()); getChildView("maturity_desired_combobox")->setEnabled( false); } // Forget previous language changes. mLanguageChanged = false; // Display selected maturity icons. onChangeMaturity(); // 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(); } void LLFloaterPreference::onVertexShaderEnable() { refreshEnabledGraphics(); } void LLFloaterPreference::onEnhancedSkeletonEnable(LLUICtrl *ctrl) { bool enabled = ctrl->getValue().asBoolean(); bool curr_enabled = gSavedSettings.getBOOL("IncludeEnhancedSkeleton"); if (enabled != curr_enabled) { gSavedSettings.setBOOL("IncludeEnhancedSkeleton",enabled); } } //static void LLFloaterPreference::initDoNotDisturbResponse() { if (!gSavedPerAccountSettings.getBOOL("DoNotDisturbResponseChanged")) { //LLTrans::getString("DoNotDisturbModeResponseDefault") is used here for localization (EXT-5885) gSavedPerAccountSettings.setString("DoNotDisturbModeResponse", LLTrans::getString("DoNotDisturbModeResponseDefault")); } } //static void LLFloaterPreference::updateShowFavoritesCheckbox(bool val) { LLFloaterPreference* instance = LLFloaterReg::findTypedInstance("preferences"); if (instance) { instance->getChild("favorites_on_login_check")->setValue(val); } } void LLFloaterPreference::setHardwareDefaults() { LLFeatureManager::getInstance()->applyRecommendedSettings(); refreshEnabledGraphics(); LLTabContainer* tabcontainer = getChild("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(view); if (panel) panel->setHardwareDefaults(); } } //virtual void LLFloaterPreference::onClose(bool app_quitting) { gSavedSettings.setS32("LastPrefTab", getChild("pref core")->getCurrentPanelIndex()); LLPanelLogin::setAlwaysRefresh(false); if (!app_quitting) { cancel(); } } void LLFloaterPreference::onOpenHardwareSettings() { LLFloater* floater = LLFloaterReg::showInstance("prefs_hardware_settings"); addDependentFloater(floater, FALSE); } // static void LLFloaterPreference::onBtnOK() { // commit any outstanding text entry if (hasFocus()) { LLUICtrl* cur_focus = dynamic_cast(gFocusMgr.getKeyboardFocus()); if (cur_focus && cur_focus->acceptsTextInput()) { cur_focus->onCommit(); } } if (canClose()) { saveSettings(); apply(); closeFloater(false); //Conversation transcript and log path changed so reload conversations based on new location if(mPriorInstantMessageLogPath.length()) { if(moveTranscriptsAndLog()) { //When floaters are empty but have a chat history files, reload chat history into them LLFloaterIMSessionTab::reloadEmptyFloaters(); } //Couldn't move files so restore the old path and show a notification else { gSavedPerAccountSettings.setString("InstantMessageLogPath", mPriorInstantMessageLogPath); LLNotificationsUtil::add("PreferenceChatPathChanged"); } mPriorInstantMessageLogPath.clear(); } LLUIColorTable::instance().saveUserSettings(); gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE); //Only save once logged in and loaded per account settings if(mGotPersonalInfo) { gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE); } } else { // Show beep, pop up dialog, etc. LL_INFOS() << "Can't close preferences!" << LL_ENDL; } LLPanelLogin::updateLocationSelectorsVisibility(); //Need to reload the navmesh if the pathing console is up LLHandle pathfindingConsoleHandle = LLFloaterPathfindingConsole::getInstanceHandle(); if ( !pathfindingConsoleHandle.isDead() ) { LLFloaterPathfindingConsole* pPathfindingConsole = pathfindingConsoleHandle.get(); pPathfindingConsole->onRegionBoundaryCross(); } } // static void LLFloaterPreference::onBtnApply( ) { if (hasFocus()) { LLUICtrl* cur_focus = dynamic_cast(gFocusMgr.getKeyboardFocus()); if (cur_focus && cur_focus->acceptsTextInput()) { cur_focus->onCommit(); } } apply(); saveSettings(); LLPanelLogin::updateLocationSelectorsVisibility(); } // static void LLFloaterPreference::onBtnCancel() { if (hasFocus()) { LLUICtrl* cur_focus = dynamic_cast(gFocusMgr.getKeyboardFocus()); if (cur_focus && cur_focus->acceptsTextInput()) { cur_focus->onCommit(); } refresh(); } cancel(); closeFloater(); } // static void LLFloaterPreference::updateUserInfo(const std::string& visibility, bool im_via_email) { LLFloaterPreference* instance = LLFloaterReg::findTypedInstance("preferences"); if (instance) { instance->setPersonalInfo(visibility, im_via_email); } } void LLFloaterPreference::refreshEnabledGraphics() { LLFloaterPreference* instance = LLFloaterReg::findTypedInstance("preferences"); if (instance) { instance->refresh(); //instance->refreshEnabledState(); } LLFloaterHardwareSettings* hardware_settings = LLFloaterReg::getTypedInstance("prefs_hardware_settings"); if (hardware_settings) { hardware_settings->refreshEnabledState(); } } void LLFloaterPreference::onClickClearCache() { LLNotificationsUtil::add("ConfirmClearCache", LLSD(), LLSD(), callback_clear_cache); } void LLFloaterPreference::onClickBrowserClearCache() { LLNotificationsUtil::add("ConfirmClearBrowserCache", LLSD(), LLSD(), callback_clear_browser_cache); } // Called when user changes language via the combobox. void LLFloaterPreference::onLanguageChange() { // Let the user know that the change will only take effect after restart. // Do it only once so that we're not too irritating. if (!mLanguageChanged) { LLNotificationsUtil::add("ChangeLanguage"); mLanguageChanged = true; } } void LLFloaterPreference::onNotificationsChange(const std::string& OptionName) { mNotificationOptions[OptionName] = getChild(OptionName)->getSelectedItemLabel(); bool show_notifications_alert = true; for (notifications_map::iterator it_notification = mNotificationOptions.begin(); it_notification != mNotificationOptions.end(); it_notification++) { if(it_notification->second != "No action") { show_notifications_alert = false; break; } } getChild("notifications_alert")->setVisible(show_notifications_alert); } void LLFloaterPreference::onNameTagOpacityChange(const LLSD& newvalue) { LLColorSwatchCtrl* color_swatch = findChild("background"); if (color_swatch) { LLColor4 new_color = color_swatch->get(); color_swatch->set( new_color.setAlpha(newvalue.asReal()) ); } } void LLFloaterPreference::onClickSetCache() { std::string cur_name(gSavedSettings.getString("CacheLocation")); // std::string cur_top_folder(gDirUtilp->getBaseFileName(cur_name)); std::string proposed_name(cur_name); LLDirPicker& picker = LLDirPicker::instance(); if (! picker.getDir(&proposed_name ) ) { return; //Canceled! } std::string dir_name = picker.getDirName(); if (!dir_name.empty() && dir_name != cur_name) { std::string new_top_folder(gDirUtilp->getBaseFileName(dir_name)); LLNotificationsUtil::add("CacheWillBeMoved"); gSavedSettings.setString("NewCacheLocation", dir_name); gSavedSettings.setString("NewCacheLocationTopFolder", new_top_folder); } else { std::string cache_location = gDirUtilp->getCacheDir(); gSavedSettings.setString("CacheLocation", cache_location); std::string top_folder(gDirUtilp->getBaseFileName(cache_location)); gSavedSettings.setString("CacheLocationTopFolder", top_folder); } } void LLFloaterPreference::onClickResetCache() { if (gDirUtilp->getCacheDir(false) == gDirUtilp->getCacheDir(true)) { // The cache location was already the default. return; } gSavedSettings.setString("NewCacheLocation", ""); gSavedSettings.setString("NewCacheLocationTopFolder", ""); LLNotificationsUtil::add("CacheWillBeMoved"); std::string cache_location = gDirUtilp->getCacheDir(false); gSavedSettings.setString("CacheLocation", cache_location); std::string top_folder(gDirUtilp->getBaseFileName(cache_location)); gSavedSettings.setString("CacheLocationTopFolder", top_folder); } void LLFloaterPreference::onClickSkin(LLUICtrl* ctrl, const LLSD& userdata) { gSavedSettings.setString("SkinCurrent", userdata.asString()); ctrl->setValue(userdata.asString()); } void LLFloaterPreference::onSelectSkin() { std::string skin_selection = getChild("skin_selection")->getValue().asString(); gSavedSettings.setString("SkinCurrent", skin_selection); } void LLFloaterPreference::refreshSkin(void* data) { LLPanel*self = (LLPanel*)data; sSkin = gSavedSettings.getString("SkinCurrent"); self->getChild("skin_selection", true)->setValue(sSkin); } void LLFloaterPreference::buildPopupLists() { LLScrollListCtrl& disabled_popups = getChildRef("disabled_popups"); LLScrollListCtrl& enabled_popups = getChildRef("enabled_popups"); disabled_popups.deleteAllItems(); enabled_popups.deleteAllItems(); for (LLNotifications::TemplateMap::const_iterator iter = LLNotifications::instance().templatesBegin(); iter != LLNotifications::instance().templatesEnd(); ++iter) { LLNotificationTemplatePtr templatep = iter->second; LLNotificationFormPtr formp = templatep->mForm; LLNotificationForm::EIgnoreType ignore = formp->getIgnoreType(); if (ignore == LLNotificationForm::IGNORE_NO) continue; LLSD row; row["columns"][0]["value"] = formp->getIgnoreMessage(); row["columns"][0]["font"] = "SANSSERIF_SMALL"; row["columns"][0]["width"] = 400; LLScrollListItem* item = NULL; bool show_popup = !formp->getIgnored(); if (!show_popup) { if (ignore == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE) { LLSD last_response = LLUI::sSettingGroups["config"]->getLLSD("Default" + templatep->mName); if (!last_response.isUndefined()) { for (LLSD::map_const_iterator it = last_response.beginMap(); it != last_response.endMap(); ++it) { if (it->second.asBoolean()) { row["columns"][1]["value"] = formp->getElement(it->first)["ignore"].asString(); break; } } } row["columns"][1]["font"] = "SANSSERIF_SMALL"; row["columns"][1]["width"] = 360; } item = disabled_popups.addElement(row); } else { item = enabled_popups.addElement(row); } if (item) { item->setUserdata((void*)&iter->first); } } } void LLFloaterPreference::refreshEnabledState() { LLComboBox* ctrl_reflections = getChild("Reflections"); LLRadioGroup* radio_reflection_detail = getChild("ReflectionDetailRadio"); // Reflections BOOL reflections = gSavedSettings.getBOOL("VertexShaderEnable") && gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps; ctrl_reflections->setEnabled(reflections); // Bump & Shiny LLCheckBoxCtrl* bumpshiny_ctrl = getChild("BumpShiny"); bool bumpshiny = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps && LLFeatureManager::getInstance()->isFeatureAvailable("RenderObjectBump"); bumpshiny_ctrl->setEnabled(bumpshiny ? TRUE : FALSE); radio_reflection_detail->setEnabled(reflections); LLCheckBoxCtrl* ctrl_enhanced_skel = getChild("AvatarEnhancedSkeleton"); bool enhanced_skel_enabled = gSavedSettings.getBOOL("IncludeEnhancedSkeleton"); ctrl_enhanced_skel->setValue(enhanced_skel_enabled); // Avatar Mode // Enable Avatar Shaders LLCheckBoxCtrl* ctrl_avatar_vp = getChild("AvatarVertexProgram"); // Avatar Render Mode LLCheckBoxCtrl* ctrl_avatar_cloth = getChild("AvatarCloth"); bool avatar_vp_enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarVP"); if (LLViewerShaderMgr::sInitialized) { S32 max_avatar_shader = LLViewerShaderMgr::instance()->mMaxAvatarShaderLevel; avatar_vp_enabled = (max_avatar_shader > 0) ? TRUE : FALSE; } ctrl_avatar_vp->setEnabled(avatar_vp_enabled); if (gSavedSettings.getBOOL("VertexShaderEnable") == FALSE || gSavedSettings.getBOOL("RenderAvatarVP") == FALSE) { ctrl_avatar_cloth->setEnabled(false); } else { ctrl_avatar_cloth->setEnabled(true); } // Vertex Shaders // Global Shader Enable LLCheckBoxCtrl* ctrl_shader_enable = getChild("BasicShaders"); // radio set for terrain detail mode LLRadioGroup* mRadioTerrainDetail = getChild("TerrainDetailRadio"); // can be linked with control var ctrl_shader_enable->setEnabled(LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable")); BOOL shaders = ctrl_shader_enable->get(); if (shaders) { mRadioTerrainDetail->setValue(1); mRadioTerrainDetail->setEnabled(FALSE); } else { mRadioTerrainDetail->setEnabled(TRUE); } // WindLight LLCheckBoxCtrl* ctrl_wind_light = getChild("WindLightUseAtmosShaders"); // *HACK just checks to see if we can use shaders... // maybe some cards that use shaders, but don't support windlight ctrl_wind_light->setEnabled(ctrl_shader_enable->getEnabled() && shaders); //Deferred/SSAO/Shadows LLCheckBoxCtrl* ctrl_deferred = getChild("UseLightShaders"); LLCheckBoxCtrl* ctrl_deferred2 = getChild("UseLightShaders2"); BOOL enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") && ((bumpshiny_ctrl && bumpshiny_ctrl->get()) ? TRUE : FALSE) && shaders && gGLManager.mHasFramebufferObject && gSavedSettings.getBOOL("RenderAvatarVP") && (ctrl_wind_light->get()) ? TRUE : FALSE; ctrl_deferred->setEnabled(enabled); ctrl_deferred2->setEnabled(enabled); LLCheckBoxCtrl* ctrl_ssao = getChild("UseSSAO"); LLCheckBoxCtrl* ctrl_dof = getChild("UseDoF"); LLComboBox* ctrl_shadow = getChild("ShadowDetail"); // note, okay here to get from ctrl_deferred as it's twin, ctrl_deferred2 will alway match it enabled = enabled && LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferredSSAO") && (ctrl_deferred->get() ? TRUE : FALSE); ctrl_deferred->set(gSavedSettings.getBOOL("RenderDeferred")); ctrl_ssao->setEnabled(enabled); ctrl_dof->setEnabled(enabled); enabled = enabled && LLFeatureManager::getInstance()->isFeatureAvailable("RenderShadowDetail"); ctrl_shadow->setEnabled(enabled); // now turn off any features that are unavailable disableUnavailableSettings(); getChildView("block_list")->setEnabled(LLLoginInstance::getInstance()->authSuccess()); // Cannot have floater active until caps have been received getChild("default_creation_permissions")->setEnabled(LLStartUp::getStartupState() < STATE_STARTED ? false : true); } void LLFloaterPreference::disableUnavailableSettings() { LLComboBox* ctrl_reflections = getChild("Reflections"); LLCheckBoxCtrl* ctrl_avatar_vp = getChild("AvatarVertexProgram"); LLCheckBoxCtrl* ctrl_avatar_cloth = getChild("AvatarCloth"); LLCheckBoxCtrl* ctrl_shader_enable = getChild("BasicShaders"); LLCheckBoxCtrl* ctrl_wind_light = getChild("WindLightUseAtmosShaders"); LLCheckBoxCtrl* ctrl_avatar_impostors = getChild("AvatarImpostors"); LLCheckBoxCtrl* ctrl_deferred = getChild("UseLightShaders"); LLCheckBoxCtrl* ctrl_deferred2 = getChild("UseLightShaders2"); LLComboBox* ctrl_shadows = getChild("ShadowDetail"); LLCheckBoxCtrl* ctrl_ssao = getChild("UseSSAO"); LLCheckBoxCtrl* ctrl_dof = getChild("UseDoF"); // if vertex shaders off, disable all shader related products if (!LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable")) { ctrl_shader_enable->setEnabled(FALSE); ctrl_shader_enable->setValue(FALSE); ctrl_wind_light->setEnabled(FALSE); ctrl_wind_light->setValue(FALSE); ctrl_reflections->setEnabled(FALSE); ctrl_reflections->setValue(0); ctrl_avatar_vp->setEnabled(FALSE); ctrl_avatar_vp->setValue(FALSE); ctrl_avatar_cloth->setEnabled(FALSE); ctrl_avatar_cloth->setValue(FALSE); ctrl_shadows->setEnabled(FALSE); ctrl_shadows->setValue(0); ctrl_ssao->setEnabled(FALSE); ctrl_ssao->setValue(FALSE); ctrl_dof->setEnabled(FALSE); ctrl_dof->setValue(FALSE); ctrl_deferred->setEnabled(FALSE); ctrl_deferred->setValue(FALSE); ctrl_deferred2->setEnabled(FALSE); ctrl_deferred2->setValue(FALSE); } // disabled windlight if (!LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders")) { ctrl_wind_light->setEnabled(FALSE); ctrl_wind_light->setValue(FALSE); //deferred needs windlight, disable deferred ctrl_shadows->setEnabled(FALSE); ctrl_shadows->setValue(0); ctrl_ssao->setEnabled(FALSE); ctrl_ssao->setValue(FALSE); ctrl_dof->setEnabled(FALSE); ctrl_dof->setValue(FALSE); ctrl_deferred->setEnabled(FALSE); ctrl_deferred->setValue(FALSE); ctrl_deferred2->setEnabled(FALSE); ctrl_deferred2->setValue(FALSE); } // disabled deferred if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") || !gGLManager.mHasFramebufferObject) { ctrl_shadows->setEnabled(FALSE); ctrl_shadows->setValue(0); ctrl_ssao->setEnabled(FALSE); ctrl_ssao->setValue(FALSE); ctrl_dof->setEnabled(FALSE); ctrl_dof->setValue(FALSE); ctrl_deferred->setEnabled(FALSE); ctrl_deferred->setValue(FALSE); ctrl_deferred2->setEnabled(FALSE); ctrl_deferred2->setValue(FALSE); } // disabled deferred SSAO if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferredSSAO")) { ctrl_ssao->setEnabled(FALSE); ctrl_ssao->setValue(FALSE); } // disabled deferred shadows if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderShadowDetail")) { ctrl_shadows->setEnabled(FALSE); ctrl_shadows->setValue(0); } // disabled reflections if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderReflectionDetail")) { ctrl_reflections->setEnabled(FALSE); ctrl_reflections->setValue(FALSE); } // disabled av if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarVP")) { ctrl_avatar_vp->setEnabled(FALSE); ctrl_avatar_vp->setValue(FALSE); ctrl_avatar_cloth->setEnabled(FALSE); ctrl_avatar_cloth->setValue(FALSE); //deferred needs AvatarVP, disable deferred ctrl_shadows->setEnabled(FALSE); ctrl_shadows->setValue(0); ctrl_ssao->setEnabled(FALSE); ctrl_ssao->setValue(FALSE); ctrl_dof->setEnabled(FALSE); ctrl_dof->setValue(FALSE); ctrl_deferred->setEnabled(FALSE); ctrl_deferred->setValue(FALSE); ctrl_deferred2->setEnabled(FALSE); ctrl_deferred2->setValue(FALSE); } // disabled cloth if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarCloth")) { ctrl_avatar_cloth->setEnabled(FALSE); ctrl_avatar_cloth->setValue(FALSE); } // disabled impostors if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderUseImpostors")) { ctrl_avatar_impostors->setEnabled(FALSE); ctrl_avatar_impostors->setValue(FALSE); } } void LLFloaterPreference::refresh() { LLPanel::refresh(); // sliders and their text boxes // mPostProcess = gSavedSettings.getS32("RenderGlowResolutionPow"); // slider text boxes updateSliderText(getChild("ObjectMeshDetail", true), getChild("ObjectMeshDetailText", true)); updateSliderText(getChild("FlexibleMeshDetail", true), getChild("FlexibleMeshDetailText", true)); updateSliderText(getChild("TreeMeshDetail", true), getChild("TreeMeshDetailText", true)); updateSliderText(getChild("AvatarMeshDetail", true), getChild("AvatarMeshDetailText", true)); updateSliderText(getChild("AvatarMeshDetail2", true), getChild("AvatarMeshDetailText2", true)); updateSliderText(getChild("AvatarPhysicsDetail", true), getChild("AvatarPhysicsDetailText", true)); updateSliderText(getChild("TerrainMeshDetail", true), getChild("TerrainMeshDetailText", true)); updateSliderText(getChild("RenderPostProcess", true), getChild("PostProcessText", true)); updateSliderText(getChild("SkyMeshDetail", true), getChild("SkyMeshDetailText", true)); refreshEnabledState(); } void LLFloaterPreference::onCommitWindowedMode() { refresh(); } void LLFloaterPreference::onChangeQuality(const LLSD& data) { U32 level = (U32)(data.asReal()); LLFeatureManager::getInstance()->setGraphicsLevel(level, true); refreshEnabledGraphics(); refresh(); } void LLFloaterPreference::onClickSetKey() { LLVoiceSetKeyDialog* dialog = LLFloaterReg::showTypedInstance("voice_set_key", LLSD(), TRUE); if (dialog) { dialog->setParent(this); } } void LLFloaterPreference::setKey(KEY key) { getChild("modifier_combo")->setValue(LLKeyboard::stringFromKey(key)); // update the control right away since we no longer wait for apply getChild("modifier_combo")->onCommit(); } void LLFloaterPreference::onClickSetMiddleMouse() { LLUICtrl* p2t_line_editor = getChild("modifier_combo"); // update the control right away since we no longer wait for apply p2t_line_editor->setControlValue(MIDDLE_MOUSE_CV); //push2talk button "middle mouse" control value is in English, need to localize it for presentation LLPanel* advanced_preferences = dynamic_cast(p2t_line_editor->getParent()); if (advanced_preferences) { p2t_line_editor->setValue(advanced_preferences->getString("middle_mouse")); } } void LLFloaterPreference::onClickSetSounds() { // Disable Enable gesture sounds checkbox if the master sound is disabled // or if sound effects are disabled. getChild("gesture_audio_play_btn")->setEnabled(!gSavedSettings.getBOOL("MuteSounds")); } /* void LLFloaterPreference::onClickSkipDialogs() { LLNotificationsUtil::add("SkipShowNextTimeDialogs", LLSD(), LLSD(), boost::bind(&callback_skip_dialogs, _1, _2, this)); } void LLFloaterPreference::onClickResetDialogs() { LLNotificationsUtil::add("ResetShowNextTimeDialogs", LLSD(), LLSD(), boost::bind(&callback_reset_dialogs, _1, _2, this)); } */ void LLFloaterPreference::onClickEnablePopup() { LLScrollListCtrl& disabled_popups = getChildRef("disabled_popups"); std::vector items = disabled_popups.getAllSelected(); std::vector::iterator itor; for (itor = items.begin(); itor != items.end(); ++itor) { LLNotificationTemplatePtr templatep = LLNotifications::instance().getTemplate(*(std::string*)((*itor)->getUserdata())); //gSavedSettings.setWarning(templatep->mName, TRUE); std::string notification_name = templatep->mName; LLUI::sSettingGroups["ignores"]->setBOOL(notification_name, TRUE); } buildPopupLists(); } void LLFloaterPreference::onClickDisablePopup() { LLScrollListCtrl& enabled_popups = getChildRef("enabled_popups"); std::vector items = enabled_popups.getAllSelected(); std::vector::iterator itor; for (itor = items.begin(); itor != items.end(); ++itor) { LLNotificationTemplatePtr templatep = LLNotifications::instance().getTemplate(*(std::string*)((*itor)->getUserdata())); templatep->mForm->setIgnored(true); } buildPopupLists(); } void LLFloaterPreference::resetAllIgnored() { for (LLNotifications::TemplateMap::const_iterator iter = LLNotifications::instance().templatesBegin(); iter != LLNotifications::instance().templatesEnd(); ++iter) { if (iter->second->mForm->getIgnoreType() != LLNotificationForm::IGNORE_NO) { iter->second->mForm->setIgnored(false); } } } void LLFloaterPreference::setAllIgnored() { for (LLNotifications::TemplateMap::const_iterator iter = LLNotifications::instance().templatesBegin(); iter != LLNotifications::instance().templatesEnd(); ++iter) { if (iter->second->mForm->getIgnoreType() != LLNotificationForm::IGNORE_NO) { iter->second->mForm->setIgnored(true); } } } void LLFloaterPreference::onClickLogPath() { std::string proposed_name(gSavedPerAccountSettings.getString("InstantMessageLogPath")); mPriorInstantMessageLogPath.clear(); LLDirPicker& picker = LLDirPicker::instance(); //Launches a directory picker and waits for feedback if (!picker.getDir(&proposed_name ) ) { return; //Canceled! } //Gets the path from the directory picker std::string dir_name = picker.getDirName(); //Path changed if(proposed_name != dir_name) { gSavedPerAccountSettings.setString("InstantMessageLogPath", dir_name); mPriorInstantMessageLogPath = proposed_name; // enable/disable 'Delete transcripts button updateDeleteTranscriptsButton(); } } bool LLFloaterPreference::moveTranscriptsAndLog() { std::string instantMessageLogPath(gSavedPerAccountSettings.getString("InstantMessageLogPath")); std::string chatLogPath = gDirUtilp->add(instantMessageLogPath, gDirUtilp->getUserName()); bool madeDirectory = false; //Does the directory really exist, if not then make it if(!LLFile::isdir(chatLogPath)) { //mkdir success is defined as zero if(LLFile::mkdir(chatLogPath) != 0) { return false; } madeDirectory = true; } std::string originalConversationLogDir = LLConversationLog::instance().getFileName(); std::string targetConversationLogDir = gDirUtilp->add(chatLogPath, "conversation.log"); //Try to move the conversation log if(!LLConversationLog::instance().moveLog(originalConversationLogDir, targetConversationLogDir)) { //Couldn't move the log and created a new directory so remove the new directory if(madeDirectory) { LLFile::rmdir(chatLogPath); } return false; } //Attempt to move transcripts std::vector listOfTranscripts; std::vector listOfFilesMoved; LLLogChat::getListOfTranscriptFiles(listOfTranscripts); if(!LLLogChat::moveTranscripts(gDirUtilp->getChatLogsDir(), instantMessageLogPath, listOfTranscripts, listOfFilesMoved)) { //Couldn't move all the transcripts so restore those that moved back to their old location LLLogChat::moveTranscripts(instantMessageLogPath, gDirUtilp->getChatLogsDir(), listOfFilesMoved); //Move the conversation log back LLConversationLog::instance().moveLog(targetConversationLogDir, originalConversationLogDir); if(madeDirectory) { LLFile::rmdir(chatLogPath); } return false; } gDirUtilp->setChatLogsDir(instantMessageLogPath); gDirUtilp->updatePerAccountChatLogsDir(); return true; } void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im_via_email) { mGotPersonalInfo = true; mOriginalIMViaEmail = im_via_email; mDirectoryVisibility = visibility; if (visibility == VISIBILITY_DEFAULT) { mOriginalHideOnlineStatus = false; getChildView("online_visibility")->setEnabled(TRUE); } else if (visibility == VISIBILITY_HIDDEN) { mOriginalHideOnlineStatus = true; getChildView("online_visibility")->setEnabled(TRUE); } else { mOriginalHideOnlineStatus = true; } getChild("online_searchresults")->setEnabled(TRUE); getChildView("friends_online_notify_checkbox")->setEnabled(TRUE); getChild("online_visibility")->setValue(mOriginalHideOnlineStatus); getChild("online_visibility")->setLabelArg("[DIR_VIS]", mDirectoryVisibility); getChildView("send_im_to_email")->setEnabled(TRUE); getChild("send_im_to_email")->setValue(im_via_email); getChildView("favorites_on_login_check")->setEnabled(TRUE); getChildView("log_path_button")->setEnabled(TRUE); getChildView("chat_font_size")->setEnabled(TRUE); } void LLFloaterPreference::refreshUI() { refresh(); } void LLFloaterPreference::updateSliderText(LLSliderCtrl* ctrl, LLTextBox* text_box) { if (text_box == NULL || ctrl== NULL) return; // get range and points when text should change F32 value = (F32)ctrl->getValue().asReal(); F32 min = ctrl->getMinValue(); F32 max = ctrl->getMaxValue(); F32 range = max - min; llassert(range > 0); F32 midPoint = min + range / 3.0f; F32 highPoint = min + (2.0f * range / 3.0f); // choose the right text if (value < midPoint) { text_box->setText(LLTrans::getString("GraphicsQualityLow")); } else if (value < highPoint) { text_box->setText(LLTrans::getString("GraphicsQualityMid")); } else { text_box->setText(LLTrans::getString("GraphicsQualityHigh")); } } void LLFloaterPreference::onChangeMaturity() { U8 sim_access = gSavedSettings.getU32("PreferredMaturity"); getChild("rating_icon_general")->setVisible(sim_access == SIM_ACCESS_PG || sim_access == SIM_ACCESS_MATURE || sim_access == SIM_ACCESS_ADULT); getChild("rating_icon_moderate")->setVisible(sim_access == SIM_ACCESS_MATURE || sim_access == SIM_ACCESS_ADULT); getChild("rating_icon_adult")->setVisible(sim_access == SIM_ACCESS_ADULT); } // FIXME: this will stop you from spawning the sidetray from preferences dialog on login screen // but the UI for this will still be enabled void LLFloaterPreference::onClickBlockList() { LLFloaterSidePanelContainer::showPanel("people", "panel_people", LLSD().with("people_panel_tab_name", "blocked_panel")); } void LLFloaterPreference::onClickProxySettings() { LLFloaterReg::showInstance("prefs_proxy"); } void LLFloaterPreference::onClickTranslationSettings() { LLFloaterReg::showInstance("prefs_translation"); } void LLFloaterPreference::onClickAutoReplace() { LLFloaterReg::showInstance("prefs_autoreplace"); } void LLFloaterPreference::onClickSpellChecker() { LLFloaterReg::showInstance("prefs_spellchecker"); } void LLFloaterPreference::onClickActionChange() { mClickActionDirty = true; } void LLFloaterPreference::onClickPermsDefault() { LLFloaterReg::showInstance("perms_default"); } void LLFloaterPreference::onDeleteTranscripts() { LLSD args; args["FOLDER"] = gDirUtilp->getUserName(); LLNotificationsUtil::add("PreferenceChatDeleteTranscripts", args, LLSD(), boost::bind(&LLFloaterPreference::onDeleteTranscriptsResponse, this, _1, _2)); } void LLFloaterPreference::onDeleteTranscriptsResponse(const LLSD& notification, const LLSD& response) { if (0 == LLNotificationsUtil::getSelectedOption(notification, response)) { LLLogChat::deleteTranscripts(); updateDeleteTranscriptsButton(); } } void LLFloaterPreference::onLogChatHistorySaved() { LLButton * delete_transcripts_buttonp = getChild("delete_transcripts"); if (!delete_transcripts_buttonp->getEnabled()) { delete_transcripts_buttonp->setEnabled(true); } } void LLFloaterPreference::updateClickActionSettings() { const int single_clk_action = getChild("single_click_action_combo")->getValue().asInteger(); const int double_clk_action = getChild("double_click_action_combo")->getValue().asInteger(); gSavedSettings.setBOOL("ClickToWalk", single_clk_action == 1); gSavedSettings.setBOOL("DoubleClickAutoPilot", double_clk_action == 1); gSavedSettings.setBOOL("DoubleClickTeleport", double_clk_action == 2); } void LLFloaterPreference::updateClickActionControls() { const bool click_to_walk = gSavedSettings.getBOOL("ClickToWalk"); const bool dbl_click_to_walk = gSavedSettings.getBOOL("DoubleClickAutoPilot"); const bool dbl_click_to_teleport = gSavedSettings.getBOOL("DoubleClickTeleport"); getChild("single_click_action_combo")->setValue((int)click_to_walk); getChild("double_click_action_combo")->setValue(dbl_click_to_teleport ? 2 : (int)dbl_click_to_walk); } void LLFloaterPreference::applyUIColor(LLUICtrl* ctrl, const LLSD& param) { LLUIColorTable::instance().setColor(param.asString(), LLColor4(ctrl->getValue())); } void LLFloaterPreference::getUIColor(LLUICtrl* ctrl, const LLSD& param) { LLColorSwatchCtrl* color_swatch = (LLColorSwatchCtrl*) ctrl; color_swatch->setOriginal(LLUIColorTable::instance().getColor(param.asString())); } void LLFloaterPreference::setCacheLocation(const LLStringExplicit& location) { LLUICtrl* cache_location_editor = getChild("cache_location"); cache_location_editor->setValue(location); cache_location_editor->setToolTip(location); } void LLFloaterPreference::selectPanel(const LLSD& name) { LLTabContainer * tab_containerp = getChild("pref core"); LLPanel * panel = tab_containerp->getPanelByName(name); if (NULL != panel) { tab_containerp->selectTabPanel(panel); } } void LLFloaterPreference::selectPrivacyPanel() { selectPanel("im"); } void LLFloaterPreference::selectChatPanel() { selectPanel("chat"); } void LLFloaterPreference::changed() { getChild("clear_log")->setEnabled(LLConversationLog::instance().getConversations().size() > 0); // set 'enable' property for 'Delete transcripts...' button updateDeleteTranscriptsButton(); } //------------------------------Updater--------------------------------------- static bool handleBandwidthChanged(const LLSD& newvalue) { gViewerThrottle.setMaxBandwidth((F32) newvalue.asReal()); return true; } class LLPanelPreference::Updater : public LLEventTimer { public: typedef boost::function callback_t; Updater(callback_t cb, F32 period) :LLEventTimer(period), mCallback(cb) { mEventTimer.stop(); } virtual ~Updater(){} void update(const LLSD& new_value) { mNewValue = new_value; mEventTimer.start(); } protected: BOOL tick() { mCallback(mNewValue); mEventTimer.stop(); return FALSE; } private: LLSD mNewValue; callback_t mCallback; }; //---------------------------------------------------------------------------- static LLPanelInjector t_places("panel_preference"); LLPanelPreference::LLPanelPreference() : LLPanel(), mBandWidthUpdater(NULL) { mCommitCallbackRegistrar.add("Pref.setControlFalse", boost::bind(&LLPanelPreference::setControlFalse,this, _2)); mCommitCallbackRegistrar.add("Pref.updateMediaAutoPlayCheckbox", boost::bind(&LLPanelPreference::updateMediaAutoPlayCheckbox, this, _1)); } //virtual BOOL LLPanelPreference::postBuild() { ////////////////////// PanelGeneral /////////////////// if (hasChild("display_names_check", TRUE)) { BOOL use_people_api = gSavedSettings.getBOOL("UsePeopleAPI"); LLCheckBoxCtrl* ctrl_display_name = getChild("display_names_check"); ctrl_display_name->setEnabled(use_people_api); if (!use_people_api) { ctrl_display_name->setValue(FALSE); } } ////////////////////// PanelVoice /////////////////// if (hasChild("voice_unavailable", TRUE)) { BOOL voice_disabled = gSavedSettings.getBOOL("CmdLineDisableVoice"); getChildView("voice_unavailable")->setVisible( voice_disabled); getChildView("enable_voice_check")->setVisible( !voice_disabled); } //////////////////////PanelSkins /////////////////// if (hasChild("skin_selection", TRUE)) { LLFloaterPreference::refreshSkin(this); // if skin is set to a skin that no longer exists (silver) set back to default if (getChild("skin_selection")->getSelectedIndex() < 0) { gSavedSettings.setString("SkinCurrent", "default"); LLFloaterPreference::refreshSkin(this); } } //////////////////////PanelPrivacy /////////////////// if (hasChild("media_enabled", TRUE)) { bool media_enabled = gSavedSettings.getBOOL("AudioStreamingMedia"); getChild("media_enabled")->set(media_enabled); getChild("autoplay_enabled")->setEnabled(media_enabled); } if (hasChild("music_enabled", TRUE)) { getChild("music_enabled")->set(gSavedSettings.getBOOL("AudioStreamingMusic")); } if (hasChild("voice_call_friends_only_check", TRUE)) { getChild("voice_call_friends_only_check")->setCommitCallback(boost::bind(&showFriendsOnlyWarning, _1, _2)); } if (hasChild("favorites_on_login_check", TRUE)) { getChild("favorites_on_login_check")->setCommitCallback(boost::bind(&handleFavoritesOnLoginChanged, _1, _2)); bool show_favorites_at_login = LLPanelLogin::getShowFavorites(); getChild("favorites_on_login_check")->setValue(show_favorites_at_login); } //////////////////////PanelAdvanced /////////////////// if (hasChild("modifier_combo", TRUE)) { //localizing if push2talk button is set to middle mouse if (MIDDLE_MOUSE_CV == getChild("modifier_combo")->getValue().asString()) { getChild("modifier_combo")->setValue(getString("middle_mouse")); } } //////////////////////PanelSetup /////////////////// if (hasChild("max_bandwidth"), TRUE) { mBandWidthUpdater = new LLPanelPreference::Updater(boost::bind(&handleBandwidthChanged, _1), BANDWIDTH_UPDATER_TIMEOUT); gSavedSettings.getControl("ThrottleBandwidthKBPS")->getSignal()->connect(boost::bind(&LLPanelPreference::Updater::update, mBandWidthUpdater, _2)); } #ifdef EXTERNAL_TOS LLRadioGroup* ext_browser_settings = getChild("preferred_browser_behavior"); if (ext_browser_settings) { // turn off ability to set external/internal browser ext_browser_settings->setSelectedByValue(LLWeb::BROWSER_EXTERNAL_ONLY, true); ext_browser_settings->setEnabled(false); } #endif apply(); return true; } LLPanelPreference::~LLPanelPreference() { if (mBandWidthUpdater) { delete mBandWidthUpdater; } } void LLPanelPreference::apply() { // no-op } void LLPanelPreference::saveSettings() { // Save the value of all controls in the hierarchy mSavedValues.clear(); std::list view_stack; view_stack.push_back(this); while(!view_stack.empty()) { // Process view on top of the stack LLView* curview = view_stack.front(); view_stack.pop_front(); LLColorSwatchCtrl* color_swatch = dynamic_cast(curview); if (color_swatch) { mSavedColors[color_swatch->getName()] = color_swatch->get(); } else { LLUICtrl* ctrl = dynamic_cast(curview); if (ctrl) { LLControlVariable* control = ctrl->getControlVariable(); if (control) { mSavedValues[control] = control->getValue(); } } } // Push children onto the end of the work stack for (child_list_t::const_iterator iter = curview->getChildList()->begin(); iter != curview->getChildList()->end(); ++iter) { view_stack.push_back(*iter); } } } void LLPanelPreference::showFriendsOnlyWarning(LLUICtrl* checkbox, const LLSD& value) { if (checkbox && checkbox->getValue()) { LLNotificationsUtil::add("FriendsAndGroupsOnly"); } } void LLPanelPreference::handleFavoritesOnLoginChanged(LLUICtrl* checkbox, const LLSD& value) { if (checkbox) { LLFavoritesOrderStorage::instance().showFavoritesOnLoginChanged(checkbox->getValue().asBoolean()); if(checkbox->getValue()) { LLNotificationsUtil::add("FavoritesOnLogin"); } } } void LLPanelPreference::cancel() { for (control_values_map_t::iterator iter = mSavedValues.begin(); iter != mSavedValues.end(); ++iter) { LLControlVariable* control = iter->first; LLSD ctrl_value = iter->second; if((control->getName() == "InstantMessageLogPath") && (ctrl_value.asString() == "")) { continue; } control->set(ctrl_value); } for (string_color_map_t::iterator iter = mSavedColors.begin(); iter != mSavedColors.end(); ++iter) { LLColorSwatchCtrl* color_swatch = findChild(iter->first); if (color_swatch) { color_swatch->set(iter->second); color_swatch->onCommit(); } } } void LLPanelPreference::setControlFalse(const LLSD& user_data) { std::string control_name = user_data.asString(); LLControlVariable* control = findControl(control_name); if (control) control->set(LLSD(FALSE)); } void LLPanelPreference::updateMediaAutoPlayCheckbox(LLUICtrl* ctrl) { std::string name = ctrl->getName(); // Disable "Allow Media to auto play" only when both // "Streaming Music" and "Media" are unchecked. STORM-513. if ((name == "enable_music") || (name == "enable_media")) { bool music_enabled = getChild("enable_music")->get(); bool media_enabled = getChild("enable_media")->get(); getChild("media_auto_play_btn")->setEnabled(music_enabled || media_enabled); } } class LLPanelPreferencePrivacy : public LLPanelPreference { public: LLPanelPreferencePrivacy() { mAccountIndependentSettings.push_back("VoiceCallsFriendsOnly"); mAccountIndependentSettings.push_back("AutoDisengageMic"); } /*virtual*/ void saveSettings() { LLPanelPreference::saveSettings(); // Don't save (=erase from the saved values map) per-account privacy settings // if we're not logged in, otherwise they will be reset to defaults on log off. if (LLStartUp::getStartupState() != STATE_STARTED) { // Erase only common settings, assuming there are no color settings on Privacy page. for (control_values_map_t::iterator it = mSavedValues.begin(); it != mSavedValues.end(); ) { const std::string setting = it->first->getName(); if (find(mAccountIndependentSettings.begin(), mAccountIndependentSettings.end(), setting) == mAccountIndependentSettings.end()) { mSavedValues.erase(it++); } else { ++it; } } } } private: std::list mAccountIndependentSettings; }; static LLPanelInjector t_pref_graph("panel_preference_graphics"); static LLPanelInjector t_pref_privacy("panel_preference_privacy"); BOOL LLPanelPreferenceGraphics::postBuild() { return LLPanelPreference::postBuild(); } void LLPanelPreferenceGraphics::draw() { LLPanelPreference::draw(); LLButton* button_apply = findChild("Apply"); if (button_apply && button_apply->getVisible()) { bool enable = hasDirtyChilds(); button_apply->setEnabled(enable); } } bool LLPanelPreferenceGraphics::hasDirtyChilds() { std::list view_stack; view_stack.push_back(this); while(!view_stack.empty()) { // Process view on top of the stack LLView* curview = view_stack.front(); view_stack.pop_front(); LLUICtrl* ctrl = dynamic_cast(curview); if (ctrl) { if (ctrl->isDirty()) return true; } // Push children onto the end of the work stack for (child_list_t::const_iterator iter = curview->getChildList()->begin(); iter != curview->getChildList()->end(); ++iter) { view_stack.push_back(*iter); } } return false; } void LLPanelPreferenceGraphics::resetDirtyChilds() { std::list view_stack; view_stack.push_back(this); while(!view_stack.empty()) { // Process view on top of the stack LLView* curview = view_stack.front(); view_stack.pop_front(); LLUICtrl* ctrl = dynamic_cast(curview); if (ctrl) { ctrl->resetDirty(); } // Push children onto the end of the work stack for (child_list_t::const_iterator iter = curview->getChildList()->begin(); iter != curview->getChildList()->end(); ++iter) { view_stack.push_back(*iter); } } } void LLPanelPreferenceGraphics::apply() { resetDirtyChilds(); LLPanelPreference::apply(); } void LLPanelPreferenceGraphics::cancel() { resetDirtyChilds(); LLPanelPreference::cancel(); } void LLPanelPreferenceGraphics::saveSettings() { resetDirtyChilds(); LLPanelPreference::saveSettings(); } void LLPanelPreferenceGraphics::setHardwareDefaults() { resetDirtyChilds(); LLPanelPreference::setHardwareDefaults(); } LLFloaterPreferenceProxy::LLFloaterPreferenceProxy(const LLSD& key) : LLFloater(key), mSocksSettingsDirty(false) { mCommitCallbackRegistrar.add("Proxy.OK", boost::bind(&LLFloaterPreferenceProxy::onBtnOk, this)); mCommitCallbackRegistrar.add("Proxy.Cancel", boost::bind(&LLFloaterPreferenceProxy::onBtnCancel, this)); mCommitCallbackRegistrar.add("Proxy.Change", boost::bind(&LLFloaterPreferenceProxy::onChangeSocksSettings, this)); } LLFloaterPreferenceProxy::~LLFloaterPreferenceProxy() { } BOOL LLFloaterPreferenceProxy::postBuild() { LLRadioGroup* socksAuth = getChild("socks5_auth_type"); if (!socksAuth) { return FALSE; } if (socksAuth->getSelectedValue().asString() == "None") { getChild("socks5_username")->setEnabled(false); getChild("socks5_password")->setEnabled(false); } else { // Populate the SOCKS 5 credential fields with protected values. LLPointer socks_cred = gSecAPIHandler->loadCredential("SOCKS5"); getChild("socks5_username")->setValue(socks_cred->getIdentifier()["username"].asString()); getChild("socks5_password")->setValue(socks_cred->getAuthenticator()["creds"].asString()); } return TRUE; } void LLFloaterPreferenceProxy::onOpen(const LLSD& key) { saveSettings(); } void LLFloaterPreferenceProxy::onClose(bool app_quitting) { if(app_quitting) { cancel(); } if (mSocksSettingsDirty) { // If the user plays with the Socks proxy settings after login, it's only fair we let them know // it will not be updated until next restart. if (LLStartUp::getStartupState()>STATE_LOGIN_WAIT) { LLNotifications::instance().add("ChangeProxySettings", LLSD(), LLSD()); mSocksSettingsDirty = false; // we have notified the user now be quiet again } } } void LLFloaterPreferenceProxy::saveSettings() { // Save the value of all controls in the hierarchy mSavedValues.clear(); std::list view_stack; view_stack.push_back(this); while(!view_stack.empty()) { // Process view on top of the stack LLView* curview = view_stack.front(); view_stack.pop_front(); LLUICtrl* ctrl = dynamic_cast(curview); if (ctrl) { LLControlVariable* control = ctrl->getControlVariable(); if (control) { mSavedValues[control] = control->getValue(); } } // Push children onto the end of the work stack for (child_list_t::const_iterator iter = curview->getChildList()->begin(); iter != curview->getChildList()->end(); ++iter) { view_stack.push_back(*iter); } } } void LLFloaterPreferenceProxy::onBtnOk() { // commit any outstanding text entry if (hasFocus()) { LLUICtrl* cur_focus = dynamic_cast(gFocusMgr.getKeyboardFocus()); if (cur_focus && cur_focus->acceptsTextInput()) { cur_focus->onCommit(); } } // Save SOCKS proxy credentials securely if password auth is enabled LLRadioGroup* socksAuth = getChild("socks5_auth_type"); if (socksAuth->getSelectedValue().asString() == "UserPass") { LLSD socks_id = LLSD::emptyMap(); socks_id["type"] = "SOCKS5"; socks_id["username"] = getChild("socks5_username")->getValue().asString(); LLSD socks_authenticator = LLSD::emptyMap(); socks_authenticator["type"] = "SOCKS5"; socks_authenticator["creds"] = getChild("socks5_password")->getValue().asString(); // Using "SOCKS5" as the "grid" argument since the same proxy // settings will be used for all grids and because there is no // way to specify the type of credential. LLPointer socks_cred = gSecAPIHandler->createCredential("SOCKS5", socks_id, socks_authenticator); gSecAPIHandler->saveCredential(socks_cred, true); } else { // Clear SOCKS5 credentials since they are no longer needed. LLPointer socks_cred = new LLCredential("SOCKS5"); gSecAPIHandler->deleteCredential(socks_cred); } closeFloater(false); } void LLFloaterPreferenceProxy::onBtnCancel() { if (hasFocus()) { LLUICtrl* cur_focus = dynamic_cast(gFocusMgr.getKeyboardFocus()); if (cur_focus && cur_focus->acceptsTextInput()) { cur_focus->onCommit(); } refresh(); } cancel(); } void LLFloaterPreferenceProxy::onClickCloseBtn(bool app_quitting) { cancel(); } void LLFloaterPreferenceProxy::cancel() { for (control_values_map_t::iterator iter = mSavedValues.begin(); iter != mSavedValues.end(); ++iter) { LLControlVariable* control = iter->first; LLSD ctrl_value = iter->second; control->set(ctrl_value); } mSocksSettingsDirty = false; closeFloater(); } void LLFloaterPreferenceProxy::onChangeSocksSettings() { mSocksSettingsDirty = true; LLRadioGroup* socksAuth = getChild("socks5_auth_type"); if (socksAuth->getSelectedValue().asString() == "None") { getChild("socks5_username")->setEnabled(false); getChild("socks5_password")->setEnabled(false); } else { getChild("socks5_username")->setEnabled(true); getChild("socks5_password")->setEnabled(true); } // Check for invalid states for the other HTTP proxy radio LLRadioGroup* otherHttpProxy = getChild("other_http_proxy_type"); if ((otherHttpProxy->getSelectedValue().asString() == "Socks" && getChild("socks_proxy_enabled")->get() == FALSE )||( otherHttpProxy->getSelectedValue().asString() == "Web" && getChild("web_proxy_enabled")->get() == FALSE ) ) { otherHttpProxy->selectFirstItem(); } }