diff --git a/jsc_checker.cpp b/jsc_checker.cpp index 727d82b..b72936f 100644 --- a/jsc_checker.cpp +++ b/jsc_checker.cpp @@ -145,6 +145,61 @@ void JSCChecker::checkRange(QTextEdit* edit, int start, int end) edit->document()->blockSignals(false); } +QSet oneEdit(QString word, bool includeAdditions, bool includeDeletions){ + QSet all; + + // 1-edit distance words (i.e., prefixed/suffixed/edited characters) + for(int i = 0; i < 26; i++){ + if(includeAdditions){ + auto prefixed = ALPHABET.mid(i, 1) + word; + all.insert(prefixed); + + auto suffixed = word + ALPHABET.mid(i, 1); + all.insert(suffixed); + } + + for(int j = 0; j < word.length(); j++){ + auto edited = word.mid(0, j) + ALPHABET.mid(i, 1) + word.mid(j + 1, word.length() - j); + all.insert(edited); + } + } + + // 1-edit distance words (i.e., removed characters) + if(includeDeletions){ + for(int j = 0; j < word.length(); j++){ + auto deleted = word.mid(0, j) + word.mid(j + 1, word.length() - j); + all.insert(deleted); + } + } + + return all; +} + +QMap candidates(QString word, bool includeTwoEdits){ + // one edit + QSet one = oneEdit(word, true, true); + + // two edits + QSet two; + if(includeTwoEdits){ + foreach(auto w, one){ + two |= oneEdit(w, false, false); + } + } + + // existence check + QMap m; + + quint32 index; + foreach(auto w, one | two){ + if(JSC::exists(w, &index)){ + m[index] = w; + } + } + + return m; +} + QStringList JSCChecker::suggestions(QString word, int n, bool *pFound){ QStringList s; @@ -163,38 +218,16 @@ QStringList JSCChecker::suggestions(QString word, int n, bool *pFound){ } } - // 1-edit distance words (i.e., prefixed/suffixed/edited/removed characters) - for(int i = 0; i < 26; i++){ - auto prefixed = ALPHABET.mid(i, 1) + word; - if(JSC::exists(prefixed, &index)){ - m[index] = prefixed; - } - - auto suffixed = word + ALPHABET.mid(i, 1); - if(JSC::exists(suffixed, &index)){ - m[index] = suffixed; - } - - for(int j = 0; j < word.length(); j++){ - auto edited = word.mid(0, j) + ALPHABET.mid(i, 1) + word.mid(j + 1, word.length() - j); - if(JSC::exists(edited, &index)){ - m[index] = edited; - } - } - } - for(int j = 0; j < word.length(); j++){ - auto deleted = word.mid(0, j) + word.mid(j + 1, word.length() - j); - if(JSC::exists(deleted, &index)){ - m[index] = deleted; - } - } + // compute suggestion candidates + m.unite(candidates(word, false)); // return in order of probability (i.e., index rank) int i = 0; - foreach(auto key, m.keys()){ + foreach(auto key, m.uniqueKeys()){ if(i >= n){ break; } + qDebug() << "suggest" << m[key] << key; s.append(m[key]); i++; } diff --git a/mainwindow.cpp b/mainwindow.cpp index e19f40c..5a20cdd 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -1177,15 +1177,13 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, connect(ui->extFreeTextMsgEdit, &QTableWidget::customContextMenuRequested, this, [this, clearAction2, clearActionAll, restoreAction](QPoint const &point){ QMenu * menu = new QMenu(ui->extFreeTextMsgEdit); - // spelling suggestions... - buildSuggestionsMenu(menu, ui->extFreeTextMsgEdit, point); - auto selectedCall = callsignSelected(); bool missingCallsign = selectedCall.isEmpty(); + buildSuggestionsMenu(menu, ui->extFreeTextMsgEdit, point); + restoreAction->setDisabled(m_lastTxMessage.isEmpty()); menu->addAction(restoreAction); - menu->addSeparator(); auto savedMenu = menu->addMenu("Saved messages..."); buildSavedMessagesMenu(savedMenu); @@ -7455,18 +7453,17 @@ void MainWindow::buildSuggestionsMenu(QMenu *menu, QTextEdit *edit, const QPoint return; } - QStringList suggestions = JSCChecker::suggestions(word, 10, &found); + QStringList suggestions = JSCChecker::suggestions(word, 5, &found); if(suggestions.isEmpty() && !found){ return; } - auto suggestionsMenu = menu->addMenu("Suggestions..."); if(suggestions.isEmpty()){ - auto a = suggestionsMenu->addAction("No suggestions"); + auto a = menu->addAction("No Suggestions"); a->setDisabled(true); } else { foreach(auto suggestion, suggestions){ - auto a = suggestionsMenu->addAction(suggestion); + auto a = menu->addAction(suggestion); connect(a, &QAction::triggered, this, [this, edit, point, suggestion](){ auto c = edit->cursorForPosition(point);