diff options
author | Ansariel <ansariel.hiller@phoenixviewer.com> | 2024-05-22 21:25:21 +0200 |
---|---|---|
committer | Andrey Lihatskiy <alihatskiy@productengine.com> | 2024-05-22 22:40:26 +0300 |
commit | e2e37cced861b98de8c1a7c9c0d3a50d2d90e433 (patch) | |
tree | 1bb897489ce524986f6196201c10ac0d8861aa5f /indra/newview/llfloaterautoreplacesettings.cpp | |
parent | 069ea06848f766466f1a281144c82a0f2bd79f3a (diff) |
Fix line endlings
Diffstat (limited to 'indra/newview/llfloaterautoreplacesettings.cpp')
-rw-r--r-- | indra/newview/llfloaterautoreplacesettings.cpp | 1324 |
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"); +*/ |