Only enable the Remove Word button when the word can be removed. Updates #1184.

This commit is contained in:
Thomas Goyne 2012-12-21 15:59:25 -08:00
parent fe630e052b
commit 835f7c0f78
5 changed files with 63 additions and 88 deletions

View file

@ -37,6 +37,11 @@ public:
/// @return Whether or not word can be added /// @return Whether or not word can be added
virtual bool CanAddWord(std::string const& word)=0; virtual bool CanAddWord(std::string const& word)=0;
/// Can the word be removed from the current dictionary?
/// @param word Word to check
/// @return Whether or not word can be removed
virtual bool CanRemoveWord(std::string const& word)=0;
/// Check if the given word is spelled correctly /// Check if the given word is spelled correctly
/// @param word Word to check /// @param word Word to check
/// @return Whether or not the word is valid /// @return Whether or not the word is valid

View file

@ -80,6 +80,10 @@ DialogSpellChecker::DialogSpellChecker(agi::Context *context)
current_word_sizer->Add(new wxStaticText(this, -1, _("Replace with:")), 0, wxALIGN_CENTER_VERTICAL); current_word_sizer->Add(new wxStaticText(this, -1, _("Replace with:")), 0, wxALIGN_CENTER_VERTICAL);
current_word_sizer->Add(replace_word = new wxTextCtrl(this, -1, ""), wxSizerFlags(1).Expand()); current_word_sizer->Add(replace_word = new wxTextCtrl(this, -1, ""), wxSizerFlags(1).Expand());
replace_word->Bind(wxEVT_COMMAND_TEXT_UPDATED, [=](wxCommandEvent&) {
remove_button->Enable(spellchecker->CanRemoveWord(from_wx(replace_word->GetValue())));
});
// List of suggested corrections // List of suggested corrections
suggest_list = new wxListBox(this, -1, wxDefaultPosition, wxSize(300, 150)); suggest_list = new wxListBox(this, -1, wxDefaultPosition, wxSize(300, 150));
suggest_list->Bind(wxEVT_COMMAND_LISTBOX_SELECTED, &DialogSpellChecker::OnChangeSuggestion, this); suggest_list->Bind(wxEVT_COMMAND_LISTBOX_SELECTED, &DialogSpellChecker::OnChangeSuggestion, this);
@ -132,19 +136,32 @@ DialogSpellChecker::DialogSpellChecker(agi::Context *context)
button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &DialogSpellChecker::OnReplace, this); button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &DialogSpellChecker::OnReplace, this);
actions_sizer->Add(button = new wxButton(this, -1, _("Replace &all")), button_flags); actions_sizer->Add(button = new wxButton(this, -1, _("Replace &all")), button_flags);
button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &DialogSpellChecker::OnReplaceAll, this); button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [=](wxCommandEvent&) {
auto_replace[from_wx(orig_word->GetValue())] = from_wx(replace_word->GetValue());
Replace();
FindNext();
});
actions_sizer->Add(button = new wxButton(this, -1, _("&Ignore")), button_flags); actions_sizer->Add(button = new wxButton(this, -1, _("&Ignore")), button_flags);
button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [=](wxCommandEvent&) { FindNext(); }); button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [=](wxCommandEvent&) { FindNext(); });
actions_sizer->Add(button = new wxButton(this, -1, _("Ignore a&ll")), button_flags); actions_sizer->Add(button = new wxButton(this, -1, _("Ignore a&ll")), button_flags);
button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &DialogSpellChecker::OnIgnoreAll, this); button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [=](wxCommandEvent&) {
auto_ignore.insert(from_wx(orig_word->GetValue()));
FindNext();
});
actions_sizer->Add(add_button = new wxButton(this, -1, _("Add to &dictionary")), button_flags); actions_sizer->Add(add_button = new wxButton(this, -1, _("Add to &dictionary")), button_flags);
add_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &DialogSpellChecker::OnAdd, this); add_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [=](wxCommandEvent&) {
spellchecker->AddWord(from_wx(orig_word->GetValue()));
FindNext();
});
actions_sizer->Add(remove_button = new wxButton(this, -1, _("Remove fro&m dictionary")), button_flags); actions_sizer->Add(remove_button = new wxButton(this, -1, _("Remove fro&m dictionary")), button_flags);
remove_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &DialogSpellChecker::OnRemove, this); remove_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [=](wxCommandEvent&) {
spellchecker->RemoveWord(from_wx(replace_word->GetValue()));
SetWord(from_wx(orig_word->GetValue()));
});
actions_sizer->Add(new HelpButton(this, "Spell Checker"), button_flags); actions_sizer->Add(new HelpButton(this, "Spell Checker"), button_flags);
@ -166,30 +183,6 @@ void DialogSpellChecker::OnReplace(wxCommandEvent&) {
FindNext(); FindNext();
} }
void DialogSpellChecker::OnReplaceAll(wxCommandEvent&) {
auto_replace[from_wx(orig_word->GetValue())] = from_wx(replace_word->GetValue());
Replace();
FindNext();
}
void DialogSpellChecker::OnIgnoreAll(wxCommandEvent&) {
auto_ignore.insert(from_wx(orig_word->GetValue()));
FindNext();
}
void DialogSpellChecker::OnAdd(wxCommandEvent&) {
spellchecker->AddWord(from_wx(orig_word->GetValue()));
FindNext();
}
void DialogSpellChecker::OnRemove(wxCommandEvent&) {
// TODO pop-up dialog
spellchecker->RemoveWord(from_wx(replace_word->GetValue()));
FindNext();
}
void DialogSpellChecker::OnChangeLanguage(wxCommandEvent&) { void DialogSpellChecker::OnChangeLanguage(wxCommandEvent&) {
wxString code = dictionary_lang_codes[language->GetSelection()]; wxString code = dictionary_lang_codes[language->GetSelection()];
OPT_SET("Tool/Spell Checker/Language")->SetString(STD_STR(code)); OPT_SET("Tool/Spell Checker/Language")->SetString(STD_STR(code));

View file

@ -85,10 +85,6 @@ class DialogSpellChecker : public wxDialog {
void OnChangeSuggestion(wxCommandEvent&); void OnChangeSuggestion(wxCommandEvent&);
void OnReplace(wxCommandEvent&); void OnReplace(wxCommandEvent&);
void OnReplaceAll(wxCommandEvent&);
void OnIgnoreAll(wxCommandEvent&);
void OnAdd(wxCommandEvent&);
void OnRemove(wxCommandEvent&);
public: public:
DialogSpellChecker(agi::Context *context); DialogSpellChecker(agi::Context *context);

View file

@ -63,25 +63,19 @@ bool HunspellSpellChecker::CanAddWord(std::string const& word) {
} }
} }
bool HunspellSpellChecker::CanRemoveWord(std::string const& word) {
return !!customWords.count(word);
}
void HunspellSpellChecker::AddWord(std::string const& word) { void HunspellSpellChecker::AddWord(std::string const& word) {
if (!hunspell) return; if (!hunspell) return;
// Add it to the in-memory dictionary // Add it to the in-memory dictionary
hunspell->add(conv->Convert(word).c_str()); hunspell->add(conv->Convert(word).c_str());
std::set<std::string> words;
try {
ReadUserDictionary(words);
}
catch (agi::FileNotFoundError&) {
LOG_I("dictionary/hunspell/add") << "User dictionary not found; creating it";
}
// Add the word // Add the word
words.insert(word); if (customWords.insert(word).second)
WriteUserDictionary();
WriteUserDictionary(words);
} }
void HunspellSpellChecker::RemoveWord(std::string const& word) { void HunspellSpellChecker::RemoveWord(std::string const& word) {
@ -90,26 +84,17 @@ void HunspellSpellChecker::RemoveWord(std::string const& word) {
// Remove it from the in-memory dictionary // Remove it from the in-memory dictionary
hunspell->remove(conv->Convert(word).c_str()); hunspell->remove(conv->Convert(word).c_str());
std::set<std::string> words; auto word_iter = customWords.find(word);
if (word_iter != customWords.end()) {
customWords.erase(word_iter);
try { WriteUserDictionary();
ReadUserDictionary(words);
}
catch (agi::FileNotFoundError&) {
LOG_I("dictionary/hunspell/remove") << "User dictionary not found; nothing to remove";
return;
}
auto word_iter = words.find(word);
if (word_iter != words.end()) {
words.erase(word_iter);
WriteUserDictionary(words);
} }
} }
void HunspellSpellChecker::ReadUserDictionary(std::set<std::string> &words) void HunspellSpellChecker::ReadUserDictionary() {
{ customWords.clear();
// Ensure that the path exists // Ensure that the path exists
wxFileName fn(userDicPath); wxFileName fn(userDicPath);
if (!fn.DirExists()) { if (!fn.DirExists()) {
@ -118,21 +103,19 @@ void HunspellSpellChecker::ReadUserDictionary(std::set<std::string> &words)
// Read the old contents of the user's dictionary // Read the old contents of the user's dictionary
else { else {
agi::scoped_ptr<std::istream> stream(agi::io::Open(STD_STR(userDicPath))); agi::scoped_ptr<std::istream> stream(agi::io::Open(STD_STR(userDicPath)));
remove_copy_if( copy_if(
++agi::line_iterator<std::string>(*stream), ++agi::line_iterator<std::string>(*stream), agi::line_iterator<std::string>(),
agi::line_iterator<std::string>(), inserter(customWords, customWords.end()),
inserter(words, words.end()), [](std::string const& str) { return !str.empty(); });
[](std::string const& str) { return str.empty(); });
} }
} }
void HunspellSpellChecker::WriteUserDictionary(std::set<std::string> const& words) void HunspellSpellChecker::WriteUserDictionary() {
{
// Write the new dictionary // Write the new dictionary
{ {
agi::io::Save writer(STD_STR(userDicPath)); agi::io::Save writer(STD_STR(userDicPath));
writer.Get() << words.size() << "\n"; writer.Get() << customWords.size() << "\n";
copy(words.begin(), words.end(), std::ostream_iterator<std::string>(writer.Get(), "\n")); copy(customWords.begin(), customWords.end(), std::ostream_iterator<std::string>(writer.Get(), "\n"));
} }
// Announce a language change so that any other spellcheckers reload the // Announce a language change so that any other spellcheckers reload the
@ -252,15 +235,11 @@ void HunspellSpellChecker::OnLanguageChanged() {
conv.reset(new agi::charset::IconvWrapper("utf-8", hunspell->get_dic_encoding())); conv.reset(new agi::charset::IconvWrapper("utf-8", hunspell->get_dic_encoding()));
rconv.reset(new agi::charset::IconvWrapper(hunspell->get_dic_encoding(), "utf-8")); rconv.reset(new agi::charset::IconvWrapper(hunspell->get_dic_encoding(), "utf-8"));
ReadUserDictionary();
for (auto const& word : customWords) {
try { try {
agi::scoped_ptr<std::istream> stream(agi::io::Open(STD_STR(userDicPath))); hunspell->add(conv->Convert(word).c_str());
agi::line_iterator<std::string> userDic(*stream);
agi::line_iterator<std::string> end;
++userDic; // skip entry count line
for (; userDic != end; ++userDic) {
if (userDic->empty()) continue;
try {
hunspell->add(conv->Convert(*userDic).c_str());
} }
catch (agi::charset::ConvError const&) { catch (agi::charset::ConvError const&) {
// Normally this shouldn't happen, but some versions of Aegisub // Normally this shouldn't happen, but some versions of Aegisub
@ -268,10 +247,6 @@ void HunspellSpellChecker::OnLanguageChanged() {
} }
} }
} }
catch (agi::Exception const&) {
// File doesn't exist or we don't have permission to read it
}
}
void HunspellSpellChecker::OnPathChanged() { void HunspellSpellChecker::OnPathChanged() {
languages.clear(); languages.clear();

View file

@ -26,6 +26,8 @@
#include <libaegisub/scoped_ptr.h> #include <libaegisub/scoped_ptr.h>
#include <libaegisub/signal.h> #include <libaegisub/signal.h>
#include <set>
#include <wx/string.h> #include <wx/string.h>
namespace agi { namespace charset { class IconvWrapper; } } namespace agi { namespace charset { class IconvWrapper; } }
@ -46,6 +48,9 @@ class HunspellSpellChecker : public agi::SpellChecker {
/// Path to user-local dictionary. /// Path to user-local dictionary.
wxString userDicPath; wxString userDicPath;
/// Words in the custom user dictionary
std::set<std::string> customWords;
/// Dictionary language change connection /// Dictionary language change connection
agi::signal::Connection lang_listener; agi::signal::Connection lang_listener;
/// Dictionary language change handler /// Dictionary language change handler
@ -57,9 +62,9 @@ class HunspellSpellChecker : public agi::SpellChecker {
void OnPathChanged(); void OnPathChanged();
/// Load words from custom dictionary /// Load words from custom dictionary
void ReadUserDictionary(std::set<std::string> &words); void ReadUserDictionary();
/// Save words to custom dictionary /// Save words to custom dictionary
void WriteUserDictionary(std::set<std::string> const& words); void WriteUserDictionary();
public: public:
HunspellSpellChecker(); HunspellSpellChecker();
@ -68,6 +73,7 @@ public:
void AddWord(std::string const& word); void AddWord(std::string const& word);
void RemoveWord(std::string const& word); void RemoveWord(std::string const& word);
bool CanAddWord(std::string const& word); bool CanAddWord(std::string const& word);
bool CanRemoveWord(std::string const& word);
bool CheckWord(std::string const& word); bool CheckWord(std::string const& word);
std::vector<std::string> GetSuggestions(std::string const& word); std::vector<std::string> GetSuggestions(std::string const& word);
std::vector<std::string> GetLanguageList(); std::vector<std::string> GetLanguageList();