mirror of https://github.com/odrling/Aegisub
Only enable the Remove Word button when the word can be removed. Updates #1184.
This commit is contained in:
parent
fe630e052b
commit
835f7c0f78
|
@ -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
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,24 +235,16 @@ 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"));
|
||||||
|
|
||||||
try {
|
ReadUserDictionary();
|
||||||
agi::scoped_ptr<std::istream> stream(agi::io::Open(STD_STR(userDicPath)));
|
|
||||||
agi::line_iterator<std::string> userDic(*stream);
|
for (auto const& word : customWords) {
|
||||||
agi::line_iterator<std::string> end;
|
try {
|
||||||
++userDic; // skip entry count line
|
hunspell->add(conv->Convert(word).c_str());
|
||||||
for (; userDic != end; ++userDic) {
|
}
|
||||||
if (userDic->empty()) continue;
|
catch (agi::charset::ConvError const&) {
|
||||||
try {
|
// Normally this shouldn't happen, but some versions of Aegisub
|
||||||
hunspell->add(conv->Convert(*userDic).c_str());
|
// wrote words in the wrong charset
|
||||||
}
|
|
||||||
catch (agi::charset::ConvError const&) {
|
|
||||||
// Normally this shouldn't happen, but some versions of Aegisub
|
|
||||||
// wrote words in the wrong charset
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch (agi::Exception const&) {
|
|
||||||
// File doesn't exist or we don't have permission to read it
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in New Issue