diff options
-rw-r--r-- | indra/llui/llspellcheck.cpp | 45 | ||||
-rw-r--r-- | indra/llui/llspellcheck.h | 5 | ||||
-rw-r--r-- | indra/newview/llfilepicker.cpp | 22 | ||||
-rw-r--r-- | indra/newview/llfilepicker.h | 1 | ||||
-rw-r--r-- | indra/newview/llfloaterspellchecksettings.cpp | 127 | ||||
-rw-r--r-- | indra/newview/llfloaterspellchecksettings.h | 25 | ||||
-rw-r--r-- | indra/newview/llviewerfloaterreg.cpp | 1 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/floater_spellcheck.xml | 10 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/floater_spellcheck_import.xml | 116 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/strings.xml | 1 |
10 files changed, 335 insertions, 18 deletions
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,32 +88,63 @@ S32 LLSpellChecker::getSuggestions(const std::string& word, std::vector<std::str } // static -const LLSD LLSpellChecker::getDictionaryData(const std::string& dict_name) +const LLSD LLSpellChecker::getDictionaryData(const std::string& dict_language) { for (LLSD::array_const_iterator it = sDictMap.beginArray(); it != sDictMap.endArray(); ++it) { const LLSD& dict_entry = *it; - if (dict_name == dict_entry["language"].asString()) + if (dict_language == dict_entry["language"].asString()) return dict_entry; } return LLSD(); } // static +void LLSpellChecker::setDictionaryData(const LLSD& dict_info) +{ + const std::string dict_language = dict_info["language"].asString(); + if (dict_language.empty()) + return; + + for (LLSD::array_iterator it = sDictMap.beginArray(); it != sDictMap.endArray(); ++it) + { + LLSD& dict_entry = *it; + if (dict_language == dict_entry["language"].asString()) + { + dict_entry = dict_info; + return; + } + } + sDictMap.append(dict_info); + return; +} + +// static void LLSpellChecker::refreshDictionaryMap() { const std::string app_path = getDictionaryAppPath(); const std::string user_path = getDictionaryUserPath(); // Load dictionary information (file name, friendly name, ...) - llifstream user_map(user_path + "dictionaries.xml", std::ios::binary); - if ( (!user_map.is_open()) || (0 == LLSDSerialize::fromXMLDocument(sDictMap, user_map)) || (0 == sDictMap.size()) ) + llifstream user_file(user_path + "dictionaries.xml", std::ios::binary); + if ( (!user_file.is_open()) || (0 == LLSDSerialize::fromXMLDocument(sDictMap, user_file)) || (0 == sDictMap.size()) ) { - llifstream app_map(app_path + "dictionaries.xml", std::ios::binary); - if ( (!app_map.is_open()) || (0 == LLSDSerialize::fromXMLDocument(sDictMap, app_map)) || (0 == sDictMap.size()) ) + llifstream app_file(app_path + "dictionaries.xml", std::ios::binary); + if ( (!app_file.is_open()) || (0 == LLSDSerialize::fromXMLDocument(sDictMap, app_file)) || (0 == sDictMap.size()) ) return; } + // Load user installed dictionary information + llifstream custom_file(user_path + "user_dictionaries.xml", std::ios::binary); + if (custom_file.is_open()) + { + LLSD custom_dict_map; + LLSDSerialize::fromXMLDocument(custom_dict_map, custom_file); + for (LLSD::array_const_iterator it = custom_dict_map.beginArray(); it != custom_dict_map.endArray(); ++it) + setDictionaryData(*it); + custom_file.close(); + } + // Look for installed dictionaries std::string tmp_app_path, tmp_user_path; for (LLSD::array_iterator it = sDictMap.beginArray(); it != sDictMap.endArray(); ++it) @@ -126,6 +157,8 @@ void LLSpellChecker::refreshDictionaryMap() sdDict["has_custom"] = (!tmp_user_path.empty()) && (gDirUtilp->fileExists(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<void()> 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 <boost/algorithm/string.hpp> +///---------------------------------------------------------------------------- +/// 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<LLUICtrl>("spellcheck_import_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onBtnImport, this)); getChild<LLUICtrl>("spellcheck_main_combo")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::refreshDictionaryLists, this, false)); - getChild<LLUICtrl>("spellcheck_moveleft_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onClickDictMove, this, "spellcheck_active_list", "spellcheck_available_list")); - getChild<LLUICtrl>("spellcheck_moveright_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onClickDictMove, this, "spellcheck_available_list", "spellcheck_active_list")); - getChild<LLUICtrl>("spellcheck_ok")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onOK, this)); - getChild<LLUICtrl>("spellcheck_cancel")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onCancel, this)); + getChild<LLUICtrl>("spellcheck_moveleft_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onBtnMove, this, "spellcheck_active_list", "spellcheck_available_list")); + getChild<LLUICtrl>("spellcheck_moveright_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onBtnMove, this, "spellcheck_available_list", "spellcheck_active_list")); + getChild<LLUICtrl>("spellcheck_ok")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onBtnOK, this)); + getChild<LLUICtrl>("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<LLScrollListCtrl>(from); LLScrollListCtrl* to_ctrl = findChild<LLScrollListCtrl>(to); @@ -75,7 +88,7 @@ void LLFloaterSpellCheckerSettings::onClickDictMove(const std::string& from, con from_ctrl->deleteSelectedItems(); } -void LLFloaterSpellCheckerSettings::onOK() +void LLFloaterSpellCheckerSettings::onBtnOK() { std::list<std::string> 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<LLUICtrl>("dictionary_path_browse")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerImport::onBtnBrowse, this)); + getChild<LLUICtrl>("ok_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerImport::onBtnOK, this)); + getChild<LLUICtrl>("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<LLUICtrl>("dictionary_path")->setValue(filepath); + + mDictionaryDir = gDirUtilp->getDirName(filepath); + mDictionaryBasename = gDirUtilp->getBaseFileName(filepath, true); + getChild<LLUICtrl>("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<LLUICtrl>("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 2fbf47617a..3a4428d4c3 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 // LLFLOATERSPELLCHECKERSETTINGS_H diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 4d84262a3a..8d716a7317 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -249,6 +249,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("preferences", "floater_preferences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreference>); LLFloaterReg::add("prefs_proxy", "floater_preferences_proxy.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreferenceProxy>); LLFloaterReg::add("prefs_hardware_settings", "floater_hardware_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHardwareSettings>); + LLFloaterReg::add("prefs_spellchecker_import", "floater_spellcheck_import.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSpellCheckerImport>); LLFloaterReg::add("prefs_translation", "floater_translation_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTranslationSettings>); LLFloaterReg::add("prefs_spellchecker", "floater_spellcheck.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSpellCheckerSettings>); LLFloaterReg::add("prefs_autoreplace", "floater_autoreplace.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAutoReplaceSettings>); 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" /> + <button + follows="left|top" + height="23" + label="Import" + label_selected="Import" + layout="topleft" + left_pad="5" + name="spellcheck_import_btn" + top_delta="0" + width="75" /> <text enabled_control="SpellCheck" follows="top|left" diff --git a/indra/newview/skins/default/xui/en/floater_spellcheck_import.xml b/indra/newview/skins/default/xui/en/floater_spellcheck_import.xml new file mode 100644 index 0000000000..b54090015d --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_spellcheck_import.xml @@ -0,0 +1,116 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + border="true" + can_close="true" + can_minimize="true" + bottom="275" + left="300" + can_resize="false" + height="140" + width="400" + name="spellcheck_import" + title="Import Dictionary"> + <text + follows="top|left" + height="16" + layout="topleft" + left="25" + top="15" + type="string" + width="65"> + Dictionary: + </text> + <line_editor + enabled="false" + follows="left|top" + height="23" + layout="topleft" + left_pad="10" + max_length_bytes="255" + name="dictionary_path" + top_delta="-5" + width="200" /> + <button + follows="left|top" + height="23" + label="Browse" + label_selected="Browse" + layout="topleft" + left_pad="5" + name="dictionary_path_browse" + top_delta="0" + width="75" /> + <text + follows="top|left" + height="16" + layout="topleft" + left="25" + top_pad="8" + type="string" + width="65"> + Name: + </text> + <line_editor + enabled="false" + follows="left|top" + height="23" + layout="topleft" + left_pad="10" + max_length_bytes="255" + name="dictionary_name" + top_delta="-5" + width="200" /> + <text + follows="top|left" + height="16" + layout="topleft" + left="25" + top_pad="8" + type="string" + width="65"> + Language: + </text> + <line_editor + follows="left|top" + height="23" + layout="topleft" + left_pad="10" + max_length_bytes="255" + name="dictionary_language" + top_delta="-5" + width="200" /> + <view_border + top_pad="10" + left="2" + height="0" + width="396" + follows="left|top" + bevel_style="none" + border_thickness="1" + mouse_opaque="false" + name="divisor"/> + <button + top_pad="10" + right="280" + height="22" + width="90" + enabled="true" + follows="left|top" + mouse_opaque="true" + halign="center" + scale_image="true" + name="ok_btn" + label="Import" /> + <button + top_delta="0" + right="380" + height="22" + width="90" + enabled="true" + follows="left|top" + mouse_opaque="true" + halign="center" + scale_image="true" + name="cancel_btn" + label="Cancel" /> +</floater> diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 4ccec4838a..4b58df595f 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -440,6 +440,7 @@ Please try logging in again in a minute.</string> <string name="load_files">Load Files</string> <string name="choose_the_directory">Choose Directory</string> <string name="script_files">Scripts</string> + <string name="dictionary_files">Dictionaries</string> <!-- LSL Usage Hover Tips --> <!-- NOTE: For now these are set as translate="false", until DEV-40761 is implemented (to internationalize the rest of tooltips in the same window). |