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(updatePB, SIGNAL(clicked()),
59 this, SLOT(updateView()));
60 connect(outputFormatCO, SIGNAL(activated(int)),
61 this, SLOT(setViewFormat()));
63 // setting a document at this point trigger an assertion in Qt
64 // so we disable the signals here:
65 document_->blockSignals(true);
66 viewSourceTV->setDocument(document_);
67 document_->blockSignals(false);
68 viewSourceTV->setReadOnly(true);
69 ///dialog_->viewSourceTV->setAcceptRichText(false);
70 // this is personal. I think source code should be in fixed-size font
71 QFont font(guiApp->typewriterFontName());
72 font.setKerning(false);
73 font.setFixedPitch(true);
74 font.setStyleHint(QFont::TypeWriter);
75 viewSourceTV->setFont(font);
76 // again, personal taste
77 viewSourceTV->setWordWrapMode(QTextOption::NoWrap);
81 static size_t crcCheck(docstring const & s)
83 boost::crc_32_type crc;
84 crc.process_bytes(&s[0], sizeof(char_type) * s.size());
85 return crc.checksum();
89 /** get the source code of selected paragraphs, or the whole document
90 \param fullSource get full source code
91 \return true if the content has changed since last call.
93 static bool getContent(BufferView const * view, Buffer::OutputWhat output,
94 QString & qstr, string const format, bool force_getcontent)
96 // get the *top* level paragraphs that contain the cursor,
97 // or the selected text
101 if (!view->cursor().selection()) {
102 par_begin = view->cursor().bottom().pit();
105 par_begin = view->cursor().selectionBegin().bottom().pit();
106 par_end = view->cursor().selectionEnd().bottom().pit();
108 if (par_begin > par_end)
109 swap(par_begin, par_end);
110 odocstringstream ostr;
111 view->buffer().getSourceCode(ostr, format, par_begin, par_end + 1, output);
112 docstring s = ostr.str();
113 static size_t crc = 0;
114 size_t newcrc = crcCheck(s);
115 if (newcrc == crc && !force_getcontent)
123 void ViewSourceWidget::setBufferView(BufferView const * bv)
126 force_getcontent_ = true;
128 setEnabled(bv ? true : false);
132 void ViewSourceWidget::contentsChanged()
134 if (autoUpdateCB->isChecked())
139 void ViewSourceWidget::setViewFormat()
141 view_format_ = outputFormatCO->itemData(
142 outputFormatCO->currentIndex()).toString();
146 void ViewSourceWidget::updateView()
149 document_->setPlainText(QString());
156 string const format = fromqstr(view_format_);
159 Buffer::OutputWhat output = Buffer::CurrentParagraph;
160 if (contentsCO->currentIndex() == 1)
161 output = Buffer::FullSource;
162 else if (contentsCO->currentIndex() == 2)
163 output = Buffer::OnlyPreamble;
164 else if (contentsCO->currentIndex() == 3)
165 output = Buffer::OnlyBody;
167 if (getContent(bv_, output, content, format, force_getcontent_))
168 document_->setPlainText(content);
170 CursorSlice beg = bv_->cursor().selectionBegin().bottom();
171 CursorSlice end = bv_->cursor().selectionEnd().bottom();
172 int const begrow = bv_->buffer().texrow().
173 getRowFromIdPos(beg.paragraph().id(), beg.pos());
174 int endrow = bv_->buffer().texrow().
175 getRowFromIdPos(end.paragraph().id(), end.pos());
176 int const nextendrow = bv_->buffer().texrow().
177 getRowFromIdPos(end.paragraph().id(), end.pos() + 1);
178 if (endrow != nextendrow)
179 endrow = nextendrow - 1;
181 QTextCursor c = QTextCursor(viewSourceTV->document());
182 c.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor, begrow);
183 c.select(QTextCursor::BlockUnderCursor);
184 c.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor,
185 endrow - begrow + 1);
186 viewSourceTV->setTextCursor(c);
190 void ViewSourceWidget::updateDefaultFormat()
195 outputFormatCO->blockSignals(true);
196 outputFormatCO->clear();
197 outputFormatCO->addItem(qt_("Default"),
198 QVariant(QString("default")));
200 vector<string> tmp = bv_->buffer().params().backends();
201 vector<string>::const_iterator it = tmp.begin();
202 vector<string>::const_iterator en = tmp.end();
203 for (; it != en; ++it) {
204 string const format = *it;
205 Format const * fmt = formats.getFormat(format);
207 LYXERR0("Can't find format for backend " << format << "!");
208 else if (fmt->name() == "lyx")
209 // we can't presently display the LyX format itself
212 QString const pretty =
213 fmt ? qt_(fmt->prettyname()) : toqstr(format);
214 outputFormatCO->addItem(pretty, QVariant(toqstr(format)));
217 outputFormatCO->blockSignals(false);
221 GuiViewSource::GuiViewSource(GuiView & parent,
222 Qt::DockWidgetArea area, Qt::WindowFlags flags)
223 : DockView(parent, "view-source", qt_("LaTeX Source"), area, flags)
225 widget_ = new ViewSourceWidget();
230 GuiViewSource::~GuiViewSource()
236 void GuiViewSource::updateView()
238 if (widget_->autoUpdateCB->isChecked()) {
239 widget_->setBufferView(bufferview());
240 widget_->updateView();
245 void GuiViewSource::enableView(bool enable)
247 widget_->setBufferView(bufferview());
248 widget_->updateDefaultFormat();
250 // In the opposite case, updateView() will be called anyway.
251 widget_->updateView();
255 bool GuiViewSource::initialiseParams(string const & /*source*/)
257 setWindowTitle(title());
262 QString GuiViewSource::title() const
266 return qt_("LaTeX Source");
268 return qt_("DocBook Source");
270 return qt_("Literate Source");
272 LASSERT(false, /**/);
277 void GuiViewSource::saveSession() const
279 Dialog::saveSession();
282 // settings.setValue(
283 // sessionKey() + "/output", widget_->contentsCO->currentIndex());
285 sessionKey() + "/autoupdate", widget_->autoUpdateCB->isChecked());
289 void GuiViewSource::restoreSession()
291 DockView::restoreSession();
292 // FIXME: Full source updating is too slow to be done at startup.
293 //widget_->outputCO-setCurrentIndex(
294 // settings.value(sessionKey() + "/output", false).toInt());
295 widget_->contentsCO->setCurrentIndex(0);
297 widget_->autoUpdateCB->setChecked(
298 settings.value(sessionKey() + "/autoupdate", true).toBool());
299 widget_->updateView();
303 Dialog * createGuiViewSource(GuiView & lv)
305 return new GuiViewSource(lv);
309 } // namespace frontend
312 #include "moc_GuiViewSource.cpp"