2 * \file GuiViewSource.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
8 * \author Abdelrazak Younes
10 * Full author contact details are available in file CREDITS.
15 #include "GuiViewSource.h"
16 #include "qt_helpers.h"
18 #include "Application.h"
19 #include "BufferView.h"
23 #include "Paragraph.h"
26 #include <QTextCursor>
27 #include <QTextDocument>
28 #include <boost/tuple/tuple.hpp>
35 GuiViewSourceDialog::GuiViewSourceDialog(ControlViewSource & controller)
36 : controller_(controller), document_(new QTextDocument(this)),
37 highlighter_(new LaTeXHighlighter(document_))
40 setWindowTitle(qt_("LaTeX Source"));
42 connect(viewFullSourceCB, SIGNAL(clicked()),
43 this, SLOT(updateView()));
44 connect(autoUpdateCB, SIGNAL(toggled(bool)),
45 updatePB, SLOT(setDisabled(bool)));
46 connect(updatePB, SIGNAL(clicked()),
47 this, SLOT(updateView()));
49 // setting a document at this point trigger an assertion in Qt
50 // so we disable the signals here:
51 document()->blockSignals(true);
52 viewSourceTV->setDocument(document());
53 document()->blockSignals(false);
54 viewSourceTV->setReadOnly(true);
55 ///dialog_->viewSourceTV->setAcceptRichText(false);
56 // this is personal. I think source code should be in fixed-size font
57 QFont font(toqstr(theApp()->typewriterFontName()));
58 font.setKerning(false);
59 font.setFixedPitch(true);
60 font.setStyleHint(QFont::TypeWriter);
61 viewSourceTV->setFont(font);
62 // again, personal taste
63 viewSourceTV->setWordWrapMode(QTextOption::NoWrap);
67 void GuiViewSourceDialog::updateView()
69 if (autoUpdateCB->isChecked())
70 update(viewFullSourceCB->isChecked());
73 boost::tie(beg, end) = controller_.getRows();
74 QTextCursor c = QTextCursor(viewSourceTV->document());
75 c.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor, beg);
76 c.select(QTextCursor::BlockUnderCursor);
77 c.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor, end - beg + 1);
78 viewSourceTV->setTextCursor(c);
83 void GuiViewSourceDialog::update(bool full_source)
85 document_->setPlainText(toqstr(controller_.updateContent(full_source)));
90 /////////////////////////////////////////////////////////////////////
94 /////////////////////////////////////////////////////////////////////
97 LaTeXHighlighter::LaTeXHighlighter(QTextDocument * parent)
98 : QSyntaxHighlighter(parent)
100 keywordFormat.setForeground(Qt::darkBlue);
101 keywordFormat.setFontWeight(QFont::Bold);
102 commentFormat.setForeground(Qt::darkGray);
103 mathFormat.setForeground(Qt::red);
107 void LaTeXHighlighter::highlightBlock(QString const & text)
110 QRegExp exprMath("\\$[^\\$]*\\$");
111 int index = text.indexOf(exprMath);
113 int length = exprMath.matchedLength();
114 setFormat(index, length, mathFormat);
115 index = text.indexOf(exprMath, index + length);
118 QRegExp exprStartDispMath("(\\\\\\[|"
119 "\\\\begin\\{equation\\**\\}|"
120 "\\\\begin\\{eqnarray\\**\\}|"
121 "\\\\begin\\{align(ed|at)*\\**\\}|"
122 "\\\\begin\\{flalign\\**\\}|"
123 "\\\\begin\\{gather\\**\\}|"
124 "\\\\begin\\{multline\\**\\}|"
125 "\\\\begin\\{array\\**\\}|"
126 "\\\\begin\\{cases\\**\\}"
128 QRegExp exprEndDispMath("(\\\\\\]|"
129 "\\\\end\\{equation\\**\\}|"
130 "\\\\end\\{eqnarray\\**\\}|"
131 "\\\\end\\{align(ed|at)*\\**\\}|"
132 "\\\\end\\{flalign\\**\\}|"
133 "\\\\end\\{gather\\**\\}|"
134 "\\\\end\\{multline\\**\\}|"
135 "\\\\end\\{array\\**\\}|"
136 "\\\\end\\{cases\\**\\}"
139 // if previous block was in 'disp math'
140 // start search from 0 (for end disp math)
141 // otherwise, start search from 'begin disp math'
142 if (previousBlockState() != 1)
143 startIndex = text.indexOf(exprStartDispMath);
144 while (startIndex >= 0) {
145 int endIndex = text.indexOf(exprEndDispMath, startIndex);
147 if (endIndex == -1) {
148 setCurrentBlockState(1);
149 length = text.length() - startIndex;
151 length = endIndex - startIndex + exprEndDispMath.matchedLength();
153 setFormat(startIndex, length, mathFormat);
154 startIndex = text.indexOf(exprStartDispMath, startIndex + length);
157 QRegExp exprKeyword("\\\\[A-Za-z]+");
158 index = text.indexOf(exprKeyword);
160 int length = exprKeyword.matchedLength();
161 setFormat(index, length, keywordFormat);
162 index = text.indexOf(exprKeyword, index + length);
165 QRegExp exprComment("(^|[^\\\\])%.*$");
166 index = text.indexOf(exprComment);
168 int const length = exprComment.matchedLength();
169 setFormat(index, length, commentFormat);
170 index = text.indexOf(exprComment, index + length);
175 ControlViewSource::ControlViewSource(Dialog & parent)
180 bool ControlViewSource::initialiseParams(string const & /*source*/)
186 docstring const ControlViewSource::updateContent(bool fullSource)
188 // get the *top* level paragraphs that contain the cursor,
189 // or the selected text
193 BufferView * view = bufferview();
194 if (!view->cursor().selection()) {
195 par_begin = view->cursor().bottom().pit();
198 par_begin = view->cursor().selectionBegin().bottom().pit();
199 par_end = view->cursor().selectionEnd().bottom().pit();
201 if (par_begin > par_end)
202 std::swap(par_begin, par_end);
203 odocstringstream ostr;
204 view->buffer().getSourceCode(ostr, par_begin, par_end + 1, fullSource);
209 std::pair<int, int> ControlViewSource::getRows() const
211 BufferView const * view = bufferview();
212 CursorSlice beg = view->cursor().selectionBegin().bottom();
213 CursorSlice end = view->cursor().selectionEnd().bottom();
215 int begrow = view->buffer().texrow().
216 getRowFromIdPos(beg.paragraph().id(), beg.pos());
217 int endrow = view->buffer().texrow().
218 getRowFromIdPos(end.paragraph().id(), end.pos());
219 int nextendrow = view->buffer().texrow().
220 getRowFromIdPos(end.paragraph().id(), end.pos() + 1);
221 return std::make_pair(begrow, endrow == nextendrow ? endrow : (nextendrow - 1));
225 docstring const ControlViewSource::title() const
229 return _("LaTeX Source");
231 return _("DocBook Source");
233 return _("Literate Source");
241 Dialog * createGuiViewSource(LyXView & lv)
243 return new GuiViewSource(static_cast<GuiViewBase &>(lv));
247 } // namespace frontend
250 #include "GuiViewSource_moc.cpp"