diff options
| author | Kelly Washington <kelly@lindenlab.com> | 2012-06-27 14:43:10 -0700 | 
|---|---|---|
| committer | Kelly Washington <kelly@lindenlab.com> | 2012-06-27 14:43:10 -0700 | 
| commit | a68c7c27f9980a130af5eaf65c6731271a27b060 (patch) | |
| tree | fa2d9a9444cfe742d1db3166079fd6631a26ddbd /indra/newview/llfloaterautoreplacesettings.cpp | |
| parent | 14ebeffe8776562c0ac9711a44b7ebe3dec49c47 (diff) | |
| parent | 8a7fa77f23b94f9ba2cb6da1942e4f86da314b5a (diff) | |
Merge pulled in lindenlab/viewer-beta to kelly_linden/maint-1078
Diffstat (limited to 'indra/newview/llfloaterautoreplacesettings.cpp')
| -rw-r--r-- | indra/newview/llfloaterautoreplacesettings.cpp | 641 | 
1 files changed, 641 insertions, 0 deletions
| diff --git a/indra/newview/llfloaterautoreplacesettings.cpp b/indra/newview/llfloaterautoreplacesettings.cpp new file mode 100644 index 0000000000..7d1bcba978 --- /dev/null +++ b/indra/newview/llfloaterautoreplacesettings.cpp @@ -0,0 +1,641 @@ +/**  + * @file llfloaterautoreplacesettings.cpp + * @brief Auto Replace List floater + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + *  + * 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 + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloaterautoreplacesettings.h" + +#include "llagentdata.h" +#include "llcommandhandler.h" +#include "llfloater.h" +#include "lluictrlfactory.h" +#include "llagent.h" +#include "llpanel.h" +#include "llbutton.h" +#include "llcolorswatch.h" +#include "llcombobox.h" +#include "llview.h" +#include "llhttpclient.h" +#include "llbufferstream.h" +#include "llcheckboxctrl.h" +#include "llviewercontrol.h" + +#include "llui.h" +#include "llcontrol.h" +#include "llscrollingpanellist.h" +#include "llautoreplace.h" +#include "llfilepicker.h" +#include "llfile.h" +#include "llsdserialize.h" +#include "llsdutil.h" + +#include "llchat.h" +#include "llinventorymodel.h" +#include "llhost.h" +#include "llassetstorage.h" +#include "roles_constants.h" +#include "llviewertexteditor.h" +#include <boost/tokenizer.hpp> + +#include <iosfwd> +#include "llfloaterreg.h" +#include "llinspecttoast.h" +#include "llnotificationhandler.h" +#include "llnotificationmanager.h" +#include "llnotificationsutil.h" + + +LLFloaterAutoReplaceSettings::LLFloaterAutoReplaceSettings(const LLSD& key) + : LLFloater(key) + , mSelectedListName("") + , mListNames(NULL) + , mReplacementsList(NULL) + , mKeyword(NULL) + , mPreviousKeyword("") + , mReplacement(NULL) +{ +} + +void LLFloaterAutoReplaceSettings::onClose(bool app_quitting) +{ +	cleanUp(); +} + +BOOL LLFloaterAutoReplaceSettings::postBuild(void) +{ +	// get copies of the current settings that we will operate on +	mEnabled  = gSavedSettings.getBOOL("AutoReplace"); +	LL_DEBUGS("AutoReplace") << ( mEnabled ? "enabled" : "disabled") << LL_ENDL; + +	mSettings = LLAutoReplace::getInstance()->getSettings(); +	 +	// global checkbox for whether or not autoreplace is active +	LLUICtrl* enabledCheckbox = getChild<LLUICtrl>("autoreplace_enable"); +	enabledCheckbox->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onAutoReplaceToggled, this)); +	enabledCheckbox->setValue(LLSD(mEnabled)); + +	// top row list creation and deletion +	getChild<LLUICtrl>("autoreplace_import_list")->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onImportList,this)); +	getChild<LLUICtrl>("autoreplace_export_list")->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onExportList,this)); +	getChild<LLUICtrl>("autoreplace_new_list")->setCommitCallback(   boost::bind(&LLFloaterAutoReplaceSettings::onNewList,this)); +	getChild<LLUICtrl>("autoreplace_delete_list")->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onDeleteList,this)); + +	// the list of keyword->replacement lists +	mListNames = getChild<LLScrollListCtrl>("autoreplace_list_name"); +	mListNames->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onSelectList, this)); +	mListNames->setCommitOnSelectionChange(true); +	 +	// list ordering +	getChild<LLUICtrl>("autoreplace_list_up")->setCommitCallback(  boost::bind(&LLFloaterAutoReplaceSettings::onListUp,this)); +	getChild<LLUICtrl>("autoreplace_list_down")->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onListDown,this)); + +	// keyword->replacement entry add / delete +	getChild<LLUICtrl>("autoreplace_add_entry")->setCommitCallback(   boost::bind(&LLFloaterAutoReplaceSettings::onAddEntry,this)); +	getChild<LLUICtrl>("autoreplace_delete_entry")->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onDeleteEntry,this)); + +	// entry edits +	mKeyword     = getChild<LLLineEditor>("autoreplace_keyword"); +	mReplacement = getChild<LLLineEditor>("autoreplace_replacement"); +	getChild<LLUICtrl>("autoreplace_save_entry")->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onSaveEntry, this)); + +	// dialog termination ( Save Changes / Cancel ) +	getChild<LLUICtrl>("autoreplace_save_changes")->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onSaveChanges, this)); +	getChild<LLUICtrl>("autoreplace_cancel")->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onCancel, this)); + +	// the list of keyword->replacement pairs +	mReplacementsList = getChild<LLScrollListCtrl>("autoreplace_list_replacements"); +	mReplacementsList->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onSelectEntry, this)); +	mReplacementsList->setCommitOnSelectionChange(true); + +	center(); + +	mSelectedListName.clear(); +	updateListNames(); +	updateListNamesControls(); +	updateReplacementsList(); + +	return true; +} + + +void LLFloaterAutoReplaceSettings::updateListNames() +{ +	mListNames->deleteAllItems(); // start from scratch + +	LLSD listNames = mSettings.getListNames(); // Array of Strings +    +	for ( LLSD::array_const_iterator entry = listNames.beginArray(), end = listNames.endArray(); +		  entry != end; +		  ++entry +		 ) +	{ +		const std::string& listName = entry->asString(); +		mListNames->addSimpleElement(listName); +	} + +	if (!mSelectedListName.empty()) +	{ +		mListNames->setSelectedByValue( LLSD(mSelectedListName), true ); +	} +} + +void LLFloaterAutoReplaceSettings::updateListNamesControls() +{ +	if ( mSelectedListName.empty() ) +	{ +		// There is no selected list + +		// Disable all controls that operate on the selected list +		getChild<LLButton>("autoreplace_export_list")->setEnabled(false); +		getChild<LLButton>("autoreplace_delete_list")->setEnabled(false); +		getChild<LLButton>("autoreplace_list_up")->setEnabled(false); +		getChild<LLButton>("autoreplace_list_down")->setEnabled(false); + +		mReplacementsList->deleteAllItems(); +	} +	else +	{ +		// Enable the controls that operate on the selected list +		getChild<LLButton>("autoreplace_export_list")->setEnabled(true); +		getChild<LLButton>("autoreplace_delete_list")->setEnabled(true); +		getChild<LLButton>("autoreplace_list_up")->setEnabled(!selectedListIsFirst()); +		getChild<LLButton>("autoreplace_list_down")->setEnabled(!selectedListIsLast()); +	} +} + +void LLFloaterAutoReplaceSettings::onSelectList() +{ +	std::string previousSelectedListName = mSelectedListName; +	// only one selection allowed +	LLSD selected = mListNames->getSelectedValue(); +	if (selected.isDefined()) +	{ +		mSelectedListName = selected.asString(); +		LL_DEBUGS("AutoReplace")<<"selected list '"<<mSelectedListName<<"'"<<LL_ENDL; +	} +	else +	{ +		mSelectedListName.clear(); +		LL_DEBUGS("AutoReplace")<<"unselected"<<LL_ENDL; +	} + +	updateListNamesControls(); + +	if ( previousSelectedListName != mSelectedListName ) +	{ +		updateReplacementsList(); +	} +} + +void LLFloaterAutoReplaceSettings::onSelectEntry() +{ +    LLSD selectedRow = mReplacementsList->getSelectedValue(); +	if (selectedRow.isDefined()) +	{ +		mPreviousKeyword = selectedRow.asString(); +		LL_DEBUGS("AutoReplace")<<"selected entry '"<<mPreviousKeyword<<"'"<<LL_ENDL;	 +		mKeyword->setValue(selectedRow); +		std::string replacement = mSettings.replacementFor(mPreviousKeyword, mSelectedListName ); +		mReplacement->setValue(replacement); +		enableReplacementEntry();		 +		mReplacement->setFocus(true); +	} +	else +	{ +		// no entry selection, so the entry panel should be off +		disableReplacementEntry();		 +		LL_DEBUGS("AutoReplace")<<"no row selected"<<LL_ENDL; +	} +} + +void LLFloaterAutoReplaceSettings::updateReplacementsList() +{ +	// start from scratch, since this should only be called when the list changes +	mReplacementsList->deleteAllItems(); + +	if ( mSelectedListName.empty() ) +	{ +		mReplacementsList->setEnabled(false); +		getChild<LLButton>("autoreplace_add_entry")->setEnabled(false); +		disableReplacementEntry();		 +	} +	else +	{ +		// Populate the keyword->replacement list from the selected list +		const LLSD* mappings = mSettings.getListEntries(mSelectedListName); +		for ( LLSD::map_const_iterator entry = mappings->beginMap(), end = mappings->endMap(); +			  entry != end; +			  entry++ +			 ) +		{ +			LLSD row; +			row["id"] = entry->first; +			row["columns"][0]["column"] = "keyword"; +			row["columns"][0]["value"]  = entry->first; +			row["columns"][1]["column"] = "replacement"; +			row["columns"][1]["value"]  = entry->second; + +			mReplacementsList->addElement(row, ADD_BOTTOM); +		} + +		mReplacementsList->deselectAllItems(false /* don't call commit */); +		mReplacementsList->setEnabled(true); + +		getChild<LLButton>("autoreplace_add_entry")->setEnabled(true); +		disableReplacementEntry();		 +	} +} + +void LLFloaterAutoReplaceSettings::enableReplacementEntry() +{ +	LL_DEBUGS("AutoReplace")<<LL_ENDL; +	mKeyword->setEnabled(true); +	mReplacement->setEnabled(true); +	getChild<LLButton>("autoreplace_save_entry")->setEnabled(true); +	getChild<LLButton>("autoreplace_delete_entry")->setEnabled(true); +} + +void LLFloaterAutoReplaceSettings::disableReplacementEntry() +{ +	LL_DEBUGS("AutoReplace")<<LL_ENDL; +	mPreviousKeyword.clear(); +	mKeyword->clear(); +	mKeyword->setEnabled(false); +	mReplacement->clear(); +	mReplacement->setEnabled(false); +	getChild<LLButton>("autoreplace_save_entry")->setEnabled(false); +	getChild<LLButton>("autoreplace_delete_entry")->setEnabled(false); +} + +// called when the global settings checkbox is changed +void LLFloaterAutoReplaceSettings::onAutoReplaceToggled() +{ +	// set our local copy of the flag, copied to the global preference in onOk +	mEnabled = childGetValue("autoreplace_enable").asBoolean(); +	LL_DEBUGS("AutoReplace")<< "autoreplace_enable " << ( mEnabled ? "on" : "off" ) << LL_ENDL; +} + +// called when the List Up button is pressed +void LLFloaterAutoReplaceSettings::onListUp() +{ +	S32 selectedRow = mListNames->getFirstSelectedIndex(); +	LLSD selectedName = mListNames->getSelectedValue().asString(); + +	if ( mSettings.increaseListPriority(selectedName) ) +	{ +		updateListNames(); +		updateListNamesControls(); +	} +	else +	{ +		LL_WARNS("AutoReplace") +			<< "invalid row ("<<selectedRow<<") selected '"<<selectedName<<"'" +			<<LL_ENDL; +	} +} + +// called when the List Down button is pressed +void LLFloaterAutoReplaceSettings::onListDown() +{ +	S32 selectedRow = mListNames->getFirstSelectedIndex(); +	std::string selectedName = mListNames->getSelectedValue().asString(); + +	if ( mSettings.decreaseListPriority(selectedName) ) +	{ +		updateListNames(); +		updateListNamesControls(); +	} +	else +	{ +		LL_WARNS("AutoReplace") +			<< "invalid row ("<<selectedRow<<") selected '"<<selectedName<<"'" +			<<LL_ENDL; +	} +} + +// called when the Delete Entry button is pressed +void LLFloaterAutoReplaceSettings::onDeleteEntry() +{ +    LLSD selectedRow = mReplacementsList->getSelectedValue(); +	if (selectedRow.isDefined()) +	{	 +		std::string keyword = selectedRow.asString(); +		mReplacementsList->deleteSelectedItems(); // delete from the control +		mSettings.removeEntryFromList(keyword, mSelectedListName); // delete from the local settings copy +		disableReplacementEntry(); // no selection active, so turn off the buttons +	} +} + +// called when the Import List button is pressed +void LLFloaterAutoReplaceSettings::onImportList() +{ +	LLFilePicker& picker = LLFilePicker::instance(); +	if( picker.getOpenFile( LLFilePicker::FFLOAD_XML) ) +	{ +		llifstream file; +		file.open(picker.getFirstFile().c_str()); +		LLSD newList; +		if (file.is_open()) +		{ +			LLSDSerialize::fromXMLDocument(newList, file); +		} +		file.close(); + +		switch ( mSettings.addList(newList) ) +		{ +		case LLAutoReplaceSettings::AddListOk: +			mSelectedListName = LLAutoReplaceSettings::getListName(newList); +			 +			updateListNames(); +			updateListNamesControls(); +			updateReplacementsList(); +			break; + +		case LLAutoReplaceSettings::AddListDuplicateName: +			{ +				std::string newName = LLAutoReplaceSettings::getListName(newList); +				LL_WARNS("AutoReplace")<<"name '"<<newName<<"' is in use; prompting for new name"<<LL_ENDL; +				LLSD newPayload; +				newPayload["list"] = newList; +				LLSD args; +				args["DUPNAME"] = newName; +	 +				LLNotificationsUtil::add("RenameAutoReplaceList", args, newPayload, +										 boost::bind(&LLFloaterAutoReplaceSettings::callbackListNameConflict, this, _1, _2)); +			} +			break; + +		case LLAutoReplaceSettings::AddListInvalidList: +			LLNotificationsUtil::add("InvalidAutoReplaceList"); +			LL_WARNS("AutoReplace") << "imported list was invalid" << LL_ENDL; + +			mSelectedListName.clear(); +			updateListNames(); +			updateListNamesControls(); +			updateReplacementsList(); +			break; + +		default: +			LL_ERRS("AutoReplace") << "invalid AddListResult" << LL_ENDL; + +		} +		 +	} +	else +	{ +		LL_DEBUGS("AutoReplace") << "file selection failed for import list" << LL_ENDL; +	}		 +} + +void LLFloaterAutoReplaceSettings::onNewList() +{ +	LLSD payload; +	LLSD emptyList; +	LLAutoReplaceSettings::createEmptyList(emptyList); +	payload["list"] = emptyList; +    LLSD args; +	 +	LLNotificationsUtil::add("AddAutoReplaceList", args, payload, +							 boost::bind(&LLFloaterAutoReplaceSettings::callbackNewListName, this, _1, _2)); +} + +bool LLFloaterAutoReplaceSettings::callbackNewListName(const LLSD& notification, const LLSD& response) +{ +	LL_DEBUGS("AutoReplace")<<"called"<<LL_ENDL; +	 +	LLSD newList = notification["payload"]["list"]; + +	if ( response.has("listname") && response["listname"].isString() ) +	{ +		std::string newName = response["listname"].asString(); +		LLAutoReplaceSettings::setListName(newList, newName); + +		switch ( mSettings.addList(newList) ) +		{ +		case LLAutoReplaceSettings::AddListOk: +			LL_INFOS("AutoReplace") << "added new list '"<<newName<<"'"<<LL_ENDL; +			mSelectedListName = newName; +			updateListNames(); +			updateListNamesControls(); +			updateReplacementsList(); +			break; + +		case LLAutoReplaceSettings::AddListDuplicateName: +			{ +				LL_WARNS("AutoReplace")<<"name '"<<newName<<"' is in use; prompting for new name"<<LL_ENDL; +				LLSD newPayload; +				newPayload["list"] = notification["payload"]["list"]; +				LLSD args; +				args["DUPNAME"] = newName; +	 +				LLNotificationsUtil::add("RenameAutoReplaceList", args, newPayload, +										 boost::bind(&LLFloaterAutoReplaceSettings::callbackListNameConflict, this, _1, _2)); +			} +			break; + +		case LLAutoReplaceSettings::AddListInvalidList: +			LLNotificationsUtil::add("InvalidAutoReplaceList"); + +			mSelectedListName.clear(); +			updateListNames(); +			updateListNamesControls(); +			updateReplacementsList(); +			break; + +		default: +			LL_ERRS("AutoReplace") << "invalid AddListResult" << LL_ENDL; +		} +	} +	else +	{ +		LL_ERRS("AutoReplace") << "adding notification response" << LL_ENDL; +	} +	return false; +} + +// callback for the RenameAutoReplaceList notification +bool LLFloaterAutoReplaceSettings::callbackListNameConflict(const LLSD& notification, const LLSD& response) +{ +	LLSD newList = notification["payload"]["list"]; + +	S32 option = LLNotificationsUtil::getSelectedOption(notification, response); +	switch ( option ) +	{ +	case 0: +		// Replace current list +		LL_INFOS("AutoReplace")<<"option 'replace current list' selected"<<LL_ENDL; +		 +		break; + +	case 1: +		// Use New Name +		LL_INFOS("AutoReplace")<<"option 'use new name' selected"<<LL_ENDL; +		callbackNewListName(notification, response); +		break; + +	default: +		LL_ERRS("AutoReplace")<<"invalid selected option "<<option<<LL_ENDL; +	} + +	return false; +} + +void LLFloaterAutoReplaceSettings::onDeleteList() +{ +	std::string listName= mListNames->getFirstSelected()->getColumn(0)->getValue().asString(); +	mSettings.removeReplacementList(listName); // remove from the copy of settings +	mReplacementsList->deleteSelectedItems();   // remove from the scrolling list + +	mSelectedListName.clear(); +	updateListNames(); +	updateListNamesControls(); +	updateReplacementsList(); +} + +void LLFloaterAutoReplaceSettings::onExportList() +{ +	std::string listName=mListNames->getFirstSelected()->getColumn(0)->getValue().asString(); +	const LLSD* list = mSettings.exportList(listName); +	std::string listFileName = listName + ".xml"; +	LLFilePicker& picker = LLFilePicker::instance(); +	if( picker.getSaveFile( LLFilePicker::FFSAVE_XML, listFileName) ) +	{ +		llofstream file; +		file.open(picker.getFirstFile().c_str()); +		LLSDSerialize::toPrettyXML(*list, file); +		file.close(); +	} +} + +void LLFloaterAutoReplaceSettings::onAddEntry() +{ +	mPreviousKeyword.clear(); +	mReplacementsList->deselectAllItems(false /* don't call commit */); +	mKeyword->clear(); +	mReplacement->clear(); +	enableReplacementEntry(); +	mKeyword->setFocus(true); +} + +void LLFloaterAutoReplaceSettings::onSaveEntry() +{ +	LL_DEBUGS("AutoReplace")<<"called"<<LL_ENDL; +	 +	if ( ! mPreviousKeyword.empty() ) +	{ +		// delete any existing value for the key that was editted +		LL_INFOS("AutoReplace") +			<< "list '" << mSelectedListName << "' " +			<< "removed '" << mPreviousKeyword +			<< "'" << LL_ENDL; +		mSettings.removeEntryFromList( mPreviousKeyword, mSelectedListName ); +	} + +	LLWString keyword     = mKeyword->getWText(); +	LLWString replacement = mReplacement->getWText(); +	if ( mSettings.addEntryToList(keyword, replacement, mSelectedListName) ) +	{ +		// insert the new keyword->replacement pair +		LL_INFOS("AutoReplace") +			<< "list '" << mSelectedListName << "' " +			<< "added '" << wstring_to_utf8str(keyword) +			<< "' -> '" << wstring_to_utf8str(replacement) +			<< "'" << LL_ENDL; + +		updateReplacementsList(); +	} +	else +	{ +		LLNotificationsUtil::add("InvalidAutoReplaceEntry"); +		LL_WARNS("AutoReplace")<<"invalid entry " +							   << "keyword '" << wstring_to_utf8str(keyword) +							   << "' replacement '" << wstring_to_utf8str(replacement) +							   << "'" << LL_ENDL; +	} +} + +void LLFloaterAutoReplaceSettings::onCancel() +{ +	cleanUp(); +	closeFloater(false /* not quitting */); +} + +void LLFloaterAutoReplaceSettings::onSaveChanges() +{ +	// put our local copy of the settings into the active copy +	LLAutoReplace::getInstance()->setSettings( mSettings ); +	// save our local copy of the global feature enable/disable value +	gSavedSettings.setBOOL("AutoReplace", mEnabled); +	cleanUp(); +	closeFloater(false /* not quitting */); +} + +void LLFloaterAutoReplaceSettings::cleanUp() +{ + +} + +bool LLFloaterAutoReplaceSettings::selectedListIsFirst() +{ +	bool isFirst = false; +	 +	if (!mSelectedListName.empty()) +	{ +		LLSD lists = mSettings.getListNames(); // an Array of Strings +		LLSD first = lists.get(0); +		if ( first.isString() && first.asString() == mSelectedListName ) +		{ +			isFirst = true; +		} +	} +	return isFirst; +} + +bool LLFloaterAutoReplaceSettings::selectedListIsLast() +{ +	bool isLast = false; +	 +	if (!mSelectedListName.empty()) +	{ +		LLSD last; +		LLSD lists = mSettings.getListNames(); // an Array of Strings +		for ( LLSD::array_const_iterator list = lists.beginArray(), listEnd = lists.endArray(); +			  list != listEnd; +			  list++ +			 ) +		{ +			last = *list; +		} +		if ( last.isString() && last.asString() == mSelectedListName ) +		{ +			isLast = true; +		} +	} +	return isLast; +} + +/* TBD +mOldText = getChild<LLLineEditor>("autoreplace_old_text"); +mNewText = getChild<LLLineEditor>("autoreplace_new_text"); +*/ | 
