"Fossies" - the Fresh Open Source Software Archive

Member "texstudio-3.1.1/src/spellerdialog.cpp" (21 Feb 2021, 10671 Bytes) of package /linux/misc/texstudio-3.1.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "spellerdialog.cpp" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3.1.0_vs_3.1.1.

    1 /***************************************************************************
    2  *   copyright       : (C) 2007 by Pascal Brachet                          *
    3  *                                                                         *
    4  *   This program is free software; you can redistribute it and/or modify  *
    5  *   it under the terms of the GNU General Public License as published by  *
    6  *   the Free Software Foundation; either version 2 of the License, or     *
    7  *   (at your option) any later version.                                   *
    8  *                                                                         *
    9  ***************************************************************************/
   10 
   11 #include "spellerdialog.h"
   12 
   13 #include "smallUsefulFunctions.h"
   14 #include "utilsUI.h"
   15 
   16 #include "qdocumentline.h"
   17 
   18 #include <QItemEditorCreatorBase>
   19 #include <QStyledItemDelegate>
   20 
   21 const QRegExpValidator wordValidator(QRegExp("[^<].*"), nullptr);
   22 
   23 SpellerDialog::SpellerDialog(QWidget *parent, SpellerUtility *utility)
   24     : QDialog(parent), m_statusBar(nullptr), m_speller(utility), editor(nullptr), editorView(nullptr)
   25 {
   26     ui.setupUi(this);
   27     setModal(true);
   28     UtilsUi::resizeInFontHeight(this, 31, 26);
   29 
   30     m_statusBar = new QStatusBar();
   31     delete ui.dummyStatusBar;
   32     layout()->addWidget(m_statusBar);
   33     // workaround for wrong status bar text color (black) in modern style
   34     // TODO: change the style and remove this extra label
   35     QLabel *messageArea = new QLabel(m_statusBar);
   36     connect(m_statusBar, SIGNAL(messageChanged(QString)), messageArea, SLOT(setText(QString)));
   37     m_statusBar->addPermanentWidget(messageArea, 1);
   38 
   39     connect(ui.pushButtonIgnoreList, SIGNAL(clicked()), this, SLOT(toggleIgnoreList()));
   40     connect(ui.pushButtonAdd, SIGNAL(clicked()), this, SLOT(addIgnoredWord()));
   41     connect(ui.pushButtonRemove, SIGNAL(clicked()), this, SLOT(removeIgnoredWord()));
   42     connect(ui.pushButtonIgnore, SIGNAL(clicked()), this, SLOT(slotIgnore()));
   43     connect(ui.pushButtonAlwaysIgnore, SIGNAL(clicked()), this, SLOT(slotAlwaysIgnore()));
   44     connect(ui.pushButtonReplace, SIGNAL(clicked()), this, SLOT(slotReplace()));
   45     connect(ui.listSuggestions, SIGNAL(itemSelectionChanged()), this, SLOT(updateItem()));
   46 
   47     ui.listSuggestions->setEnabled(false);
   48     ui.lineEditNew->setEnabled(false);
   49     ui.pushButtonIgnore->setEnabled(false);
   50     ui.pushButtonAlwaysIgnore->setEnabled(false);
   51     ui.pushButtonReplace->setEnabled(false);
   52     ui.lineEditOriginal->setEnabled(false);
   53 
   54     ui.ignoreListView->setEditTriggers(QAbstractItemView::NoEditTriggers);
   55     IgnoreListViewDelegate *itemDelegate = new IgnoreListViewDelegate(ui.ignoreListView);
   56     ui.ignoreListView->setItemDelegate(itemDelegate);
   57     connect(itemDelegate, SIGNAL(closeEditor(QWidget *)), this, SLOT(finishEditIgnoreList()));
   58 
   59     toggleIgnoreList(true);  // start with hidden ignore list
   60 }
   61 
   62 SpellerDialog::~SpellerDialog()
   63 {
   64     ui.lineEditOriginal->clear();
   65     ui.listSuggestions->clear();
   66     ui.lineEditNew->clear();
   67 
   68 }
   69 
   70 void SpellerDialog::setEditorView(LatexEditorView *edView)
   71 {
   72     editor = edView ? edView->editor : nullptr;
   73     editorView = edView;
   74     if(edView)
   75         mReplacementList=edView->getReplacementList();
   76 }
   77 
   78 void SpellerDialog::startSpelling()
   79 {
   80     if (!editor) return;
   81     ignoreListChanged = false;
   82     if (editor->cursor().hasSelection()) {
   83 
   84         m_statusBar->showMessage(tr("Check spelling selection..."));
   85         startLine = editor->cursor().selectionStart().lineNumber();
   86         startIndex = editor->cursor().selectionStart().columnNumber();
   87         endLine = editor->cursor().selectionEnd().lineNumber();
   88         endIndex = editor->cursor().selectionEnd().columnNumber();
   89     } else  {
   90         m_statusBar->showMessage(tr("Check spelling from cursor..."));
   91         editor->getCursorPosition(startLine, startIndex);
   92         endLine = editor->document()->lines() - 1;
   93         endIndex = editor->text(endLine).length();
   94     }
   95     curLine = startLine;
   96     // determine tokenIndex from cursor index
   97     QDocumentLineHandle *dlh=editor->document()->line(curLine).handle();
   98     tl=dlh->getCookieLocked(QDocumentLine::LEXER_COOKIE).value<TokenList >();
   99     for(tokenListIndex=0;tokenListIndex<tl.length();++tokenListIndex){
  100         Token tk=tl.at(tokenListIndex);
  101         if(tk.start+tk.length>startIndex)
  102             break;
  103     }
  104     --tokenListIndex; // index is increased as first step in SpellingNextWord()
  105     show();
  106     SpellingNextWord();
  107 }
  108 
  109 void SpellerDialog::closeEvent(QCloseEvent *ce)
  110 {
  111     if (editorView && ignoreListChanged) {
  112         ignoreListChanged = false;
  113         editorView->reCheckSyntax(0);
  114     }
  115     if (editor) editor->setCursorPosition(startLine, startIndex);
  116     ce->accept();
  117 }
  118 
  119 void SpellerDialog::accept()
  120 {
  121     if (editorView && ignoreListChanged) {
  122         ignoreListChanged = false;
  123         editorView->reCheckSyntax(0);
  124     }
  125     if (editor) editor->setCursorPosition(startLine, startIndex);
  126     QDialog::accept();
  127 }
  128 
  129 void SpellerDialog::updateItem()
  130 {
  131     int current = -1;
  132     QList<QListWidgetItem *> items;
  133     items = ui.listSuggestions->selectedItems();
  134     if (items.count() > 0) {
  135         ui.listSuggestions->setCurrentItem(items[0]);
  136         current = ui.listSuggestions->row(items[0]);
  137     }
  138     if (current >= 0) {
  139         ui.lineEditNew->setText(ui.listSuggestions->currentItem()->text());
  140     }
  141 }
  142 
  143 void SpellerDialog::slotIgnore()
  144 {
  145     SpellingNextWord();
  146 }
  147 
  148 void SpellerDialog::slotAlwaysIgnore()
  149 {
  150     //todo: real time update of now allowed words
  151     m_speller->addToIgnoreList(ui.lineEditOriginal->text());
  152     ignoreListChanged = true;
  153     SpellingNextWord();
  154 }
  155 
  156 void SpellerDialog::slotReplace()
  157 {
  158     if (!editor) return;
  159     if (editor->cursor().hasSelection()) {
  160         QString selectedword = editor->cursor().selectedText();
  161         editor->insertText(ui.lineEditNew->text());
  162     }
  163     SpellingNextWord();
  164 }
  165 
  166 void SpellerDialog::SpellingNextWord()
  167 {
  168     if (!editor || !m_speller) return;
  169     for (; curLine <= endLine; curLine++) {
  170         QDocumentLineHandle *dlh=editor->document()->line(curLine).handle();
  171         tl=dlh->getCookieLocked(QDocumentLine::LEXER_COOKIE).value<TokenList >();
  172         while(tokenListIndex<tl.length()-1){
  173             ++tokenListIndex;
  174             Token tk=tl.at(tokenListIndex);
  175             if (tk.type!=Token::word)
  176                 continue;
  177             if(tk.subtype != Token::text && tk.subtype != Token::title && tk.subtype != Token::shorttitle && tk.subtype != Token::todo && tk.subtype != Token::none)
  178                 continue;
  179             QString word=tk.getText();
  180             word = latexToPlainWordwithReplacementList(word, mReplacementList);
  181             if (tk.ignoreSpelling || m_speller->check(word)) continue;
  182             QStringList suggWords = m_speller->suggest(word);
  183 
  184             QDocumentCursor wordSelection(editor->document(), curLine, tk.start);
  185             wordSelection.movePosition(tk.length, QDocumentCursor::NextCharacter, QDocumentCursor::KeepAnchor);
  186             editor->setCursor(wordSelection);
  187 
  188             ui.listSuggestions->setEnabled(true);
  189             ui.lineEditNew->setEnabled(true);
  190             ui.pushButtonIgnore->setEnabled(true);
  191             ui.pushButtonAlwaysIgnore->setEnabled(true);
  192             ui.pushButtonReplace->setEnabled(true);
  193             ui.lineEditOriginal->setEnabled(true);
  194             ui.lineEditOriginal->setText(word);
  195             ui.listSuggestions->clear();
  196             ui.lineEditNew->clear();
  197             m_statusBar->clearMessage();
  198             if (!suggWords.isEmpty()) {
  199                 ui.listSuggestions->addItems(suggWords);
  200                 ui.lineEditNew->setText(suggWords.at(0));
  201             }
  202             return;
  203         }
  204         tokenListIndex = -1;
  205     }
  206 
  207     //no word found
  208     ui.listSuggestions->setEnabled(false);
  209     ui.lineEditNew->setEnabled(false);
  210     ui.pushButtonIgnore->setEnabled(false);
  211     ui.pushButtonAlwaysIgnore->setEnabled(false);
  212     ui.pushButtonReplace->setEnabled(false);
  213     ui.lineEditOriginal->setEnabled(false);
  214     ui.lineEditOriginal->clear();
  215     ui.listSuggestions->clear();
  216     ui.lineEditNew->clear();
  217     m_statusBar->showMessage("<b>" + tr("No more misspelled words") + "</b>");
  218 }
  219 
  220 void SpellerDialog::toggleIgnoreList(bool forceHide)
  221 {
  222     QList<QWidget *> hideableWidgets = QList<QWidget *>() << ui.ignoreListView << ui.labelIgnoredWords << ui.pushButtonAdd << ui.pushButtonRemove << ui.labelAsHideableSpacer;
  223 
  224     if (ui.ignoreListView->isVisible() || forceHide) {
  225         foreach (QWidget * w, hideableWidgets) w->hide();
  226         ui.pushButtonIgnoreList->setText(tr("Show User Words"));
  227         ui.pushButtonIgnoreList->setIcon(getRealIcon("down-arrow-circle-silver"));
  228         resize(width(), height() - (ui.ignoreListView->height() + ui.gridLayout->verticalSpacing()));
  229     } else {
  230         resize(width(), height() + (ui.listSuggestions->height() + ui.gridLayout->verticalSpacing()));
  231         ui.pushButtonIgnoreList->setText(tr("Hide User Words"));
  232         ui.pushButtonIgnoreList->setIcon(getRealIcon("up-arrow-circle-silver"));
  233         if (m_speller && !ui.ignoreListView->model())
  234             ui.ignoreListView->setModel(m_speller->ignoreListModel());
  235         foreach (QWidget * w, hideableWidgets) w->show();
  236     }
  237 }
  238 
  239 void SpellerDialog::addIgnoredWord()
  240 {
  241     if (!m_speller) return;
  242     finishEditIgnoreList(); // needed for possible cleanup if an editor is open, harmless otherwise
  243 
  244     QStringListModel *m = m_speller->ignoreListModel();
  245     m->insertRow(0);
  246     m->setData(m->index(0), QVariant(tr("<new>", "Placeholder for new added word in ignore list")));
  247 
  248     ui.ignoreListView->selectionModel()->setCurrentIndex(m->index(0), QItemSelectionModel::Select);
  249     ui.ignoreListView->edit(m->index(0));
  250 }
  251 
  252 void SpellerDialog::removeIgnoredWord()
  253 {
  254     if (!m_speller) return;
  255     if (!ui.ignoreListView->model()) return;
  256     QString selectedWord = ui.ignoreListView->model()->data(ui.ignoreListView->currentIndex(), Qt::DisplayRole).toString();
  257     m_speller->removeFromIgnoreList(selectedWord);
  258 }
  259 
  260 void SpellerDialog::finishEditIgnoreList()
  261 {
  262     QString word = ui.ignoreListView->model()->data(ui.ignoreListView->currentIndex(), Qt::DisplayRole).toString();
  263     int dummy;
  264     if (wordValidator.validate(word, dummy) == QValidator::Acceptable) {
  265         m_speller->addToIgnoreList(word);
  266     } else {
  267         ui.ignoreListView->model()->removeRow(ui.ignoreListView->currentIndex().row());
  268     }
  269 }
  270 
  271 ValidatedLineEdit::ValidatedLineEdit(QWidget *parent) : QLineEdit(parent)
  272 {
  273     setValidator(&wordValidator);
  274 }
  275 
  276 IgnoreListViewDelegate::IgnoreListViewDelegate(QObject *parent) : QStyledItemDelegate(parent)
  277 {
  278     QItemEditorCreatorBase *creator = new QStandardItemEditorCreator<ValidatedLineEdit>();
  279     QItemEditorFactory *factory = new QItemEditorFactory();
  280     factory->registerEditor(QVariant::String, creator);
  281     setItemEditorFactory(factory);
  282 }
  283 
  284 void IgnoreListViewDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
  285 {
  286     QByteArray n = editor->metaObject()->userProperty().name();
  287     if (!n.isEmpty()) {
  288         QString word = editor->property(n).toString();
  289         int pos;
  290         if (wordValidator.validate(word, pos) == QValidator::Acceptable) {
  291             model->setData(index, editor->property(n), Qt::EditRole);
  292         }
  293     }
  294 }