]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/QViewSource.cpp
Transfer Text::drawSelection() from InsetText::drawSelection() to InsetText::draw...
[lyx.git] / src / frontends / qt4 / QViewSource.cpp
1 /**
2  * \file QViewSource.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author John Levon
7  * \author Bo Peng
8  * \author Abdelrazak Younes
9  *
10  * Full author contact details are available in file CREDITS.
11  */
12
13 #include <config.h>
14
15 #include "QViewSource.h"
16 #include "qt_helpers.h"
17
18 #include <boost/tuple/tuple.hpp>
19
20 #include <QTextCursor>
21 #include <QTextDocument>
22
23 namespace lyx {
24 namespace frontend {
25
26 /////////////////////////////////////////////////////////////////////
27 //
28 // QViewSourceDialog
29 //
30 /////////////////////////////////////////////////////////////////////
31
32 QViewSourceDialog::QViewSourceDialog(QViewSource * form)
33         : form_(form)
34 {
35         setupUi(this);
36
37         connect(viewFullSourceCB, SIGNAL(clicked()),
38                 this, SLOT(update()));
39         connect(autoUpdateCB, SIGNAL(toggled(bool)),
40                 updatePB, SLOT(setDisabled(bool)));
41         connect(updatePB, SIGNAL(clicked()),
42                 this, SLOT(update()));
43
44         // setting a document at this point trigger an assertion in Qt
45         // so we disable the signals here:
46         form_->document()->blockSignals(true);
47         viewSourceTV->setDocument(form_->document());
48         form_->document()->blockSignals(false);
49         viewSourceTV->setReadOnly(true);
50         ///dialog_->viewSourceTV->setAcceptRichText(false);
51         // this is personal. I think source code should be in fixed-size font
52         QFont font(toqstr(theApp()->typewriterFontName()));
53         font.setKerning(false);
54         font.setFixedPitch(true);
55         font.setStyleHint(QFont::TypeWriter);
56         viewSourceTV->setFont(font);
57         // again, personal taste
58         viewSourceTV->setWordWrapMode(QTextOption::NoWrap);
59 }
60
61
62 void QViewSourceDialog::update()
63 {
64         if (autoUpdateCB->isChecked())
65                 form_->update(viewFullSourceCB->isChecked());
66
67         int beg, end;
68         boost::tie(beg, end) = form_->getRows();
69         QTextCursor c = QTextCursor(viewSourceTV->document());
70         c.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor, beg);
71         c.select(QTextCursor::BlockUnderCursor);
72         c.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor, end - beg + 1);
73         viewSourceTV->setTextCursor(c);
74         QWidget::update();
75 }
76
77
78 /////////////////////////////////////////////////////////////////////
79 //
80 // LaTeXHighlighter
81 //
82 /////////////////////////////////////////////////////////////////////
83
84
85 LaTeXHighlighter::LaTeXHighlighter(QTextDocument * parent)
86         : QSyntaxHighlighter(parent)
87 {
88         keywordFormat.setForeground(Qt::darkBlue);
89         keywordFormat.setFontWeight(QFont::Bold);
90         commentFormat.setForeground(Qt::darkGray);
91         mathFormat.setForeground(Qt::red);
92 }
93
94
95 void LaTeXHighlighter::highlightBlock(QString const & text)
96 {
97         // $ $
98         QRegExp exprMath("\\$[^\\$]*\\$");
99         int index = text.indexOf(exprMath);
100         while (index >= 0) {
101                 int length = exprMath.matchedLength();
102                 setFormat(index, length, mathFormat);
103                 index = text.indexOf(exprMath, index + length);
104         }
105         // [ ]
106         QRegExp exprStartDispMath("(\\\\\\[|"
107                 "\\\\begin\\{equation\\**\\}|"
108                 "\\\\begin\\{eqnarray\\**\\}|"
109                 "\\\\begin\\{align(ed|at)*\\**\\}|"
110                 "\\\\begin\\{flalign\\**\\}|"
111                 "\\\\begin\\{gather\\**\\}|"
112                 "\\\\begin\\{multline\\**\\}|"
113                 "\\\\begin\\{array\\**\\}|"
114                 "\\\\begin\\{cases\\**\\}"
115                 ")");
116         QRegExp exprEndDispMath("(\\\\\\]|"
117                 "\\\\end\\{equation\\**\\}|"
118                 "\\\\end\\{eqnarray\\**\\}|"
119                 "\\\\end\\{align(ed|at)*\\**\\}|"
120                 "\\\\end\\{flalign\\**\\}|"
121                 "\\\\end\\{gather\\**\\}|"
122                 "\\\\end\\{multline\\**\\}|"
123                 "\\\\end\\{array\\**\\}|"
124                 "\\\\end\\{cases\\**\\}"
125                 ")");
126         int startIndex = 0;
127         // if previous block was in 'disp math'
128         // start search from 0 (for end disp math)
129         // otherwise, start search from 'begin disp math'
130         if (previousBlockState() != 1)
131                 startIndex = text.indexOf(exprStartDispMath);
132         while (startIndex >= 0) {
133                 int endIndex = text.indexOf(exprEndDispMath, startIndex);
134                 int length;
135                 if (endIndex == -1) {
136                         setCurrentBlockState(1);
137                         length = text.length() - startIndex;
138                 } else {
139                         length = endIndex - startIndex + exprEndDispMath.matchedLength();
140                 }
141                 setFormat(startIndex, length, mathFormat);
142                 startIndex = text.indexOf(exprStartDispMath, startIndex + length);
143         }
144         // \whatever
145         QRegExp exprKeyword("\\\\[A-Za-z]+");
146         index = text.indexOf(exprKeyword);
147         while (index >= 0) {
148                 int length = exprKeyword.matchedLength();
149                 setFormat(index, length, keywordFormat);
150                 index = text.indexOf(exprKeyword, index + length);
151         }
152         // comment
153         QRegExp exprComment("(^|[^\\\\])%.*$");
154         index = text.indexOf(exprComment);
155         while (index >= 0) {
156                 int const length = exprComment.matchedLength();
157                 setFormat(index, length, commentFormat);
158                 index = text.indexOf(exprComment, index + length);
159         }
160 }
161
162
163 QViewSource::QViewSource(Dialog & parent)
164         : ControlViewSource(parent)
165 {
166         document_ = new QTextDocument(this);
167         highlighter_ = new LaTeXHighlighter(document_);
168 }
169
170
171 /////////////////////////////////////////////////////////////////////
172 //
173 // QViewSource
174 //
175 /////////////////////////////////////////////////////////////////////
176
177 void QViewSource::update(bool full_source)
178 {
179         document_->setPlainText(toqstr(updateContent(full_source)));
180 }
181
182
183 } // namespace frontend
184 } // namespace lyx
185
186 #include "QViewSource_moc.cpp"