From 8d4db7d376c849796fed2fcf80931abbe8db91a5 Mon Sep 17 00:00:00 2001 From: Jordan Sherer Date: Wed, 25 Sep 2019 20:26:41 -0400 Subject: [PATCH] Fixed spell checker with the new incremental transmit editor --- TransmitTextEdit.cpp | 193 +++++++++++++++++++++++++++++++++++++++++-- TransmitTextEdit.h | 35 +++++++- jsc_checker.cpp | 8 +- mainwindow.cpp | 135 +++++++++--------------------- 4 files changed, 264 insertions(+), 107 deletions(-) diff --git a/TransmitTextEdit.cpp b/TransmitTextEdit.cpp index dddce0e..9c9ff0b 100644 --- a/TransmitTextEdit.cpp +++ b/TransmitTextEdit.cpp @@ -2,39 +2,154 @@ #include +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): - QTextEdit(parent) + QTextEdit(parent), + m_sent { 0 }, + m_textSent { "" }, + m_protected { false } { connect(this, &QTextEdit::selectionChanged, 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 auto c = textCursor(); c.movePosition(QTextCursor::Start); c.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, n); - auto ch = c.charFormat(); - ch.setFontStrikeOut(true); - c.mergeCharFormat(ch); - - // keep track + // keep track of sent text + m_textSent = c.selectedText().toUpper(); m_sent = n; + + // highlight the sent text + //highlightCharsSent(); + highlight(); +} + +// override +QString TransmitTextEdit::toPlainText() const { + return QTextEdit::toPlainText().toUpper(); } // override void TransmitTextEdit::setPlainText(const QString &text){ QTextEdit::setPlainText(text); + m_textSent.clear(); 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 void TransmitTextEdit::clear(){ QTextEdit::clear(); + m_textSent.clear(); m_sent = 0; } +void TransmitTextEdit::setProtected(bool protect){ + m_protected = protect; +} + // slot void TransmitTextEdit::on_selectionChanged(){ auto c = textCursor(); @@ -45,9 +160,69 @@ void TransmitTextEdit::on_selectionChanged(){ end = start; 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; + 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(); +} + diff --git a/TransmitTextEdit.h b/TransmitTextEdit.h index 0360cd7..0a9958b 100644 --- a/TransmitTextEdit.h +++ b/TransmitTextEdit.h @@ -1,22 +1,55 @@ #ifndef TRANSMITTEXTEDIT_H #define TRANSMITTEXTEDIT_H +#include "qt_helpers.hpp" + #include +#include +#include +#include +#include +#include + +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 { public: 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 setFont(QFont f); + void setFont(QFont f, QColor fg, QColor bg); void clear(); + bool isProtected() const { + return m_protected; + } + void setProtected(bool protect); + void highlightBase(); + void highlightCharsSent(); + void highlight(); + public slots: void on_selectionChanged(); + void on_textContentsChanged(int pos, int rem, int add); private: + QString m_lastText; + QString m_textSent; int m_sent; + bool m_protected; + QFont m_font; + QColor m_fg; + QColor m_bg; }; #endif // TRANSMITTEXTEDIT_H diff --git a/jsc_checker.cpp b/jsc_checker.cpp index b72936f..a491471 100644 --- a/jsc_checker.cpp +++ b/jsc_checker.cpp @@ -58,7 +58,7 @@ bool cursorHasProperty(const QTextCursor &cursor, int property){ QString nextChar(QTextCursor c){ QTextCursor cur(c); cur.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor); - return cur.selectedText(); + return cur.selectedText().toUpper(); } bool isNumeric(QString s){ @@ -97,7 +97,7 @@ void JSCChecker::checkRange(QTextEdit* edit, int start, int end) bool correct = false; cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); - if(cursor.selectedText() == "@"){ + if(cursor.selectedText()/*.toUpper()*/ == "@"){ cursor.movePosition(QTextCursor::NextCharacter, 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)){ correct = true; } else { - QString word = cursor.selectedText(); + QString word = cursor.selectedText().toUpper(); // three or less is always "correct" if(word.length() < 4 || isNumeric(word)){ @@ -121,6 +121,8 @@ void JSCChecker::checkRange(QTextEdit* edit, int start, int end) correct = Varicode::isValidCallsign(word, nullptr); } } + + qDebug() << "word" << word << "correct" << correct; } if(correct){ diff --git a/mainwindow.cpp b/mainwindow.cpp index 6852c27..d640f8e 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -256,88 +256,6 @@ namespace 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 QList listCopyReverse(QList const &list){ QList newList = QList(); @@ -710,6 +628,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, 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->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 auto d = ui->textEditRX->document(); @@ -1919,7 +1838,7 @@ void MainWindow::initializeDummyData(){ #endif ui->extFreeTextMsgEdit->setPlainText("HELLO BRAVE NEW WORLD"); - ui->extFreeTextMsgEdit->markCharsSent(6); + ui->extFreeTextMsgEdit->setCharsSent(6); logHeardGraph("KN4CRD", "OH8STN"); 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->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" @@ -5408,7 +5329,7 @@ void MainWindow::stopTx() // start message marker // - keep track of the total message sent so far, and mark it having been sent m_totalTxMessage.append(dt.message()); - ui->extFreeTextMsgEdit->markCharsSent(m_totalTxMessage.length()); + ui->extFreeTextMsgEdit->setCharsSent(m_totalTxMessage.length()); qDebug() << "total sent:\n" << m_totalTxMessage; // end message marker @@ -5427,6 +5348,7 @@ void MainWindow::stopTx() #endif if(!shouldContinue){ // TODO: jsherer - split this up... + ui->extFreeTextMsgEdit->clear(); ui->extFreeTextMsgEdit->setReadOnly(false); update_dynamic_property(ui->extFreeTextMsgEdit, "transmitting", false); on_stopTxButton_clicked(); @@ -6319,6 +6241,7 @@ void MainWindow::on_nextFreeTextMsg_currentTextChanged (QString const& text) void MainWindow::on_extFreeTextMsgEdit_currentTextChanged (QString const& text) { +#if 0 QString x; QString::const_iterator 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 maxpos = x.size(); - // don't emit current text changed or text contents changed - ui->extFreeTextMsgEdit->blockSignals(true); - { - ui->extFreeTextMsgEdit->setPlainText(x); - } - ui->extFreeTextMsgEdit->blockSignals(false); + int sent = ui->extFreeTextMsgEdit->charsSent(); + ui->extFreeTextMsgEdit->setPlainText(x); + ui->extFreeTextMsgEdit->setCharsSent(sent); + // set cursor position QTextCursor c = ui->extFreeTextMsgEdit->textCursor(); c.setPosition(pos < maxpos ? pos : maxpos, QTextCursor::MoveAnchor); @@ -6347,9 +6268,35 @@ void MainWindow::on_extFreeTextMsgEdit_currentTextChanged (QString const& text) ui->extFreeTextMsgEdit->setTextCursor(c); } +#endif - m_txTextDirty = x != m_txTextDirtyLastText; - m_txTextDirtyLastText = x; +#if 0 + 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 updateButtonDisplay(); @@ -8390,7 +8337,7 @@ void MainWindow::buildSuggestionsMenu(QMenu *menu, QTextEdit *edit, const QPoint c.movePosition(QTextCursor::StartOfWord); c.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); - auto word = c.selectedText().trimmed(); + auto word = c.selectedText().toUpper().trimmed(); if(word.isEmpty()){ return; } @@ -10468,7 +10415,7 @@ void MainWindow::processCommandActivity() { c = ui->textEditRX->textCursor(); c.movePosition(QTextCursor::StartOfBlock); 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.deletePreviousChar(); c.deletePreviousChar();