1 /*
2  *      linespell.cpp
3  *
4  *      Copyright 2014 David Vachulka <arch_dvx@users.sourceforge.net>
5  *
6  *      This program is free software; you can redistribute it and/or modify
7  *      it under the terms of the GNU General Public License as published by
8  *      the Free Software Foundation; either version 3 of the License, or
9  *      (at your option) any later version.
10  *
11  *      This program is distributed in the hope that it will be useful,
12  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *      GNU General Public License for more details.
15  *
16  *      You should have received a copy of the GNU General Public License
17  *      along with this program; if not, write to the Free Software
18  *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  *      MA 02110-1301, USA.
20  */
21 
22 #include <QAbstractTextDocumentLayout>
23 #include <QKeyEvent>
24 #include <QRegularExpression>
25 #include "linespell.h"
26 #include "config.h"
27 #include "preferences.h"
28 #include "dxutils.h"
29 
SpellHighlighter(QTextDocument * parent)30 SpellHighlighter::SpellHighlighter(QTextDocument *parent)
31     : QSyntaxHighlighter(parent), m_spellLang("")
32 {}
33 
highlightBlock(const QString & text)34 void SpellHighlighter::highlightBlock(const QString &text)
35 {
36     if(!m_spellLang.isEmpty())
37     {
38         QTextCharFormat tcf;
39         tcf.setUnderlineColor(QColor(255,0,0));
40         tcf.setUnderlineStyle(QTextCharFormat::SpellCheckUnderline);
41         QRegularExpression expression("\\b\\w+\\b");
42         // Iterate through all words
43         int startIndex = text.indexOf(expression);
44         while(startIndex >= 0)
45         {
46             QRegularExpressionMatch endMatch;
47             int endIndex = text.indexOf(expression, startIndex, &endMatch);
48             int length;
49             if(endIndex == -1)
50             {
51                 length = text.length() - startIndex;
52             }
53             else
54             {
55                 length = endIndex - startIndex + endMatch.capturedLength();
56             }
57             if(!dxUtils.checkWord(text.mid(startIndex,length), m_spellLang))
58                 setFormat(startIndex, length, tcf);
59             startIndex = text.indexOf(expression, startIndex + length);
60         }
61     }
62 }
63 
language() const64 QString SpellHighlighter::language() const
65 {
66     return m_spellLang;
67 }
68 
setLanguage(const QString & lang)69 void SpellHighlighter::setLanguage(const QString &lang)
70 {
71     m_spellLang = lang;
72 }
73 
LineSpell(QWidget * parent)74 LineSpell::LineSpell(QWidget *parent) :
75     QTextEdit(parent), m_useSpell(preferences.m_useSpell)
76 {
77     setWordWrapMode(QTextOption::NoWrap);
78     setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
79     setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
80     setTabChangesFocus(true);
81     setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
82     m_spell = new SpellHighlighter(document());
83 }
84 
minimumSizeHint() const85 QSize LineSpell::minimumSizeHint() const
86 {
87     QSize sh = QTextEdit::minimumSizeHint();
88     sh.setHeight(fontMetrics().height() + 1);
89     sh += QSize(0, QFrame::lineWidth() * 2);
90     return sh;
91 }
92 
sizeHint() const93 QSize LineSpell::sizeHint() const
94 {
95     QSize sh = QTextEdit::sizeHint();
96     sh.setHeight(int(document()->documentLayout()->documentSize().height()));
97     sh += QSize(0, QFrame::lineWidth() * 2);
98     ((QTextEdit*)this)->setMaximumHeight(sh.height());
99     return sh;
100 }
101 
text() const102 QString LineSpell::text() const
103 {
104     return toPlainText();
105 }
106 
setText(const QString & text)107 void LineSpell::setText(const QString &text)
108 {
109     setPlainText(text);
110     QTextCursor cursor(textCursor());
111     cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
112     setTextCursor(cursor);
113 }
114 
cursorPosition() const115 int LineSpell::cursorPosition() const
116 {
117     QTextCursor cursor(textCursor());
118     return cursor.position();
119 }
120 
setCursorPosition(int pos)121 void LineSpell::setCursorPosition(int pos)
122 {
123     QTextCursor cursor(textCursor());
124     cursor.setPosition(pos);
125     setTextCursor(cursor);
126 }
127 
setUseSpell(bool spell)128 void LineSpell::setUseSpell(bool spell)
129 {
130     m_useSpell = spell;
131     if(!m_useSpell)
132     {
133         m_spell->setLanguage("");
134         int cursor = cursorPosition();
135         setText(text());
136         setCursorPosition(cursor);
137     }
138 }
139 
language() const140 QString LineSpell::language() const
141 {
142     return m_spell->language();
143 }
144 
setLanguage(const QString & lang)145 void LineSpell::setLanguage(const QString &lang)
146 {
147     m_spell->setLanguage(lang);
148 }
149 
keyPressEvent(QKeyEvent * e)150 void LineSpell::keyPressEvent(QKeyEvent *e)
151 {
152     if(e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return)
153     {
154         emit returnPressed();
155         e->ignore();
156     }
157     else
158         QTextEdit::keyPressEvent(e);
159 }
160 
161 
162