From 53222ef517b97249df1e1a6db2e29c0d86b2e773 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Thu, 31 May 2012 02:56:42 +0200 Subject: STORM-276 Match preferences look to that of the auto-replace functionality in STORM-1738 --- indra/newview/llfloaterspellchecksettings.cpp | 179 ++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 indra/newview/llfloaterspellchecksettings.cpp (limited to 'indra/newview/llfloaterspellchecksettings.cpp') diff --git a/indra/newview/llfloaterspellchecksettings.cpp b/indra/newview/llfloaterspellchecksettings.cpp new file mode 100644 index 0000000000..ff5afc8169 --- /dev/null +++ b/indra/newview/llfloaterspellchecksettings.cpp @@ -0,0 +1,179 @@ +/** + * @file llfloaterspellchecksettings.h + * @brief Spell checker settings floater + * +* $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llcombobox.h" +#include "llfloaterspellchecksettings.h" +#include "llscrolllistctrl.h" +#include "llspellcheck.h" +#include "llviewercontrol.h" + +#include + +LLFloaterSpellCheckerSettings::LLFloaterSpellCheckerSettings(const LLSD& key) + : LLFloater(key) +{ +} + +BOOL LLFloaterSpellCheckerSettings::postBuild(void) +{ + gSavedSettings.getControl("SpellCheck")->getSignal()->connect(boost::bind(&LLFloaterSpellCheckerSettings::refreshDictionaryLists, this, false)); + getChild("spellcheck_main_combo")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::refreshDictionaryLists, this, false)); + getChild("spellcheck_moveleft_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onClickDictMove, this, "spellcheck_active_list", "spellcheck_available_list")); + getChild("spellcheck_moveright_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onClickDictMove, this, "spellcheck_available_list", "spellcheck_active_list")); + getChild("spellcheck_ok")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onOK, this)); + getChild("spellcheck_cancel")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onCancel, this)); + + return true; +} + +void LLFloaterSpellCheckerSettings::onCancel() +{ + closeFloater(false); +} + +void LLFloaterSpellCheckerSettings::onClickDictMove(const std::string& from, const std::string& to) +{ + LLScrollListCtrl* from_ctrl = findChild(from); + LLScrollListCtrl* to_ctrl = findChild(to); + + LLSD row; + row["columns"][0]["column"] = "name"; + row["columns"][0]["font"]["name"] = "SANSSERIF_SMALL"; + row["columns"][0]["font"]["style"] = "NORMAL"; + + std::vector sel_items = from_ctrl->getAllSelected(); + for (std::vector::const_iterator sel_it = sel_items.begin(); sel_it != sel_items.end(); ++sel_it) + { + row["columns"][0]["value"] = (*sel_it)->getColumn(0)->getValue(); + to_ctrl->addElement(row); + } + from_ctrl->deleteSelectedItems(); +} + +void LLFloaterSpellCheckerSettings::onOK() +{ + std::list list_dict; + + LLComboBox* dict_combo = findChild("spellcheck_main_combo"); + const std::string dict_name = dict_combo->getSelectedItemLabel(); + if (!dict_name.empty()) + { + list_dict.push_back(dict_name); + + LLScrollListCtrl* list_ctrl = findChild("spellcheck_active_list"); + std::vector list_items = list_ctrl->getAllData(); + for (std::vector::const_iterator item_it = list_items.begin(); item_it != list_items.end(); ++item_it) + list_dict.push_back((*item_it)->getColumn(0)->getValue().asString()); + } + gSavedSettings.setString("SpellCheckDictionary", boost::join(list_dict, ",")); + + closeFloater(false); +} + +void LLFloaterSpellCheckerSettings::onOpen(const LLSD& key) +{ + refreshDictionaryLists(true); +} + +void LLFloaterSpellCheckerSettings::refreshDictionaryLists(bool from_settings) +{ + bool enabled = gSavedSettings.getBOOL("SpellCheck"); + getChild("spellcheck_moveleft_btn")->setEnabled(enabled); + getChild("spellcheck_moveright_btn")->setEnabled(enabled); + + // Populate the dictionary combobox + LLComboBox* dict_combo = findChild("spellcheck_main_combo"); + std::string dict_cur = dict_combo->getSelectedItemLabel(); + if ((dict_cur.empty() || from_settings) && (LLSpellChecker::getUseSpellCheck())) + dict_cur = LLSpellChecker::instance().getActiveDictionary(); + dict_combo->clearRows(); + dict_combo->setEnabled(enabled); + + const LLSD& dict_map = LLSpellChecker::getDictionaryMap(); + if (dict_map.size()) + { + for (LLSD::array_const_iterator dict_it = dict_map.beginArray(); dict_it != dict_map.endArray(); ++dict_it) + { + const LLSD& dict = *dict_it; + if ( (dict["installed"].asBoolean()) && (dict["is_primary"].asBoolean()) && (dict.has("language")) ) + dict_combo->add(dict["language"].asString()); + } + if (!dict_combo->selectByValue(dict_cur)) + dict_combo->clear(); + } + + // Populate the available and active dictionary list + LLScrollListCtrl* avail_ctrl = findChild("spellcheck_available_list"); + LLScrollListCtrl* active_ctrl = findChild("spellcheck_active_list"); + + LLSpellChecker::dict_list_t active_list; + if ( ((!avail_ctrl->getItemCount()) && (!active_ctrl->getItemCount())) || (from_settings) ) + { + if (LLSpellChecker::getUseSpellCheck()) + active_list = LLSpellChecker::instance().getSecondaryDictionaries(); + } + else + { + std::vector active_items = active_ctrl->getAllData(); + for (std::vector::const_iterator item_it = active_items.begin(); item_it != active_items.end(); ++item_it) + { + std::string dict = (*item_it)->getColumn(0)->getValue().asString(); + if (dict_cur != dict) + active_list.push_back(dict); + } + } + + LLSD row; + row["columns"][0]["column"] = "name"; + row["columns"][0]["font"]["name"] = "SANSSERIF_SMALL"; + row["columns"][0]["font"]["style"] = "NORMAL"; + + active_ctrl->clearRows(); + active_ctrl->setEnabled(enabled); + active_ctrl->sortByColumnIndex(0, true); + for (LLSpellChecker::dict_list_t::const_iterator it = active_list.begin(); it != active_list.end(); ++it) + { + row["columns"][0]["value"] = *it; + active_ctrl->addElement(row); + } + active_list.push_back(dict_cur); + + avail_ctrl->clearRows(); + avail_ctrl->setEnabled(enabled); + avail_ctrl->sortByColumnIndex(0, true); + for (LLSD::array_const_iterator dict_it = dict_map.beginArray(); dict_it != dict_map.endArray(); ++dict_it) + { + const LLSD& dict = *dict_it; + if ( (dict["installed"].asBoolean()) && (dict.has("language")) && + (active_list.end() == std::find(active_list.begin(), active_list.end(), dict["language"].asString())) ) + { + row["columns"][0]["value"] = dict["language"].asString(); + avail_ctrl->addElement(row); + } + } +} -- cgit v1.3 From 20210455f5a350b3e8e24515ba7af71db0eece0b Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Mon, 4 Jun 2012 16:10:32 +0200 Subject: STORM-276 Dictionary import functionality and floater --- indra/llui/llspellcheck.cpp | 45 +++++++- indra/llui/llspellcheck.h | 5 +- indra/newview/llfilepicker.cpp | 22 ++++ indra/newview/llfilepicker.h | 1 + indra/newview/llfloaterspellchecksettings.cpp | 127 +++++++++++++++++++-- indra/newview/llfloaterspellchecksettings.h | 25 +++- indra/newview/llviewerfloaterreg.cpp | 1 + .../skins/default/xui/en/floater_spellcheck.xml | 10 ++ .../default/xui/en/floater_spellcheck_import.xml | 116 +++++++++++++++++++ indra/newview/skins/default/xui/en/strings.xml | 1 + 10 files changed, 335 insertions(+), 18 deletions(-) create mode 100644 indra/newview/skins/default/xui/en/floater_spellcheck_import.xml (limited to 'indra/newview/llfloaterspellchecksettings.cpp') diff --git a/indra/llui/llspellcheck.cpp b/indra/llui/llspellcheck.cpp index bde3b56741..04c8a4fed0 100644 --- a/indra/llui/llspellcheck.cpp +++ b/indra/llui/llspellcheck.cpp @@ -88,17 +88,37 @@ S32 LLSpellChecker::getSuggestions(const std::string& word, std::vectorfileExists(tmp_user_path + DICT_CUSTOM_SUFFIX + ".dic")); sdDict["has_ignore"] = (!tmp_user_path.empty()) && (gDirUtilp->fileExists(tmp_user_path + DICT_IGNORE_SUFFIX + ".dic")); } + + sSettingsChangeSignal(); } void LLSpellChecker::addToCustomDictionary(const std::string& word) diff --git a/indra/llui/llspellcheck.h b/indra/llui/llspellcheck.h index d736a7f082..acb121dd19 100644 --- a/indra/llui/llspellcheck.h +++ b/indra/llui/llspellcheck.h @@ -59,12 +59,15 @@ public: static const std::string getDictionaryAppPath(); static const std::string getDictionaryUserPath(); - static const LLSD getDictionaryData(const std::string& dict_name); + static const LLSD getDictionaryData(const std::string& dict_language); static const LLSD& getDictionaryMap() { return sDictMap; } static bool getUseSpellCheck(); static void refreshDictionaryMap(); static void setUseSpellCheck(const std::string& dict_name); +protected: + static void setDictionaryData(const LLSD& dict_info); +public: typedef boost::signals2::signal settings_change_signal_t; static boost::signals2::connection setSettingsChangeCallback(const settings_change_signal_t::slot_type& cb); protected: diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index 8986a694f9..cbb5a40cfa 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -59,6 +59,7 @@ LLFilePicker LLFilePicker::sInstance; #define RAW_FILTER L"RAW files (*.raw)\0*.raw\0" #define MODEL_FILTER L"Model files (*.dae)\0*.dae\0" #define SCRIPT_FILTER L"Script files (*.lsl)\0*.lsl\0" +#define DICTIONARY_FILTER L"Dictionary files (*.dic)\0*.dic\0" #endif // @@ -218,6 +219,10 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter) mOFN.lpstrFilter = SCRIPT_FILTER \ L"\0"; break; + case FFLOAD_DICTIONARY: + mOFN.lpstrFilter = DICTIONARY_FILTER \ + L"\0"; + break; default: res = FALSE; break; @@ -643,6 +648,14 @@ Boolean LLFilePicker::navOpenFilterProc(AEDesc *theItem, void *info, void *callB result = false; } } + else if (filter == FFLOAD_DICTIONARY) + { + if (fileInfo.filetype != 'DIC ' && + (fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("dic"), kCFCompareCaseInsensitive) != kCFCompareEqualTo)) ) + { + result = false; + } + } if (fileInfo.extension) { @@ -1235,6 +1248,12 @@ static std::string add_script_filter_to_gtkchooser(GtkWindow *picker) LLTrans::getString("script_files") + " (*.lsl)"); } +static std::string add_dictionary_filter_to_gtkchooser(GtkWindow *picker) +{ + return add_simple_mime_filter_to_gtkchooser(picker, "text/plain", + LLTrans::getString("dictionary_files") + " (*.dic)"); +} + BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename ) { BOOL rtn = FALSE; @@ -1371,6 +1390,9 @@ BOOL LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking ) case FFLOAD_SCRIPT: filtername = add_script_filter_to_gtkchooser(picker); break; + case FFLOAD_DICTIONARY: + filtername = add_dictionary_filter_to_gtkchooser(picker); + break; default:; break; } diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h index a4d5d68ff5..55c665b9c7 100644 --- a/indra/newview/llfilepicker.h +++ b/indra/newview/llfilepicker.h @@ -85,6 +85,7 @@ public: FFLOAD_MODEL = 9, FFLOAD_COLLADA = 10, FFLOAD_SCRIPT = 11, + FFLOAD_DICTIONARY = 12 }; enum ESaveFilter diff --git a/indra/newview/llfloaterspellchecksettings.cpp b/indra/newview/llfloaterspellchecksettings.cpp index ff5afc8169..8bf480c4df 100644 --- a/indra/newview/llfloaterspellchecksettings.cpp +++ b/indra/newview/llfloaterspellchecksettings.cpp @@ -27,13 +27,19 @@ #include "llviewerprecompiledheaders.h" #include "llcombobox.h" +#include "llfilepicker.h" +#include "llfloaterreg.h" #include "llfloaterspellchecksettings.h" #include "llscrolllistctrl.h" +#include "llsdserialize.h" #include "llspellcheck.h" #include "llviewercontrol.h" #include +///---------------------------------------------------------------------------- +/// Class LLFloaterSpellCheckerSettings +///---------------------------------------------------------------------------- LLFloaterSpellCheckerSettings::LLFloaterSpellCheckerSettings(const LLSD& key) : LLFloater(key) { @@ -42,21 +48,28 @@ LLFloaterSpellCheckerSettings::LLFloaterSpellCheckerSettings(const LLSD& key) BOOL LLFloaterSpellCheckerSettings::postBuild(void) { gSavedSettings.getControl("SpellCheck")->getSignal()->connect(boost::bind(&LLFloaterSpellCheckerSettings::refreshDictionaryLists, this, false)); + LLSpellChecker::setSettingsChangeCallback(boost::bind(&LLFloaterSpellCheckerSettings::onSpellCheckSettingsChange, this)); + getChild("spellcheck_import_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onBtnImport, this)); getChild("spellcheck_main_combo")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::refreshDictionaryLists, this, false)); - getChild("spellcheck_moveleft_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onClickDictMove, this, "spellcheck_active_list", "spellcheck_available_list")); - getChild("spellcheck_moveright_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onClickDictMove, this, "spellcheck_available_list", "spellcheck_active_list")); - getChild("spellcheck_ok")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onOK, this)); - getChild("spellcheck_cancel")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onCancel, this)); + getChild("spellcheck_moveleft_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onBtnMove, this, "spellcheck_active_list", "spellcheck_available_list")); + getChild("spellcheck_moveright_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onBtnMove, this, "spellcheck_available_list", "spellcheck_active_list")); + getChild("spellcheck_ok")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onBtnOK, this)); + getChild("spellcheck_cancel")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onBtnCancel, this)); return true; } -void LLFloaterSpellCheckerSettings::onCancel() +void LLFloaterSpellCheckerSettings::onBtnCancel() { closeFloater(false); } -void LLFloaterSpellCheckerSettings::onClickDictMove(const std::string& from, const std::string& to) +void LLFloaterSpellCheckerSettings::onBtnImport() +{ + LLFloaterReg::showInstance("prefs_spellchecker_import"); +} + +void LLFloaterSpellCheckerSettings::onBtnMove(const std::string& from, const std::string& to) { LLScrollListCtrl* from_ctrl = findChild(from); LLScrollListCtrl* to_ctrl = findChild(to); @@ -75,7 +88,7 @@ void LLFloaterSpellCheckerSettings::onClickDictMove(const std::string& from, con from_ctrl->deleteSelectedItems(); } -void LLFloaterSpellCheckerSettings::onOK() +void LLFloaterSpellCheckerSettings::onBtnOK() { std::list list_dict; @@ -100,6 +113,11 @@ void LLFloaterSpellCheckerSettings::onOpen(const LLSD& key) refreshDictionaryLists(true); } +void LLFloaterSpellCheckerSettings::onSpellCheckSettingsChange() +{ + refreshDictionaryLists(true); +} + void LLFloaterSpellCheckerSettings::refreshDictionaryLists(bool from_settings) { bool enabled = gSavedSettings.getBOOL("SpellCheck"); @@ -177,3 +195,98 @@ void LLFloaterSpellCheckerSettings::refreshDictionaryLists(bool from_settings) } } } + +///---------------------------------------------------------------------------- +/// Class LLFloaterSpellCheckerImport +///---------------------------------------------------------------------------- +LLFloaterSpellCheckerImport::LLFloaterSpellCheckerImport(const LLSD& key) + : LLFloater(key) +{ +} + +BOOL LLFloaterSpellCheckerImport::postBuild(void) +{ + getChild("dictionary_path_browse")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerImport::onBtnBrowse, this)); + getChild("ok_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerImport::onBtnOK, this)); + getChild("cancel_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerImport::onBtnCancel, this)); + + return true; +} + +void LLFloaterSpellCheckerImport::onBtnBrowse() +{ + LLFilePicker& file_picker = LLFilePicker::instance(); + if (!file_picker.getOpenFile(LLFilePicker::FFLOAD_DICTIONARY)) + { + return; + } + + const std::string filepath = file_picker.getFirstFile(); + getChild("dictionary_path")->setValue(filepath); + + mDictionaryDir = gDirUtilp->getDirName(filepath); + mDictionaryBasename = gDirUtilp->getBaseFileName(filepath, true); + getChild("dictionary_name")->setValue(mDictionaryBasename); +} + +void LLFloaterSpellCheckerImport::onBtnCancel() +{ + closeFloater(false); +} + +void LLFloaterSpellCheckerImport::onBtnOK() +{ + const std::string dict_dic = mDictionaryDir + gDirUtilp->getDirDelimiter() + mDictionaryBasename + ".dic"; + const std::string dict_aff = mDictionaryDir + gDirUtilp->getDirDelimiter() + mDictionaryBasename + ".aff"; + std::string dict_language = getChild("dictionary_language")->getValue().asString(); + LLStringUtil::trim(dict_language); + if ( (dict_language.empty()) || (!gDirUtilp->fileExists(dict_dic)) || + (mDictionaryDir.empty()) || (mDictionaryBasename.empty()) ) + { + return; + } + + LLSD custom_dict_info; + custom_dict_info["is_primary"] = (bool)gDirUtilp->fileExists(dict_aff); + custom_dict_info["name"] = mDictionaryBasename; + custom_dict_info["language"] = dict_language; + + LLSD custom_dict_map; + llifstream custom_file_in(LLSpellChecker::getDictionaryUserPath() + "user_dictionaries.xml"); + if (custom_file_in.is_open()) + { + LLSDSerialize::fromXMLDocument(custom_dict_map, custom_file_in); + custom_file_in.close(); + } + + LLSD::array_iterator it = custom_dict_map.beginArray(); + for (; it != custom_dict_map.endArray(); ++it) + { + LLSD& dict_info = *it; + if (dict_info["name"].asString() == mDictionaryBasename) + { + dict_info = custom_dict_info; + break; + } + } + if (custom_dict_map.endArray() == it) + { + custom_dict_map.append(custom_dict_info); + } + + llofstream custom_file_out(LLSpellChecker::getDictionaryUserPath() + "user_dictionaries.xml", std::ios::trunc); + if (custom_file_out.is_open()) + { + LLSDSerialize::toPrettyXML(custom_dict_map, custom_file_out); + custom_file_out.close(); + } + + LLFile::rename(dict_dic, LLSpellChecker::getDictionaryUserPath() + mDictionaryBasename + ".dic"); + if (gDirUtilp->fileExists(dict_aff)) + { + LLFile::rename(dict_aff, LLSpellChecker::getDictionaryUserPath() + mDictionaryBasename + ".aff"); + } + LLSpellChecker::refreshDictionaryMap(); + + closeFloater(false); +} diff --git a/indra/newview/llfloaterspellchecksettings.h b/indra/newview/llfloaterspellchecksettings.h index 33c376fff6..521b586835 100644 --- a/indra/newview/llfloaterspellchecksettings.h +++ b/indra/newview/llfloaterspellchecksettings.h @@ -38,11 +38,28 @@ public: /*virtual*/ void onOpen(const LLSD& key); protected: - void onCancel(); - void onClickDictMove(const std::string& from, const std::string& to); - void onOK(); - void onSave(); + void onBtnCancel(); + void onBtnImport(); + void onBtnMove(const std::string& from, const std::string& to); + void onBtnOK(); + void onSpellCheckSettingsChange(); void refreshDictionaryLists(bool from_settings); }; +class LLFloaterSpellCheckerImport : public LLFloater +{ +public: + LLFloaterSpellCheckerImport(const LLSD& key); + + /*virtual*/ BOOL postBuild(); + +protected: + void onBtnBrowse(); + void onBtnCancel(); + void onBtnOK(); + + std::string mDictionaryDir; + std::string mDictionaryBasename; +}; + #endif // LLFLOATERAUTOREPLACESETTINGS_H diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index e9ce04fd3f..9c27e19255 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -250,6 +250,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("prefs_proxy", "floater_preferences_proxy.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("prefs_hardware_settings", "floater_hardware_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("prefs_spellchecker", "floater_spellcheck.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("prefs_spellchecker_import", "floater_spellcheck_import.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("prefs_translation", "floater_translation_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("perm_prefs", "floater_perm_prefs.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("picks", "floater_picks.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); diff --git a/indra/newview/skins/default/xui/en/floater_spellcheck.xml b/indra/newview/skins/default/xui/en/floater_spellcheck.xml index bd3f60cf4a..91639ed0da 100644 --- a/indra/newview/skins/default/xui/en/floater_spellcheck.xml +++ b/indra/newview/skins/default/xui/en/floater_spellcheck.xml @@ -53,6 +53,16 @@ top_pad="-15" width="175" /> + -- cgit v1.3 From fc1f30a05b14d80786f7fd41b30640092fc5683d Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Thu, 14 Jun 2012 19:51:59 -0400 Subject: STORM-1882: keep dictionary selected when moving, allowing deletion when moved to Available --- indra/newview/llfloaterspellchecksettings.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra/newview/llfloaterspellchecksettings.cpp') diff --git a/indra/newview/llfloaterspellchecksettings.cpp b/indra/newview/llfloaterspellchecksettings.cpp index d350637790..95934d46a8 100644 --- a/indra/newview/llfloaterspellchecksettings.cpp +++ b/indra/newview/llfloaterspellchecksettings.cpp @@ -88,11 +88,13 @@ void LLFloaterSpellCheckerSettings::onBtnMove(const std::string& from, const std row["columns"][0]["font"]["style"] = "NORMAL"; std::vector sel_items = from_ctrl->getAllSelected(); - for (std::vector::const_iterator sel_it = sel_items.begin(); sel_it != sel_items.end(); ++sel_it) + std::vector::const_iterator sel_it; + for ( sel_it = sel_items.begin(); sel_it != sel_items.end(); ++sel_it) { row["value"] = (*sel_it)->getValue(); row["columns"][0]["value"] = (*sel_it)->getColumn(0)->getValue(); to_ctrl->addElement(row); + to_ctrl->setSelectedByValue( (*sel_it)->getValue(), true ); } from_ctrl->deleteSelectedItems(); } -- cgit v1.3 From c8f21753fa4cc88e3ad58f9e117c231d6f5388c0 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Thu, 14 Jun 2012 20:18:16 -0400 Subject: STORM-1881: close dictionary import dialog if parent spell checking prefs dialog is closed --- indra/newview/llfloaterspellchecksettings.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra/newview/llfloaterspellchecksettings.cpp') diff --git a/indra/newview/llfloaterspellchecksettings.cpp b/indra/newview/llfloaterspellchecksettings.cpp index 95934d46a8..5116ec50a6 100644 --- a/indra/newview/llfloaterspellchecksettings.cpp +++ b/indra/newview/llfloaterspellchecksettings.cpp @@ -106,6 +106,7 @@ void LLFloaterSpellCheckerSettings::onClose(bool app_quitting) // don't save anything return; } + LLFloaterReg::hideInstance("prefs_spellchecker_import"); std::list list_dict; -- cgit v1.3 From 02f0f87f95c7f47a93d20de9478bf0b2d5c6e4e6 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Thu, 14 Jun 2012 21:21:42 -0400 Subject: STORM-1880: copy imported dictionary files rather than moving them --- indra/newview/llfloaterspellchecksettings.cpp | 124 +++++++++++++++------ indra/newview/llfloaterspellchecksettings.h | 1 + .../newview/skins/default/xui/en/notifications.xml | 11 ++ 3 files changed, 105 insertions(+), 31 deletions(-) (limited to 'indra/newview/llfloaterspellchecksettings.cpp') diff --git a/indra/newview/llfloaterspellchecksettings.cpp b/indra/newview/llfloaterspellchecksettings.cpp index 5116ec50a6..758ac23b4c 100644 --- a/indra/newview/llfloaterspellchecksettings.cpp +++ b/indra/newview/llfloaterspellchecksettings.cpp @@ -35,6 +35,7 @@ #include "llspellcheck.h" #include "lltrans.h" #include "llviewercontrol.h" +#include "llnotificationsutil.h" #include @@ -291,47 +292,108 @@ void LLFloaterSpellCheckerImport::onBtnOK() return; } - LLSD custom_dict_info; - custom_dict_info["is_primary"] = (bool)gDirUtilp->fileExists(dict_aff); - custom_dict_info["name"] = mDictionaryBasename; - custom_dict_info["language"] = dict_language; - - LLSD custom_dict_map; - llifstream custom_file_in(LLSpellChecker::getDictionaryUserPath() + "user_dictionaries.xml"); - if (custom_file_in.is_open()) + bool imported = false; + std::string settings_dic = LLSpellChecker::getDictionaryUserPath() + mDictionaryBasename + ".dic"; + if ( copyFile( dict_dic, settings_dic ) ) { - LLSDSerialize::fromXMLDocument(custom_dict_map, custom_file_in); - custom_file_in.close(); - } - - LLSD::array_iterator it = custom_dict_map.beginArray(); - for (; it != custom_dict_map.endArray(); ++it) - { - LLSD& dict_info = *it; - if (dict_info["name"].asString() == mDictionaryBasename) + if (gDirUtilp->fileExists(dict_aff)) + { + std::string settings_aff = LLSpellChecker::getDictionaryUserPath() + mDictionaryBasename + ".aff"; + if (copyFile( dict_aff, settings_aff )) + { + imported = true; + } + else + { + LLSD args = LLSD::emptyMap(); + args["FROM_NAME"] = dict_aff; + args["TO_NAME"] = settings_aff; + LLNotificationsUtil::add("SpellingDictImportFailed", args); + } + } + else { - dict_info = custom_dict_info; - break; + imported = true; } } - if (custom_dict_map.endArray() == it) + else { - custom_dict_map.append(custom_dict_info); + LLSD args = LLSD::emptyMap(); + args["FROM_NAME"] = dict_dic; + args["TO_NAME"] = settings_dic; + LLNotificationsUtil::add("SpellingDictImportFailed", args); } - llofstream custom_file_out(LLSpellChecker::getDictionaryUserPath() + "user_dictionaries.xml", std::ios::trunc); - if (custom_file_out.is_open()) + if ( imported ) { - LLSDSerialize::toPrettyXML(custom_dict_map, custom_file_out); - custom_file_out.close(); - } + LLSD custom_dict_info; + custom_dict_info["is_primary"] = (bool)gDirUtilp->fileExists(dict_aff); + custom_dict_info["name"] = mDictionaryBasename; + custom_dict_info["language"] = dict_language; + + LLSD custom_dict_map; + llifstream custom_file_in(LLSpellChecker::getDictionaryUserPath() + "user_dictionaries.xml"); + if (custom_file_in.is_open()) + { + LLSDSerialize::fromXMLDocument(custom_dict_map, custom_file_in); + custom_file_in.close(); + } + + LLSD::array_iterator it = custom_dict_map.beginArray(); + for (; it != custom_dict_map.endArray(); ++it) + { + LLSD& dict_info = *it; + if (dict_info["name"].asString() == mDictionaryBasename) + { + dict_info = custom_dict_info; + break; + } + } + if (custom_dict_map.endArray() == it) + { + custom_dict_map.append(custom_dict_info); + } - LLFile::rename(dict_dic, LLSpellChecker::getDictionaryUserPath() + mDictionaryBasename + ".dic"); - if (gDirUtilp->fileExists(dict_aff)) - { - LLFile::rename(dict_aff, LLSpellChecker::getDictionaryUserPath() + mDictionaryBasename + ".aff"); + llofstream custom_file_out(LLSpellChecker::getDictionaryUserPath() + "user_dictionaries.xml", std::ios::trunc); + if (custom_file_out.is_open()) + { + LLSDSerialize::toPrettyXML(custom_dict_map, custom_file_out); + custom_file_out.close(); + } + + LLSpellChecker::refreshDictionaryMap(); } - LLSpellChecker::refreshDictionaryMap(); closeFloater(false); } + +bool LLFloaterSpellCheckerImport::copyFile(const std::string from, const std::string to) +{ + bool copied = false; + LLFILE* in = LLFile::fopen(from, "rb"); /* Flawfinder: ignore */ + if (in) + { + LLFILE* out = LLFile::fopen(to, "wb"); /* Flawfinder: ignore */ + if (out) + { + char buf[16384]; /* Flawfinder: ignore */ + size_t readbytes; + bool write_ok = true; + while(write_ok && (readbytes = fread(buf, 1, 16384, in))) /* Flawfinder: ignore */ + { + if (fwrite(buf, 1, readbytes, out) != readbytes) + { + LL_WARNS("SpellCheck") << "Short write" << LL_ENDL; + write_ok = false; + } + } + if ( write_ok ) + { + copied = true; + } + fclose(out); + } + } + fclose(in); + return copied; +} diff --git a/indra/newview/llfloaterspellchecksettings.h b/indra/newview/llfloaterspellchecksettings.h index 4bc68e2a88..8c4ac22bc6 100644 --- a/indra/newview/llfloaterspellchecksettings.h +++ b/indra/newview/llfloaterspellchecksettings.h @@ -58,6 +58,7 @@ protected: void onBtnBrowse(); void onBtnCancel(); void onBtnOK(); + bool copyFile(const std::string from, const std::string to); std::string mDictionaryDir; std::string mDictionaryBasename; diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index bc69e973ed..c04e33fe8e 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -2396,6 +2396,17 @@ Would you be my friend? fail + + Unable to copy + [FROM_NAME] + to + [TO_NAME] + fail + + Date: Fri, 15 Jun 2012 09:16:49 -0400 Subject: minor cosmetic changes to spelling floater --- indra/newview/llfloaterspellchecksettings.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'indra/newview/llfloaterspellchecksettings.cpp') diff --git a/indra/newview/llfloaterspellchecksettings.cpp b/indra/newview/llfloaterspellchecksettings.cpp index 758ac23b4c..8e4e5bb744 100644 --- a/indra/newview/llfloaterspellchecksettings.cpp +++ b/indra/newview/llfloaterspellchecksettings.cpp @@ -69,7 +69,7 @@ BOOL LLFloaterSpellCheckerSettings::postBuild(void) getChild("spellcheck_main_combo")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::refreshDictionaries, this, false)); getChild("spellcheck_moveleft_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onBtnMove, this, "spellcheck_active_list", "spellcheck_available_list")); getChild("spellcheck_moveright_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onBtnMove, this, "spellcheck_available_list", "spellcheck_active_list")); - + center(); return true; } @@ -85,8 +85,6 @@ void LLFloaterSpellCheckerSettings::onBtnMove(const std::string& from, const std LLSD row; row["columns"][0]["column"] = "name"; - row["columns"][0]["font"]["name"] = "SANSSERIF_SMALL"; - row["columns"][0]["font"]["style"] = "NORMAL"; std::vector sel_items = from_ctrl->getAllSelected(); std::vector::const_iterator sel_it; @@ -164,7 +162,6 @@ void LLFloaterSpellCheckerSettings::refreshDictionaries(bool from_settings) dict_cur = LLSpellChecker::instance().getPrimaryDictionary(); } dict_combo->clearRows(); - dict_combo->setEnabled(enabled); const LLSD& dict_map = LLSpellChecker::getDictionaryMap(); if (dict_map.size()) @@ -182,6 +179,7 @@ void LLFloaterSpellCheckerSettings::refreshDictionaries(bool from_settings) dict_combo->clear(); } } + dict_combo->setEnabled(enabled); // Populate the available and active dictionary list LLScrollListCtrl* avail_ctrl = findChild("spellcheck_available_list"); @@ -210,8 +208,6 @@ void LLFloaterSpellCheckerSettings::refreshDictionaries(bool from_settings) LLSD row; row["columns"][0]["column"] = "name"; - row["columns"][0]["font"]["name"] = "SANSSERIF_SMALL"; - row["columns"][0]["font"]["style"] = "NORMAL"; active_ctrl->clearRows(); active_ctrl->setEnabled(enabled); -- cgit v1.3 From bdb0f4f4853472bdba94ed7a6a70653de6290e0c Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Fri, 15 Jun 2012 17:11:58 +0200 Subject: STORM-276 FIXED Main dictionary combobox in spell check settings floater doesn't sort dictionaries by name --- indra/newview/llfloaterspellchecksettings.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra/newview/llfloaterspellchecksettings.cpp') diff --git a/indra/newview/llfloaterspellchecksettings.cpp b/indra/newview/llfloaterspellchecksettings.cpp index 8e4e5bb744..22eaa566fe 100644 --- a/indra/newview/llfloaterspellchecksettings.cpp +++ b/indra/newview/llfloaterspellchecksettings.cpp @@ -179,6 +179,7 @@ void LLFloaterSpellCheckerSettings::refreshDictionaries(bool from_settings) dict_combo->clear(); } } + dict_combo->sortByName(); dict_combo->setEnabled(enabled); // Populate the available and active dictionary list -- cgit v1.3 From 3f7ed8b888b5725912e38f19e36c4c5e1583ea7c Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Fri, 15 Jun 2012 12:36:03 -0400 Subject: STORM-1883: add alert when a secondary dictionary is imported --- indra/newview/llfloaterspellchecksettings.cpp | 4 ++++ indra/newview/skins/default/xui/en/notifications.xml | 11 +++++++++++ 2 files changed, 15 insertions(+) (limited to 'indra/newview/llfloaterspellchecksettings.cpp') diff --git a/indra/newview/llfloaterspellchecksettings.cpp b/indra/newview/llfloaterspellchecksettings.cpp index 22eaa566fe..d7fbc94631 100644 --- a/indra/newview/llfloaterspellchecksettings.cpp +++ b/indra/newview/llfloaterspellchecksettings.cpp @@ -310,6 +310,10 @@ void LLFloaterSpellCheckerImport::onBtnOK() } else { + LLSD args = LLSD::emptyMap(); + args["DIC_NAME"] = dict_dic; + LLNotificationsUtil::add("SpellingDictIsSecondary", args); + imported = true; } } diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index c04e33fe8e..79e02727e9 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -2396,6 +2396,17 @@ Would you be my friend? fail + +The dictionary [DIC_NAME] does not appear to have an "aff" file; this means that it is a "secondary" dictionary. +It can be used as an additional dictionary, but not as your Main dictionary. + +See https://wiki.secondlife.com/wiki/Adding_Spelling_Dictionaries + confirm + + Date: Fri, 15 Jun 2012 20:47:02 +0200 Subject: STORM-276 Ease-of-use importing of Open Office dictionary extensions --- indra/newview/llfilepicker.cpp | 8 ++- indra/newview/llfloaterspellchecksettings.cpp | 87 ++++++++++++++++++++++++++- indra/newview/llfloaterspellchecksettings.h | 1 + 3 files changed, 92 insertions(+), 4 deletions(-) (limited to 'indra/newview/llfloaterspellchecksettings.cpp') diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index cbb5a40cfa..5c963025cb 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -59,7 +59,7 @@ LLFilePicker LLFilePicker::sInstance; #define RAW_FILTER L"RAW files (*.raw)\0*.raw\0" #define MODEL_FILTER L"Model files (*.dae)\0*.dae\0" #define SCRIPT_FILTER L"Script files (*.lsl)\0*.lsl\0" -#define DICTIONARY_FILTER L"Dictionary files (*.dic)\0*.dic\0" +#define DICTIONARY_FILTER L"Dictionary files (*.dic; *.xcu)\0*.dic;*.xcu\0" #endif // @@ -651,7 +651,9 @@ Boolean LLFilePicker::navOpenFilterProc(AEDesc *theItem, void *info, void *callB else if (filter == FFLOAD_DICTIONARY) { if (fileInfo.filetype != 'DIC ' && - (fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("dic"), kCFCompareCaseInsensitive) != kCFCompareEqualTo)) ) + fileInfo.filetype != 'XCU ' && + (fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("dic"), kCFCompareCaseInsensitive) != kCFCompareEqualTo) && + fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("xcu"), kCFCompareCaseInsensitive) != kCFCompareEqualTo)) { result = false; } @@ -1251,7 +1253,7 @@ static std::string add_script_filter_to_gtkchooser(GtkWindow *picker) static std::string add_dictionary_filter_to_gtkchooser(GtkWindow *picker) { return add_simple_mime_filter_to_gtkchooser(picker, "text/plain", - LLTrans::getString("dictionary_files") + " (*.dic)"); + LLTrans::getString("dictionary_files") + " (*.dic; *.xcu)"); } BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename ) diff --git a/indra/newview/llfloaterspellchecksettings.cpp b/indra/newview/llfloaterspellchecksettings.cpp index d7fbc94631..c62577bc94 100644 --- a/indra/newview/llfloaterspellchecksettings.cpp +++ b/indra/newview/llfloaterspellchecksettings.cpp @@ -264,7 +264,18 @@ void LLFloaterSpellCheckerImport::onBtnBrowse() return; } - const std::string filepath = file_picker.getFirstFile(); + std::string filepath = file_picker.getFirstFile(); + + const std::string extension = gDirUtilp->getExtension(filepath); + if ("xcu" == extension) + { + filepath = parseXcuFile(filepath); + if (filepath.empty()) + { + return; + } + } + getChild("dictionary_path")->setValue(filepath); mDictionaryDir = gDirUtilp->getDirName(filepath); @@ -398,3 +409,77 @@ bool LLFloaterSpellCheckerImport::copyFile(const std::string from, const std::st fclose(in); return copied; } + +std::string LLFloaterSpellCheckerImport::parseXcuFile(const std::string& file_path) const +{ + LLXMLNodePtr xml_root; + if ( (!LLUICtrlFactory::getLayeredXMLNode(file_path, xml_root)) || (xml_root.isNull()) ) + { + return LLStringUtil::null; + } + + // Bury down to the "Dictionaries" parent node + LLXMLNode* dict_node = NULL; + for (LLXMLNode* outer_node = xml_root->getFirstChild(); outer_node && !dict_node; outer_node = outer_node->getNextSibling()) + { + std::string temp; + if ( (outer_node->getAttributeString("oor:name", temp)) && ("ServiceManager" == temp) ) + { + for (LLXMLNode* inner_node = outer_node->getFirstChild(); inner_node && !dict_node; inner_node = inner_node->getNextSibling()) + { + if ( (inner_node->getAttributeString("oor:name", temp)) && ("Dictionaries" == temp) ) + { + dict_node = inner_node; + break; + } + } + } + } + + if (dict_node) + { + // Iterate over all child nodes until we find one that has a DICT_SPELL node + for (LLXMLNode* outer_node = dict_node->getFirstChild(); outer_node; outer_node = outer_node->getNextSibling()) + { + std::string temp; + LLXMLNodePtr location_node, format_node; + for (LLXMLNode* inner_node = outer_node->getFirstChild(); inner_node; inner_node = inner_node->getNextSibling()) + { + if (inner_node->getAttributeString("oor:name", temp)) + { + if ("Locations" == temp) + { + inner_node->getChild("value", location_node, false); + } + else if ("Format" == temp) + { + inner_node->getChild("value", format_node, false); + } + } + } + if ( (format_node.isNull()) || ("DICT_SPELL" != format_node->getValue()) || (location_node.isNull()) ) + { + continue; + } + + // Found a list of file locations, return the .dic (if present) + std::list location_list; + boost::split(location_list, location_node->getValue(), boost::is_any_of(std::string(" "))); + for (std::list::iterator it = location_list.begin(); it != location_list.end(); ++it) + { + std::string& location = *it; + if ("\\" != gDirUtilp->getDirDelimiter()) + LLStringUtil::replaceString(location, "\\", gDirUtilp->getDirDelimiter()); + else + LLStringUtil::replaceString(location, "/", gDirUtilp->getDirDelimiter()); + LLStringUtil::replaceString(location, "%origin%", gDirUtilp->getDirName(file_path)); + if ("dic" == gDirUtilp->getExtension(location)) + { + return location; + } + } + } + } + + return LLStringUtil::null; +} diff --git a/indra/newview/llfloaterspellchecksettings.h b/indra/newview/llfloaterspellchecksettings.h index 8c4ac22bc6..eded3a9133 100644 --- a/indra/newview/llfloaterspellchecksettings.h +++ b/indra/newview/llfloaterspellchecksettings.h @@ -59,6 +59,7 @@ protected: void onBtnCancel(); void onBtnOK(); bool copyFile(const std::string from, const std::string to); + std::string parseXcuFile(const std::string& file_path) const; std::string mDictionaryDir; std::string mDictionaryBasename; -- cgit v1.3 From 5dceb6b06c8493d0bf0e21ead14539185bd4b4a8 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Wed, 20 Jun 2012 21:52:42 -0400 Subject: STORM-1889: require all fields when importing spelling dictionary --- indra/newview/llfloaterspellchecksettings.cpp | 56 ++++++++++++---------- .../newview/skins/default/xui/en/notifications.xml | 8 ++++ 2 files changed, 39 insertions(+), 25 deletions(-) (limited to 'indra/newview/llfloaterspellchecksettings.cpp') diff --git a/indra/newview/llfloaterspellchecksettings.cpp b/indra/newview/llfloaterspellchecksettings.cpp index c62577bc94..5ecdd11918 100644 --- a/indra/newview/llfloaterspellchecksettings.cpp +++ b/indra/newview/llfloaterspellchecksettings.cpp @@ -294,47 +294,53 @@ void LLFloaterSpellCheckerImport::onBtnOK() const std::string dict_aff = mDictionaryDir + gDirUtilp->getDirDelimiter() + mDictionaryBasename + ".aff"; std::string dict_language = getChild("dictionary_language")->getValue().asString(); LLStringUtil::trim(dict_language); - if ( (dict_language.empty()) || (!gDirUtilp->fileExists(dict_dic)) || - (mDictionaryDir.empty()) || (mDictionaryBasename.empty()) ) - { - return; - } bool imported = false; - std::string settings_dic = LLSpellChecker::getDictionaryUserPath() + mDictionaryBasename + ".dic"; - if ( copyFile( dict_dic, settings_dic ) ) + if ( dict_language.empty() + || mDictionaryDir.empty() + || mDictionaryBasename.empty() + || ! gDirUtilp->fileExists(dict_dic) + ) { - if (gDirUtilp->fileExists(dict_aff)) + LLNotificationsUtil::add("SpellingDictImportRequired"); + } + else + { + std::string settings_dic = LLSpellChecker::getDictionaryUserPath() + mDictionaryBasename + ".dic"; + if ( copyFile( dict_dic, settings_dic ) ) { - std::string settings_aff = LLSpellChecker::getDictionaryUserPath() + mDictionaryBasename + ".aff"; - if (copyFile( dict_aff, settings_aff )) + if (gDirUtilp->fileExists(dict_aff)) { - imported = true; + std::string settings_aff = LLSpellChecker::getDictionaryUserPath() + mDictionaryBasename + ".aff"; + if (copyFile( dict_aff, settings_aff )) + { + imported = true; + } + else + { + LLSD args = LLSD::emptyMap(); + args["FROM_NAME"] = dict_aff; + args["TO_NAME"] = settings_aff; + LLNotificationsUtil::add("SpellingDictImportFailed", args); + } } else { LLSD args = LLSD::emptyMap(); - args["FROM_NAME"] = dict_aff; - args["TO_NAME"] = settings_aff; - LLNotificationsUtil::add("SpellingDictImportFailed", args); + args["DIC_NAME"] = dict_dic; + LLNotificationsUtil::add("SpellingDictIsSecondary", args); + + imported = true; } } else { LLSD args = LLSD::emptyMap(); - args["DIC_NAME"] = dict_dic; - LLNotificationsUtil::add("SpellingDictIsSecondary", args); - - imported = true; + args["FROM_NAME"] = dict_dic; + args["TO_NAME"] = settings_dic; + LLNotificationsUtil::add("SpellingDictImportFailed", args); } } - else - { - LLSD args = LLSD::emptyMap(); - args["FROM_NAME"] = dict_dic; - args["TO_NAME"] = settings_dic; - LLNotificationsUtil::add("SpellingDictImportFailed", args); - } if ( imported ) { diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 79e02727e9..1cb0fad9a9 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -2396,6 +2396,14 @@ Would you be my friend? fail + + You must specify a file, a name, and a language. + fail + +