Fixed spell checker with the new incremental transmit editor

This commit is contained in:
Jordan Sherer 2019-09-25 20:26:41 -04:00
parent bb91fac20d
commit 8d4db7d376
4 changed files with 264 additions and 107 deletions

View File

@ -2,39 +2,154 @@
#include <QDebug> #include <QDebug>
void setTextEditFont(QTextEdit *edit, QFont font){
// all uppercase
font.setCapitalization(QFont::AllUppercase);
edit->setFont(font);
edit->setFontFamily(font.family());
edit->setFontItalic(font.italic());
edit->setFontPointSize(font.pointSize());
edit->setFontUnderline(font.underline());
edit->setFontWeight(font.weight());
auto d = edit->document();
d->setDefaultFont(font);
edit->setDocument(d);
auto c = edit->textCursor();
c.select(QTextCursor::Document);
auto cf = c.blockCharFormat();
cf.setFont(font);
cf.setFontCapitalization(QFont::AllUppercase);
c.mergeBlockCharFormat(cf);
edit->updateGeometry();
}
void setTextEditStyle(QTextEdit *edit, QColor fg, QColor bg, QFont font){
edit->setStyleSheet(QString("QTextEdit { color:%1; background: %2; %3; }").arg(fg.name()).arg(bg.name()).arg(font_as_stylesheet(font)));
//QTimer::singleShot(10, nullptr, [edit, fg, bg](){
QPalette p = edit->palette();
p.setColor(QPalette::Base, bg);
p.setColor(QPalette::Active, QPalette::Base, bg);
p.setColor(QPalette::Disabled, QPalette::Base, bg);
p.setColor(QPalette::Inactive, QPalette::Base, bg);
p.setColor(QPalette::Text, fg);
p.setColor(QPalette::Active, QPalette::Text, fg);
p.setColor(QPalette::Disabled, QPalette::Text, fg);
p.setColor(QPalette::Inactive, QPalette::Text, fg);
edit->setBackgroundRole(QPalette::Base);
edit->setForegroundRole(QPalette::Text);
edit->setPalette(p);
edit->updateGeometry();
edit->update();
//});
}
void highlightBlock(QTextBlock block, QFont font, QColor foreground, QColor background){
QTextCursor cursor(block);
// Set background color
QTextBlockFormat blockFormat = cursor.blockFormat();
blockFormat.setBackground(background);
cursor.setBlockFormat(blockFormat);
// Set font
/*
for (QTextBlock::iterator it = cursor.block().begin(); !(it.atEnd()); ++it) {
QTextCharFormat charFormat = it.fragment().charFormat();
charFormat.setFont(font);
charFormat.setFontCapitalization(QFont::AllUppercase);
charFormat.setForeground(QBrush(foreground));
QTextCursor tempCursor = cursor;
tempCursor.setPosition(it.fragment().position());
tempCursor.setPosition(it.fragment().position() + it.fragment().length(), QTextCursor::KeepAnchor);
tempCursor.setCharFormat(charFormat);
}
*/
cursor.select(QTextCursor::BlockUnderCursor);
auto charFormat = cursor.charFormat();
charFormat.setFont(font);
charFormat.setFontCapitalization(QFont::AllUppercase);
charFormat.setForeground(QBrush(foreground));
cursor.setCharFormat(charFormat);
}
TransmitTextEdit::TransmitTextEdit(QWidget *parent): TransmitTextEdit::TransmitTextEdit(QWidget *parent):
QTextEdit(parent) QTextEdit(parent),
m_sent { 0 },
m_textSent { "" },
m_protected { false }
{ {
connect(this, &QTextEdit::selectionChanged, this, &TransmitTextEdit::on_selectionChanged); connect(this, &QTextEdit::selectionChanged, this, &TransmitTextEdit::on_selectionChanged);
connect(this, &QTextEdit::cursorPositionChanged, this, &TransmitTextEdit::on_selectionChanged); connect(this, &QTextEdit::cursorPositionChanged, this, &TransmitTextEdit::on_selectionChanged);
connect(this->document(), &QTextDocument::contentsChange, this, &TransmitTextEdit::on_textContentsChanged);
} }
void TransmitTextEdit::markCharsSent(int n){ void TransmitTextEdit::setCharsSent(int n){
// update sent display // update sent display
auto c = textCursor(); auto c = textCursor();
c.movePosition(QTextCursor::Start); c.movePosition(QTextCursor::Start);
c.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, n); c.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, n);
auto ch = c.charFormat(); // keep track of sent text
ch.setFontStrikeOut(true); m_textSent = c.selectedText().toUpper();
c.mergeCharFormat(ch);
// keep track
m_sent = n; m_sent = n;
// highlight the sent text
//highlightCharsSent();
highlight();
}
// override
QString TransmitTextEdit::toPlainText() const {
return QTextEdit::toPlainText().toUpper();
} }
// override // override
void TransmitTextEdit::setPlainText(const QString &text){ void TransmitTextEdit::setPlainText(const QString &text){
QTextEdit::setPlainText(text); QTextEdit::setPlainText(text);
m_textSent.clear();
m_sent = 0; m_sent = 0;
} }
//
void TransmitTextEdit::setFont(QFont f){
m_font = f;
// then rehighlight
highlight();
}
//
void TransmitTextEdit::setFont(QFont f, QColor fg, QColor bg){
m_font = f;
m_fg = fg;
m_bg = bg;
// then rehighlight
highlight();
}
// override // override
void TransmitTextEdit::clear(){ void TransmitTextEdit::clear(){
QTextEdit::clear(); QTextEdit::clear();
m_textSent.clear();
m_sent = 0; m_sent = 0;
} }
void TransmitTextEdit::setProtected(bool protect){
m_protected = protect;
}
// slot // slot
void TransmitTextEdit::on_selectionChanged(){ void TransmitTextEdit::on_selectionChanged(){
auto c = textCursor(); auto c = textCursor();
@ -45,9 +160,69 @@ void TransmitTextEdit::on_selectionChanged(){
end = start; end = start;
start = x; start = x;
} }
qDebug() << "selection" << start << end;
if(start <= m_sent){ qDebug() << "selection" << start << end << m_sent;
if(m_sent && start <= m_sent){
qDebug() << "selection in protected zone" << start << "<=" << m_sent; qDebug() << "selection in protected zone" << start << "<=" << m_sent;
setProtected(true);
} else {
setProtected(false);
} }
} }
// slot
void TransmitTextEdit::on_textContentsChanged(int pos, int rem, int add){
if(rem == 0 && add == 0){
return;
}
auto text = toPlainText();
if(text != m_lastText){
qDebug() << "text changed" << pos << rem << add << "from" << m_lastText << "to" << text;
highlight();
m_lastText = text;
}
}
void TransmitTextEdit::highlightBase(){
auto d = document();
if(!d){
return;
}
auto block = d->firstBlock();
while(block.isValid()){
highlightBlock(block, m_font, m_fg, m_bg);
block = block.next();
}
}
void TransmitTextEdit::highlightCharsSent(){
if(!m_sent){
return;
}
auto d = document();
if(!d){
return;
}
// highlight sent text
auto c = textCursor();
if(c.isNull()){
return;
}
c.movePosition(QTextCursor::Start);
c.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, m_sent);
auto ch = c.charFormat();
ch.setFontStrikeOut(true);
c.mergeCharFormat(ch);
}
void TransmitTextEdit::highlight(){
highlightBase();
highlightCharsSent();
}

