diff options
| -rw-r--r-- | indra/llui/llspellcheck.cpp | 103 | ||||
| -rw-r--r-- | indra/llui/llspellcheck.h | 13 | ||||
| -rw-r--r-- | indra/newview/llfloaterspellchecksettings.cpp | 25 | ||||
| -rw-r--r-- | indra/newview/llfloaterspellchecksettings.h | 2 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/floater_spellcheck.xml | 35 | 
5 files changed, 147 insertions, 31 deletions
diff --git a/indra/llui/llspellcheck.cpp b/indra/llui/llspellcheck.cpp index 8b3ca50c29..887714d720 100644 --- a/indra/llui/llspellcheck.cpp +++ b/indra/llui/llspellcheck.cpp @@ -41,6 +41,9 @@ static const std::string DICT_DIR = "dictionaries";  static const std::string DICT_CUSTOM_SUFFIX = "_custom";  static const std::string DICT_IGNORE_SUFFIX = "_ignore"; +static const std::string DICT_FILE_MAIN = "dictionaries.xml"; +static const std::string DICT_FILE_USER = "user_dictionaries.xml"; +  LLSD LLSpellChecker::sDictMap;  LLSpellChecker::settings_change_signal_t LLSpellChecker::sSettingsChangeSignal; @@ -141,10 +144,10 @@ void LLSpellChecker::refreshDictionaryMap()  	const std::string user_path = getDictionaryUserPath();  	// Load dictionary information (file name, friendly name, ...) -	llifstream user_file(user_path + "dictionaries.xml", std::ios::binary); +	llifstream user_file(user_path + DICT_FILE_MAIN, std::ios::binary);  	if ( (!user_file.is_open()) || (0 == LLSDSerialize::fromXMLDocument(sDictMap, user_file)) || (0 == sDictMap.size()) )  	{ -		llifstream app_file(app_path + "dictionaries.xml", std::ios::binary); +		llifstream app_file(app_path + DICT_FILE_MAIN, std::ios::binary);  		if ( (!app_file.is_open()) || (0 == LLSDSerialize::fromXMLDocument(sDictMap, app_file)) || (0 == sDictMap.size()) )  		{  			return; @@ -152,7 +155,7 @@ void LLSpellChecker::refreshDictionaryMap()  	}  	// Load user installed dictionary information -	llifstream custom_file(user_path + "user_dictionaries.xml", std::ios::binary); +	llifstream custom_file(user_path + DICT_FILE_USER, std::ios::binary);  	if (custom_file.is_open())  	{  		LLSD custom_dict_map; @@ -245,6 +248,13 @@ void LLSpellChecker::addToDictFile(const std::string& dict_path, const std::stri  	}  } +bool LLSpellChecker::isActiveDictionary(const std::string& dict_language) const +{ +	return +		(mDictLanguage == dict_language) ||  +		(mDictSecondary.end() != std::find(mDictSecondary.begin(), mDictSecondary.end(), dict_language)); +} +  void LLSpellChecker::setSecondaryDictionaries(dict_list_t dict_list)  {  	if (!getUseSpellCheck()) @@ -263,8 +273,8 @@ void LLSpellChecker::setSecondaryDictionaries(dict_list_t dict_list)  	{  		mDictSecondary = dict_list; -		std::string dict_name = mDictName; -		initHunspell(dict_name); +		std::string dict_language = mDictLanguage; +		initHunspell(dict_language);  	}  	else if (end_added != dict_add.begin())		// Add the new secondary dictionaries one by one  	{ @@ -293,18 +303,18 @@ void LLSpellChecker::setSecondaryDictionaries(dict_list_t dict_list)  	}  } -void LLSpellChecker::initHunspell(const std::string& dict_name) +void LLSpellChecker::initHunspell(const std::string& dict_language)  {  	if (mHunspell)  	{  		delete mHunspell;  		mHunspell = NULL; -		mDictName.clear(); +		mDictLanguage.clear();  		mDictFile.clear();  		mIgnoreList.clear();  	} -	const LLSD dict_entry = (!dict_name.empty()) ? getDictionaryData(dict_name) : LLSD(); +	const LLSD dict_entry = (!dict_language.empty()) ? getDictionaryData(dict_language) : LLSD();  	if ( (!dict_entry.isDefined()) || (!dict_entry["installed"].asBoolean()) || (!dict_entry["is_primary"].asBoolean()))  	{  		sSettingsChangeSignal(); @@ -330,7 +340,7 @@ void LLSpellChecker::initHunspell(const std::string& dict_name)  			return;  		} -		mDictName = dict_name; +		mDictLanguage = dict_language;  		mDictFile = dict_entry["name"].asString();  		if (dict_entry["has_custom"].asBoolean()) @@ -406,18 +416,85 @@ bool LLSpellChecker::getUseSpellCheck()  }  // static +bool LLSpellChecker::canRemoveDictionary(const std::string& dict_language) +{ +	// Only user-installed inactive dictionaries can be removed +	const LLSD dict_info = getDictionaryData(dict_language); +	return  +		(dict_info["user_installed"].asBoolean()) &&  +		( (!getUseSpellCheck()) || (!LLSpellChecker::instance().isActiveDictionary(dict_language)) ); +} + +// static +void LLSpellChecker::removeDictionary(const std::string& dict_language) +{ +	if (!canRemoveDictionary(dict_language)) +	{ +		return; +	} + +	LLSD dict_map = loadUserDictionaryMap(); +	for (LLSD::array_const_iterator it = dict_map.beginArray(); it != dict_map.endArray(); ++it) +	{ +		const LLSD& dict_info = *it; +		if (dict_info["language"].asString() == dict_language) +		{ +			const std::string dict_dic = getDictionaryUserPath() + dict_info["name"].asString() + ".dic"; +			if (gDirUtilp->fileExists(dict_dic)) +			{ +				LLFile::remove(dict_dic); +			} +			const std::string dict_aff = getDictionaryUserPath() + dict_info["name"].asString() + ".aff"; +			if (gDirUtilp->fileExists(dict_aff)) +			{ +				LLFile::remove(dict_aff); +			} +			dict_map.erase(it - dict_map.beginArray()); +			break; +		} +	} +	saveUserDictionaryMap(dict_map); + +	refreshDictionaryMap(); +} + +// static +LLSD LLSpellChecker::loadUserDictionaryMap() +{ +	LLSD dict_map; +	llifstream dict_file(getDictionaryUserPath() + DICT_FILE_USER, std::ios::binary); +	if (dict_file.is_open()) +	{ +		LLSDSerialize::fromXMLDocument(dict_map, dict_file); +		dict_file.close(); +	} +	return dict_map; +} + +// static +void LLSpellChecker::saveUserDictionaryMap(const LLSD& dict_map) +{ +	llofstream dict_file(getDictionaryUserPath() + DICT_FILE_USER, std::ios::trunc); +	if (dict_file.is_open()) +	{ +		LLSDSerialize::toPrettyXML(dict_map, dict_file); +		dict_file.close(); +	} +} + +// static  boost::signals2::connection LLSpellChecker::setSettingsChangeCallback(const settings_change_signal_t::slot_type& cb)  {  	return sSettingsChangeSignal.connect(cb);  }  // static -void LLSpellChecker::setUseSpellCheck(const std::string& dict_name) +void LLSpellChecker::setUseSpellCheck(const std::string& dict_language)  { -	if ( (((dict_name.empty()) && (getUseSpellCheck())) || (!dict_name.empty())) &&  -		 (LLSpellChecker::instance().mDictName != dict_name) ) +	if ( (((dict_language.empty()) && (getUseSpellCheck())) || (!dict_language.empty())) &&  +		 (LLSpellChecker::instance().mDictLanguage != dict_language) )  	{ -		LLSpellChecker::instance().initHunspell(dict_name); +		LLSpellChecker::instance().initHunspell(dict_language);  	}  } diff --git a/indra/llui/llspellcheck.h b/indra/llui/llspellcheck.h index 776565b20a..4ab80195ea 100644 --- a/indra/llui/llspellcheck.h +++ b/indra/llui/llspellcheck.h @@ -48,15 +48,17 @@ public:  	S32  getSuggestions(const std::string& word, std::vector<std::string>& suggestions) const;  protected:  	void addToDictFile(const std::string& dict_path, const std::string& word); -	void initHunspell(const std::string& dict_name); +	void initHunspell(const std::string& dict_language);  public:  	typedef std::list<std::string> dict_list_t; -	const std::string&	getActiveDictionary() const { return mDictName; } +	const std::string&	getPrimaryDictionary() const { return mDictLanguage; }  	const dict_list_t&	getSecondaryDictionaries() const { return mDictSecondary; } +	bool				isActiveDictionary(const std::string& dict_language) const;  	void				setSecondaryDictionaries(dict_list_t dict_list); +	static bool				 canRemoveDictionary(const std::string& dict_language);  	static const std::string getDictionaryAppPath();  	static const std::string getDictionaryUserPath();  	static const LLSD		 getDictionaryData(const std::string& dict_language); @@ -64,9 +66,12 @@ public:  	static bool				 getUseSpellCheck();  	static bool				 hasDictionary(const std::string& dict_language, bool check_installed = false);  	static void				 refreshDictionaryMap(); -	static void				 setUseSpellCheck(const std::string& dict_name); +	static void				 removeDictionary(const std::string& dict_language); +	static void				 setUseSpellCheck(const std::string& dict_language);  protected: +	static LLSD				 loadUserDictionaryMap();  	static void				 setDictionaryData(const LLSD& dict_info); +	static void				 saveUserDictionaryMap(const LLSD& dict_map);  public:  	typedef boost::signals2::signal<void()> settings_change_signal_t; @@ -76,7 +81,7 @@ protected:  protected:  	Hunspell*	mHunspell; -	std::string	mDictName; +	std::string	mDictLanguage;  	std::string	mDictFile;  	dict_list_t	mDictSecondary;  	std::vector<std::string> mIgnoreList; diff --git a/indra/newview/llfloaterspellchecksettings.cpp b/indra/newview/llfloaterspellchecksettings.cpp index 0b4f08c327..059a28fbcd 100644 --- a/indra/newview/llfloaterspellchecksettings.cpp +++ b/indra/newview/llfloaterspellchecksettings.cpp @@ -46,10 +46,24 @@ LLFloaterSpellCheckerSettings::LLFloaterSpellCheckerSettings(const LLSD& key)  {  } +void LLFloaterSpellCheckerSettings::draw() +{ +	LLFloater::draw(); + +	std::vector<LLScrollListItem*> sel_items = getChild<LLScrollListCtrl>("spellcheck_available_list")->getAllSelected(); +	bool enable_remove = !sel_items.empty(); +	for (std::vector<LLScrollListItem*>::const_iterator sel_it = sel_items.begin(); sel_it != sel_items.end(); ++sel_it) +	{ +		enable_remove &= LLSpellChecker::canRemoveDictionary((*sel_it)->getValue().asString()); +	} +	getChild<LLUICtrl>("spellcheck_remove_btn")->setEnabled(enable_remove); +} +  BOOL LLFloaterSpellCheckerSettings::postBuild(void)  {  	gSavedSettings.getControl("SpellCheck")->getSignal()->connect(boost::bind(&LLFloaterSpellCheckerSettings::refreshDictionaries, this, false));  	LLSpellChecker::setSettingsChangeCallback(boost::bind(&LLFloaterSpellCheckerSettings::onSpellCheckSettingsChange, this)); +	getChild<LLUICtrl>("spellcheck_remove_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onBtnRemove, this));  	getChild<LLUICtrl>("spellcheck_import_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onBtnImport, this));  	getChild<LLUICtrl>("spellcheck_main_combo")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::refreshDictionaries, this, false));  	getChild<LLUICtrl>("spellcheck_moveleft_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onBtnMove, this, "spellcheck_active_list", "spellcheck_available_list")); @@ -121,6 +135,15 @@ void LLFloaterSpellCheckerSettings::onOpen(const LLSD& key)  	refreshDictionaries(true);  } +void LLFloaterSpellCheckerSettings::onBtnRemove() +{ +	std::vector<LLScrollListItem*> sel_items = getChild<LLScrollListCtrl>("spellcheck_available_list")->getAllSelected(); +	for (std::vector<LLScrollListItem*>::const_iterator sel_it = sel_items.begin(); sel_it != sel_items.end(); ++sel_it) +	{ +		LLSpellChecker::instance().removeDictionary((*sel_it)->getValue().asString()); +	} +} +  void LLFloaterSpellCheckerSettings::onSpellCheckSettingsChange()  {  	refreshDictionaries(true); @@ -137,7 +160,7 @@ void LLFloaterSpellCheckerSettings::refreshDictionaries(bool from_settings)  	std::string dict_cur = dict_combo->getSelectedItemLabel();  	if ((dict_cur.empty() || from_settings) && (LLSpellChecker::getUseSpellCheck()))  	{ -		dict_cur = LLSpellChecker::instance().getActiveDictionary(); +		dict_cur = LLSpellChecker::instance().getPrimaryDictionary();  	}  	dict_combo->clearRows();  	dict_combo->setEnabled(enabled); diff --git a/indra/newview/llfloaterspellchecksettings.h b/indra/newview/llfloaterspellchecksettings.h index da3239bca3..67bd260048 100644 --- a/indra/newview/llfloaterspellchecksettings.h +++ b/indra/newview/llfloaterspellchecksettings.h @@ -34,6 +34,7 @@ class LLFloaterSpellCheckerSettings : public LLFloater  public:  	LLFloaterSpellCheckerSettings(const LLSD& key); +	/*virtual*/ void draw();  	/*virtual*/ BOOL postBuild();  	/*virtual*/ void onOpen(const LLSD& key); @@ -42,6 +43,7 @@ protected:  	void onBtnImport();  	void onBtnMove(const std::string& from, const std::string& to);  	void onBtnOK(); +	void onBtnRemove();  	void onSpellCheckSettingsChange();  	void refreshDictionaries(bool from_settings);  }; diff --git a/indra/newview/skins/default/xui/en/floater_spellcheck.xml b/indra/newview/skins/default/xui/en/floater_spellcheck.xml index 91639ed0da..786b830ad9 100644 --- a/indra/newview/skins/default/xui/en/floater_spellcheck.xml +++ b/indra/newview/skins/default/xui/en/floater_spellcheck.xml @@ -3,10 +3,10 @@   border="true"   can_close="true"   can_minimize="true" - bottom="275" + bottom="300"   left="300"   can_resize="false" - height="330" + height="355"   width="490"   name="spellcheck_floater"   title="Spell Checker Settings"> @@ -53,16 +53,6 @@     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" @@ -148,6 +138,25 @@     top_pad="-105"     width="175"    /> +  <button +   enabled="false" +   follows="left|top" +   height="23" +   label="Remove" +   layout="topleft" +   left="55" +   name="spellcheck_remove_btn" +   top_pad="5" +   width="80" /> +  <button +   follows="left|top" +   height="23" +   label="Import..." +   layout="topleft" +   left_pad="15" +   name="spellcheck_import_btn" +   top_delta="0" +   width="80" />    <view_border     top_pad="10"     left="2" @@ -159,7 +168,7 @@     mouse_opaque="false"     name="divisor4"/>    <button -   top_pad="10" +   top_pad="8"     right="380"     height="22"     width="90"  | 
