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 "GuiApplication.h"
16 #include "GuiViewSource.h"
17 #include "LaTeXHighlighter.h"
18 #include "qt_helpers.h"
21 #include "BufferParams.h"
22 #include "BufferView.h"
25 #include "Paragraph.h"
28 #include "support/debug.h"
29 #include "support/lassert.h"
30 #include "support/docstream.h"
31 #include "support/gettext.h"
33 #include <boost/crc.hpp>
36 #include <QTextCursor>
37 #include <QTextDocument>
45 ViewSourceWidget::ViewSourceWidget()
46 : bv_(0), document_(new QTextDocument(this)),
47 highlighter_(new LaTeXHighlighter(document_)),
48 force_getcontent_(true)
52 connect(contentsCO, SIGNAL(activated(int)),
53 this, SLOT(contentsChanged()));
54 connect(autoUpdateCB, SIGNAL(toggled(bool)),
55 updatePB, SLOT(setDisabled(bool)));
56 connect(autoUpdateCB, SIGNAL(toggled(bool)),
57 this, SLOT(updateView()));
58 connect(masterPerspectiveCB, SIGNAL(toggled(bool)),
59 this, SLOT(updateView()));
60 connect(updatePB, SIGNAL(clicked()),
61 this, SLOT(updateView()));
62 connect(outputFormatCO, SIGNAL(activated(int)),
63 this, SLOT(setViewFormat()));
65 // setting a document at this point trigger an assertion in Qt
66 // so we disable the signals here:
67 document_->blockSignals(true);
68 viewSourceTV->setDocument(document_);
69 document_->blockSignals(false);
70 viewSourceTV->setReadOnly(true);
71 ///dialog_->viewSourceTV->setAcceptRichText(false);
72 // this is personal. I think source code should be in fixed-size font
73 QFont font(guiApp->typewriterFontName());
74 font.setKerning(false);
75 font.setFixedPitch(true);
76 font.setStyleHint(QFont::TypeWriter);
77 viewSourceTV->setFont(font);
78 // again, personal taste
79 viewSourceTV->setWordWrapMode(QTextOption::NoWrap);
83 static size_t crcCheck(docstring const & s)
85 boost::crc_32_type crc;
86 crc.process_bytes(&s[0], sizeof(char_type) * s.size());
87 return crc.checksum();
91 /** get the source code of selected paragraphs, or the whole document
92 \param fullSource get full source code
93 \return true if the content has changed since last call.
95 static bool getContent(BufferView const * view, Buffer::OutputWhat output,
96 QString & qstr, string const format, bool force_getcontent,
99 // get the *top* level paragraphs that contain the cursor,
100 // or the selected text
104 if (!view->cursor().selection()) {
105 par_begin = view->cursor().bottom().pit();
108 par_begin = view->cursor().selectionBegin().bottom().pit();
109 par_end = view->cursor().selectionEnd().bottom().pit();
111 if (par_begin > par_end)
112 swap(par_begin, par_end);
113 odocstringstream ostr;
114 view->buffer().getSourceCode(ostr, format, par_begin, par_end + 1,
116 docstring s = ostr.str();
117 static size_t crc = 0;
118 size_t newcrc = crcCheck(s);
119 if (newcrc == crc && !force_getcontent)
127 void ViewSourceWidget::setBufferView(BufferView const * bv)
130 force_getcontent_ = true;
132 setEnabled(bv ? true : false);
136 void ViewSourceWidget::contentsChanged()
138 if (autoUpdateCB->isChecked())
143 void ViewSourceWidget::setViewFormat()
145 view_format_ = outputFormatCO->itemData(
146 outputFormatCO->currentIndex()).toString();
151 void ViewSourceWidget::updateView()
154 document_->setPlainText(QString());
161 string const format = fromqstr(view_format_);
164 Buffer::OutputWhat output = Buffer::CurrentParagraph;
165 if (contentsCO->currentIndex() == 1)
166 output = Buffer::FullSource;
167 else if (contentsCO->currentIndex() == 2)
168 output = Buffer::OnlyPreamble;
169 else if (contentsCO->currentIndex() == 3)
170 output = Buffer::OnlyBody;
172 if (getContent(bv_, output, content, format,
173 force_getcontent_, masterPerspectiveCB->isChecked()))
174 document_->setPlainText(content);
176 CursorSlice beg = bv_->cursor().selectionBegin().bottom();
177 CursorSlice end = bv_->cursor().selectionEnd().bottom();
178 int const begrow = bv_->buffer().texrow().
179 getRowFromIdPos(beg.paragraph().id(), beg.pos());
180 int endrow = bv_->buffer().texrow().
181 getRowFromIdPos(end.paragraph().id(), end.pos());
182 int const nextendrow = bv_->buffer().texrow().
183 getRowFromIdPos(end.paragraph().id(), end.pos() + 1);
184 if (endrow != nextendrow)
185 endrow = nextendrow - 1;
187 QTextCursor c = QTextCursor(viewSourceTV->document());
188 c.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor, begrow);
189 c.select(QTextCursor::BlockUnderCursor);
190 c.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor,
191 endrow - begrow + 1);
192 viewSourceTV->setTextCursor(c);
196 void ViewSourceWidget::updateDefaultFormat()
201 outputFormatCO->blockSignals(true);
202 outputFormatCO->clear();
203 outputFormatCO->addItem(qt_("Default"),
204 QVariant(QString("default")));
207 vector<string> tmp = bv_->buffer().params().backends();
208 vector<string>::const_iterator it = tmp.begin();
209 vector<string>::const_iterator en = tmp.end();
210 for (; it != en; ++it) {
211 string const format = *it;
212 Format const * fmt = formats.getFormat(format);
214 LYXERR0("Can't find format for backend " << format << "!");
218 QString const pretty = qt_(fmt->prettyname());
219 QString const qformat = toqstr(format);
220 outputFormatCO->addItem(pretty, QVariant(qformat));
221 if (qformat == view_format_)
222 index = outputFormatCO->count() -1;
224 outputFormatCO->setCurrentIndex(index);
226 outputFormatCO->blockSignals(false);
230 GuiViewSource::GuiViewSource(GuiView & parent,
231 Qt::DockWidgetArea area, Qt::WindowFlags flags)
232 : DockView(parent, "view-source", qt_("LaTeX Source"), area, flags)
234 widget_ = new ViewSourceWidget;
239 GuiViewSource::~GuiViewSource()
245 void GuiViewSource::updateView()
247 if (widget_->autoUpdateCB->isChecked()) {
248 widget_->setBufferView(bufferview());
249 widget_->updateView();
251 widget_->masterPerspectiveCB->setEnabled(buffer().parent());
255 void GuiViewSource::enableView(bool enable)
257 widget_->setBufferView(bufferview());
258 widget_->updateDefaultFormat();
260 // In the opposite case, updateView() will be called anyway.
261 widget_->updateView();
265 bool GuiViewSource::initialiseParams(string const & /*source*/)
267 setWindowTitle(title());
272 QString GuiViewSource::title() const
276 return qt_("LaTeX Source");
278 return qt_("DocBook Source");
280 return qt_("Literate Source");
282 LASSERT(false, /**/);
287 void GuiViewSource::saveSession() const
289 Dialog::saveSession();
292 // settings.setValue(
293 // sessionKey() + "/output", widget_->contentsCO->currentIndex());
295 sessionKey() + "/autoupdate", widget_->autoUpdateCB->isChecked());
299 void GuiViewSource::restoreSession()
301 DockView::restoreSession();
302 // FIXME: Full source updating is too slow to be done at startup.
303 //widget_->outputCO-setCurrentIndex(
304 // settings.value(sessionKey() + "/output", false).toInt());
305 widget_->contentsCO->setCurrentIndex(0);
307 widget_->autoUpdateCB->setChecked(
308 settings.value(sessionKey() + "/autoupdate", true).toBool());
309 widget_->updateView();
313 Dialog * createGuiViewSource(GuiView & lv)
315 return new GuiViewSource(lv);
319 } // namespace frontend
322 #include "moc_GuiViewSource.cpp"