View File

@ -1,22 +1,55 @@
#ifndef TRANSMITTEXTEDIT_H #ifndef TRANSMITTEXTEDIT_H
#define TRANSMITTEXTEDIT_H #define TRANSMITTEXTEDIT_H
#include "qt_helpers.hpp"
#include <QTextEdit> #include <QTextEdit>
#include <QTextBlock>
#include <QTextCursor>
#include <QBrush>
#include <QColor>
#include <QFont>
void setTextEditFont(QTextEdit *edit, QFont font);
void setTextEditStyle(QTextEdit *edit, QColor fg, QColor bg, QFont font);
void highlightBlock(QTextBlock block, QFont font, QColor foreground, QColor background);
class TransmitTextEdit : public QTextEdit class TransmitTextEdit : public QTextEdit
{ {
public: public:
TransmitTextEdit(QWidget *parent); TransmitTextEdit(QWidget *parent);
void markCharsSent(int n); int charsSent() const {
return m_sent;
}
void setCharsSent(int n);
QString toPlainText() const;
void setPlainText(const QString &text); void setPlainText(const QString &text);
void setFont(QFont f);
void setFont(QFont f, QColor fg, QColor bg);
void clear(); void clear();
bool isProtected() const {
return m_protected;
}
void setProtected(bool protect);
void highlightBase();
void highlightCharsSent();
void highlight();
public slots: public slots:
void on_selectionChanged(); void on_selectionChanged();
void on_textContentsChanged(int pos, int rem, int add);
private: private:
QString m_lastText;
QString m_textSent;
int m_sent; int m_sent;
bool m_protected;
QFont m_font;
QColor m_fg;
QColor m_bg;
}; };
#endif // TRANSMITTEXTEDIT_H #endif // TRANSMITTEXTEDIT_H

