summaryrefslogtreecommitdiff
path: root/indra/newview/llfloaterautoreplacesettings.cpp
diff options
context:
space:
mode:
authorAnsariel <ansariel.hiller@phoenixviewer.com>2024-05-22 21:25:21 +0200
committerAndrey Lihatskiy <alihatskiy@productengine.com>2024-05-22 22:40:26 +0300
commite2e37cced861b98de8c1a7c9c0d3a50d2d90e433 (patch)
tree1bb897489ce524986f6196201c10ac0d8861aa5f /indra/newview/llfloaterautoreplacesettings.cpp
parent069ea06848f766466f1a281144c82a0f2bd79f3a (diff)
Fix line endlings
Diffstat (limited to 'indra/newview/llfloaterautoreplacesettings.cpp')
-rw-r--r--indra/newview/llfloaterautoreplacesettings.cpp1324
1 files changed, 662 insertions, 662 deletions
diff --git a/indra/newview/llfloaterautoreplacesettings.cpp b/indra/newview/llfloaterautoreplacesettings.cpp
index fe3713f2a1..99f24e161e 100644
--- a/indra/newview/llfloaterautoreplacesettings.cpp
+++ b/indra/newview/llfloaterautoreplacesettings.cpp
@@ -1,662 +1,662 @@
-/**
- * @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 "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 "llviewermenufile.h" // LLFilePickerReplyThread
-#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()
-{
- LLFilePickerReplyThread::startPicker(boost::bind(&LLFloaterAutoReplaceSettings::loadListFromFile, this, _1), LLFilePicker::FFLOAD_XML, false);
-}
-
-void LLFloaterAutoReplaceSettings::loadListFromFile(const std::vector<std::string>& filenames)
-{
- llifstream file;
- file.open(filenames[0].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;
-
- }
-}
-
-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"];
- std::string listName = LLAutoReplaceSettings::getListName(newList);
-
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- switch ( option )
- {
- case 0:
- // Replace current list
- if ( LLAutoReplaceSettings::AddListOk == mSettings.replaceList(newList) )
- {
- LL_INFOS("AutoReplace") << "replaced list '"<<listName<<"'"<<LL_ENDL;
- mSelectedListName = listName;
- updateListNames();
- updateListNamesControls();
- updateReplacementsList();
- }
- else
- {
- LL_WARNS("AutoReplace")<<"failed to replace list '"<<listName<<"'"<<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->getSelectedValue().asString();
- if ( ! listName.empty() )
- {
- if ( mSettings.removeReplacementList(listName) )
- {
- LL_INFOS("AutoReplace")<<"deleted list '"<<listName<<"'"<<LL_ENDL;
- mReplacementsList->deleteSelectedItems(); // remove from the scrolling list
- mSelectedListName.clear();
- updateListNames();
- updateListNamesControls();
- updateReplacementsList();
- }
- else
- {
- LL_WARNS("AutoReplace")<<"failed to delete list '"<<listName<<"'"<<LL_ENDL;
- }
- }
- else
- {
- LL_DEBUGS("AutoReplace")<<"no list selected for delete"<<LL_ENDL;
- }
-}
-
-void LLFloaterAutoReplaceSettings::onExportList()
-{
- std::string listName=mListNames->getFirstSelected()->getColumn(0)->getValue().asString();
- std::string listFileName = listName + ".xml";
- LLFilePickerReplyThread::startPicker(boost::bind(&LLFloaterAutoReplaceSettings::saveListToFile, this, _1, listName), LLFilePicker::FFSAVE_XML, listFileName);
-}
-
-void LLFloaterAutoReplaceSettings::saveListToFile(const std::vector<std::string>& filenames, std::string listName)
-{
- llofstream file;
- const LLSD* list = mSettings.exportList(listName);
- file.open(filenames[0].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");
-*/
+/**
+ * @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 "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 "llviewermenufile.h" // LLFilePickerReplyThread
+#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()
+{
+ LLFilePickerReplyThread::startPicker(boost::bind(&LLFloaterAutoReplaceSettings::loadListFromFile, this, _1), LLFilePicker::FFLOAD_XML, false);
+}
+
+void LLFloaterAutoReplaceSettings::loadListFromFile(const std::vector<std::string>& filenames)
+{
+ llifstream file;
+ file.open(filenames[0].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;
+
+ }
+}
+
+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"];
+ std::string listName = LLAutoReplaceSettings::getListName(newList);
+
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ switch ( option )
+ {
+ case 0:
+ // Replace current list
+ if ( LLAutoReplaceSettings::AddListOk == mSettings.replaceList(newList) )
+ {
+ LL_INFOS("AutoReplace") << "replaced list '"<<listName<<"'"<<LL_ENDL;
+ mSelectedListName = listName;
+ updateListNames();
+ updateListNamesControls();
+ updateReplacementsList();
+ }
+ else
+ {
+ LL_WARNS("AutoReplace")<<"failed to replace list '"<<listName<<"'"<<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->getSelectedValue().asString();
+ if ( ! listName.empty() )
+ {
+ if ( mSettings.removeReplacementList(listName) )
+ {
+ LL_INFOS("AutoReplace")<<"deleted list '"<<listName<<"'"<<LL_ENDL;
+ mReplacementsList->deleteSelectedItems(); // remove from the scrolling list
+ mSelectedListName.clear();
+ updateListNames();
+ updateListNamesControls();
+ updateReplacementsList();
+ }
+ else
+ {
+ LL_WARNS("AutoReplace")<<"failed to delete list '"<<listName<<"'"<<LL_ENDL;
+ }
+ }
+ else
+ {
+ LL_DEBUGS("AutoReplace")<<"no list selected for delete"<<LL_ENDL;
+ }
+}
+
+void LLFloaterAutoReplaceSettings::onExportList()
+{
+ std::string listName=mListNames->getFirstSelected()->getColumn(0)->getValue().asString();
+ std::string listFileName = listName + ".xml";
+ LLFilePickerReplyThread::startPicker(boost::bind(&LLFloaterAutoReplaceSettings::saveListToFile, this, _1, listName), LLFilePicker::FFSAVE_XML, listFileName);
+}
+
+void LLFloaterAutoReplaceSettings::saveListToFile(const std::vector<std::string>& filenames, std::string listName)
+{
+ llofstream file;
+ const LLSD* list = mSettings.exportList(listName);
+ file.open(filenames[0].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");
+*/