View File

@ -58,7 +58,7 @@ bool cursorHasProperty(const QTextCursor &cursor, int property){
QString nextChar(QTextCursor c){ QString nextChar(QTextCursor c){
QTextCursor cur(c); QTextCursor cur(c);
cur.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor); cur.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
return cur.selectedText(); return cur.selectedText().toUpper();
} }
bool isNumeric(QString s){ bool isNumeric(QString s){
@ -97,7 +97,7 @@ void JSCChecker::checkRange(QTextEdit* edit, int start, int end)
bool correct = false; bool correct = false;
cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
if(cursor.selectedText() == "@"){ if(cursor.selectedText()/*.toUpper()*/ == "@"){
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor); cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
} }
@ -105,7 +105,7 @@ void JSCChecker::checkRange(QTextEdit* edit, int start, int end)
if(cursorHasProperty(cursor, CORRECT)){ if(cursorHasProperty(cursor, CORRECT)){
correct = true; correct = true;
} else { } else {
QString word = cursor.selectedText(); QString word = cursor.selectedText().toUpper();
// three or less is always "correct" // three or less is always "correct"
if(word.length() < 4 || isNumeric(word)){ if(word.length() < 4 || isNumeric(word)){
@ -121,6 +121,8 @@ void JSCChecker::checkRange(QTextEdit* edit, int start, int end)
correct = Varicode::isValidCallsign(word, nullptr); correct = Varicode::isValidCallsign(word, nullptr);
} }
} }
qDebug() << "word" << word << "correct" << correct;
} }
if(correct){ if(correct){

View File

@ -256,88 +256,6 @@ namespace
return roundDown + multiple; return roundDown + multiple;
} }
void setTextEditFont(QTextEdit *edit, QFont font){
edit->setFont(font);
edit->setFontFamily(font.family());
edit->setFontItalic(font.italic());
edit->setFontPointSize(font.pointSize());
edit->setFontUnderline(font.underline());
edit->setFontWeight(font.weight());
auto d = edit->document();
d->setDefaultFont(font);
edit->setDocument(d);
auto c = edit->textCursor();
c.select(QTextCursor::Document);
auto cf = c.blockCharFormat();
cf.setFont(font);
c.mergeBlockCharFormat(cf);
edit->updateGeometry();
}
void setTextEditStyle(QTextEdit *edit, QColor fg, QColor bg, QFont font){
edit->setStyleSheet(QString("QTextEdit { color:%1; background: %2; %3; }").arg(fg.name()).arg(bg.name()).arg(font_as_stylesheet(font)));
QTimer::singleShot(10, nullptr, [edit, fg, bg](){
QPalette p = edit->palette();
p.setColor(QPalette::Base, bg);
p.setColor(QPalette::Active, QPalette::Base, bg);
p.setColor(QPalette::Disabled, QPalette::Base, bg);
p.setColor(QPalette::Inactive, QPalette::Base, bg);
p.setColor(QPalette::Text, fg);
p.setColor(QPalette::Active, QPalette::Text, fg);
p.setColor(QPalette::Disabled, QPalette::Text, fg);
p.setColor(QPalette::Inactive, QPalette::Text, fg);
edit->setBackgroundRole(QPalette::Base);
edit->setForegroundRole(QPalette::Text);
edit->setPalette(p);
edit->updateGeometry();
edit->update();
});
}
/*
void setTextEditForeground(QTextEdit *edit, QColor color){
QTimer::singleShot(20, nullptr, [edit, color](){
QPalette p = edit->palette();
p.setColor(QPalette::Text, color);
p.setColor(QPalette::Active, QPalette::Text, color);
p.setColor(QPalette::Disabled, QPalette::Text, color);
p.setColor(QPalette::Inactive, QPalette::Text, color);
edit->setPalette(p);
edit->updateGeometry();
edit->update();
});
}
*/
void highlightBlock(QTextBlock block, QFont font, QColor foreground, QColor background){
QTextCursor cursor(block);
// Set background color
QTextBlockFormat blockFormat = cursor.blockFormat();
blockFormat.setBackground(background);
cursor.setBlockFormat(blockFormat);
// Set font
for (QTextBlock::iterator it = cursor.block().begin(); !(it.atEnd()); ++it) {
QTextCharFormat charFormat = it.fragment().charFormat();
charFormat.setFont(font);
charFormat.setForeground(QBrush(foreground));
QTextCursor tempCursor = cursor;
tempCursor.setPosition(it.fragment().position());
tempCursor.setPosition(it.fragment().position() + it.fragment().length(), QTextCursor::KeepAnchor);
tempCursor.setCharFormat(charFormat);
}
}
template<typename T> template<typename T>
QList<T> listCopyReverse(QList<T> const &list){ QList<T> listCopyReverse(QList<T> const &list){
QList<T> newList = QList<T>(); QList<T> newList = QList<T>();
@ -710,6 +628,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
connect (&m_config, &Configuration::colors_changed, [this](){ connect (&m_config, &Configuration::colors_changed, [this](){
setTextEditStyle(ui->textEditRX, m_config.color_rx_foreground(), m_config.color_rx_background(), m_config.rx_text_font()); setTextEditStyle(ui->textEditRX, m_config.color_rx_foreground(), m_config.color_rx_background(), m_config.rx_text_font());
setTextEditStyle(ui->extFreeTextMsgEdit, m_config.color_compose_foreground(), m_config.color_compose_background(), m_config.compose_text_font()); setTextEditStyle(ui->extFreeTextMsgEdit, m_config.color_compose_foreground(), m_config.color_compose_background(), m_config.compose_text_font());
ui->extFreeTextMsgEdit->setFont(m_config.compose_text_font(), m_config.color_compose_foreground(), m_config.color_compose_background());
// rehighlight // rehighlight
auto d = ui->textEditRX->document(); auto d = ui->textEditRX->document();
@ -1919,7 +1838,7 @@ void MainWindow::initializeDummyData(){
#endif #endif
ui->extFreeTextMsgEdit->setPlainText("HELLO BRAVE NEW WORLD"); ui->extFreeTextMsgEdit->setPlainText("HELLO BRAVE NEW WORLD");
ui->extFreeTextMsgEdit->markCharsSent(6); ui->extFreeTextMsgEdit->setCharsSent(6);
logHeardGraph("KN4CRD", "OH8STN"); logHeardGraph("KN4CRD", "OH8STN");
logHeardGraph("KN4CRD", "K0OG"); logHeardGraph("KN4CRD", "K0OG");
@ -2465,6 +2384,8 @@ void MainWindow::readSettings()
setTextEditStyle(ui->textEditRX, m_config.color_rx_foreground(), m_config.color_rx_background(), m_config.rx_text_font()); setTextEditStyle(ui->textEditRX, m_config.color_rx_foreground(), m_config.color_rx_background(), m_config.rx_text_font());
setTextEditStyle(ui->extFreeTextMsgEdit, m_config.color_compose_foreground(), m_config.color_compose_background(), m_config.compose_text_font()); setTextEditStyle(ui->extFreeTextMsgEdit, m_config.color_compose_foreground(), m_config.color_compose_background(), m_config.compose_text_font());
ui->extFreeTextMsgEdit->setFont(m_config.compose_text_font(), m_config.color_compose_foreground(), m_config.color_compose_background());
{ {
auto const& coeffs = m_settings->value ("PhaseEqualizationCoefficients" auto const& coeffs = m_settings->value ("PhaseEqualizationCoefficients"
@ -5408,7 +5329,7 @@ void MainWindow::stopTx()
// start message marker // start message marker
// - keep track of the total message sent so far, and mark it having been sent // - keep track of the total message sent so far, and mark it having been sent
m_totalTxMessage.append(dt.message()); m_totalTxMessage.append(dt.message());
ui->extFreeTextMsgEdit->markCharsSent(m_totalTxMessage.length()); ui->extFreeTextMsgEdit->setCharsSent(m_totalTxMessage.length());
qDebug() << "total sent:\n" << m_totalTxMessage; qDebug() << "total sent:\n" << m_totalTxMessage;
// end message marker // end message marker
@ -5427,6 +5348,7 @@ void MainWindow::stopTx()
#endif #endif
if(!shouldContinue){ if(!shouldContinue){
// TODO: jsherer - split this up... // TODO: jsherer - split this up...
ui->extFreeTextMsgEdit->clear();
ui->extFreeTextMsgEdit->setReadOnly(false); ui->extFreeTextMsgEdit->setReadOnly(false);
update_dynamic_property(ui->extFreeTextMsgEdit, "transmitting", false); update_dynamic_property(ui->extFreeTextMsgEdit, "transmitting", false);
on_stopTxButton_clicked(); on_stopTxButton_clicked();
@ -6319,6 +6241,7 @@ void MainWindow::on_nextFreeTextMsg_currentTextChanged (QString const& text)
void MainWindow::on_extFreeTextMsgEdit_currentTextChanged (QString const& text) void MainWindow::on_extFreeTextMsgEdit_currentTextChanged (QString const& text)
{ {
#if 0
QString x; QString x;
QString::const_iterator i; QString::const_iterator i;
for(i = text.constBegin(); i != text.constEnd(); i++){ for(i = text.constBegin(); i != text.constEnd(); i++){
@ -6332,13 +6255,11 @@ void MainWindow::on_extFreeTextMsgEdit_currentTextChanged (QString const& text)
int pos = ui->extFreeTextMsgEdit->textCursor().position(); int pos = ui->extFreeTextMsgEdit->textCursor().position();
int maxpos = x.size(); int maxpos = x.size();
// don't emit current text changed or text contents changed int sent = ui->extFreeTextMsgEdit->charsSent();
ui->extFreeTextMsgEdit->blockSignals(true); ui->extFreeTextMsgEdit->setPlainText(x);
{ ui->extFreeTextMsgEdit->setCharsSent(sent);
ui->extFreeTextMsgEdit->setPlainText(x);
}
ui->extFreeTextMsgEdit->blockSignals(false);
// set cursor position
QTextCursor c = ui->extFreeTextMsgEdit->textCursor(); QTextCursor c = ui->extFreeTextMsgEdit->textCursor();
c.setPosition(pos < maxpos ? pos : maxpos, QTextCursor::MoveAnchor); c.setPosition(pos < maxpos ? pos : maxpos, QTextCursor::MoveAnchor);
@ -6347,9 +6268,35 @@ void MainWindow::on_extFreeTextMsgEdit_currentTextChanged (QString const& text)
ui->extFreeTextMsgEdit->setTextCursor(c); ui->extFreeTextMsgEdit->setTextCursor(c);
} }
#endif
m_txTextDirty = x != m_txTextDirtyLastText; #if 0
m_txTextDirtyLastText = x; auto x = text;
// only highlight if dirty
if(x != m_txTextDirtyLastText){
// highlight the edited block with our fonts
QTextCursor c = ui->extFreeTextMsgEdit->textCursor();
ui->extFreeTextMsgEdit->blockSignals(true);
{
int pos = ui->extFreeTextMsgEdit->textCursor().position();
int maxpos = x.size();
// set cursor position
QTextCursor c = ui->extFreeTextMsgEdit->textCursor();
c.setPosition(pos < maxpos ? pos : maxpos, QTextCursor::MoveAnchor);
// highlight the block with our fonts
highlightBlock(c.block(), m_config.compose_text_font(), m_config.color_compose_foreground(), QColor(Qt::transparent));
ui->extFreeTextMsgEdit->setTextCursor(c);
}
ui->extFreeTextMsgEdit->blockSignals(false);
}
#endif
m_txTextDirty = text != m_txTextDirtyLastText;
m_txTextDirtyLastText = text;
// immediately update the display // immediately update the display
updateButtonDisplay(); updateButtonDisplay();
@ -8390,7 +8337,7 @@ void MainWindow::buildSuggestionsMenu(QMenu *menu, QTextEdit *edit, const QPoint
c.movePosition(QTextCursor::StartOfWord); c.movePosition(QTextCursor::StartOfWord);
c.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); c.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
auto word = c.selectedText().trimmed(); auto word = c.selectedText().toUpper().trimmed();
if(word.isEmpty()){ if(word.isEmpty()){
return; return;
} }
@ -10468,7 +10415,7 @@ void MainWindow::processCommandActivity() {
c = ui->textEditRX->textCursor(); c = ui->textEditRX->textCursor();
c.movePosition(QTextCursor::StartOfBlock); c.movePosition(QTextCursor::StartOfBlock);
c.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); c.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
qDebug() << "should display directed message, erasing last rx activity line..." << c.selectedText(); qDebug() << "should display directed message, erasing last rx activity line..." << c.selectedText().toUpper();
c.removeSelectedText(); c.removeSelectedText();
c.deletePreviousChar(); c.deletePreviousChar();
c.deletePreviousChar(); c.deletePreviousChar();