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();
147 void ViewSourceWidget::updateView()
150 document_->setPlainText(QString());
157 string const format = fromqstr(view_format_);
160 Buffer::OutputWhat output = Buffer::CurrentParagraph;
161 if (contentsCO->currentIndex() == 1)
162 output = Buffer::FullSource;
163 else if (contentsCO->currentIndex() == 2)
164 output = Buffer::OnlyPreamble;
165 else if (contentsCO->currentIndex() == 3)
166 output = Buffer::OnlyBody;
168 if (getContent(bv_, output, content, format, force_getcontent_))
169 document_->setPlainText(content);
171 CursorSlice beg = bv_->cursor().selectionBegin().bottom();
172 CursorSlice end = bv_->cursor().selectionEnd().bottom();
173 int const begrow = bv_->buffer().texrow().
174 getRowFromIdPos(beg.paragraph().id(), beg.pos());
175 int endrow = bv_->buffer().texrow().
176 getRowFromIdPos(end.paragraph().id(), end.pos());
177 int const nextendrow = bv_->buffer().texrow().
178 getRowFromIdPos(end.paragraph().id(), end.pos() + 1);
179 if (endrow != nextendrow)
180 endrow = nextendrow - 1;
182 QTextCursor c = QTextCursor(viewSourceTV->document());
183 c.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor, begrow);
184 c.select(QTextCursor::BlockUnderCursor);
185 c.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor,
186 endrow - begrow + 1);
187 viewSourceTV->setTextCursor(c);
191 void ViewSourceWidget::updateDefaultFormat()
196 outputFormatCO->blockSignals(true);
197 outputFormatCO->clear();
198 outputFormatCO->addItem(qt_("Default"),
199 QVariant(QString("default")));
202 vector<string> tmp = bv_->buffer().params().backends();
203 vector<string>::const_iterator it = tmp.begin();
204 vector<string>::const_iterator en = tmp.end();
205 for (; it != en; ++it) {
206 string const format = *it;
207 Format const * fmt = formats.getFormat(format);
209 LYXERR0("Can't find format for backend " << format << "!");
211 } else if (fmt->name() == "lyx")
212 // we can't presently display the LyX format itself
215 QString const pretty = qt_(fmt->prettyname());
216 QString const qformat = toqstr(format);
217 outputFormatCO->addItem(pretty, QVariant(qformat));
218 if (qformat == view_format_)
219 index = outputFormatCO->count() -1;
221 outputFormatCO->setCurrentIndex(index);
223 outputFormatCO->blockSignals(false);
227 GuiViewSource::GuiViewSource(GuiView & parent,
228 Qt::DockWidgetArea area, Qt::WindowFlags flags)
229 : DockView(parent, "view-source", qt_("LaTeX Source"), area, flags)
231 widget_ = new ViewSourceWidget();
236 GuiViewSource::~GuiViewSource()
242 void GuiViewSource::updateView()
244 if (widget_->autoUpdateCB->isChecked()) {
245 widget_->setBufferView(bufferview());
246 widget_->updateView();
251 void GuiViewSource::enableView(bool enable)
253 widget_->setBufferView(bufferview());
254 widget_->updateDefaultFormat();
256 // In the opposite case, updateView() will be called anyway.
257 widget_->updateView();
261 bool GuiViewSource::initialiseParams(string const & /*source*/)
263 setWindowTitle(title());
268 QString GuiViewSource::title() const
272 return qt_("LaTeX Source");
274 return qt_("DocBook Source");
276 return qt_("Literate Source");
278 LASSERT(false, /**/);
283 void GuiViewSource::saveSession() const
285 Dialog::saveSession();
288 // settings.setValue(
289 // sessionKey() + "/output", widget_->contentsCO->currentIndex());
291 sessionKey() + "/autoupdate", widget_->autoUpdateCB->isChecked());
295 void GuiViewSource::restoreSession()
297 DockView::restoreSession();
298 // FIXME: Full source updating is too slow to be done at startup.
299 //widget_->outputCO-setCurrentIndex(
300 // settings.value(sessionKey() + "/output", false).toInt());
301 widget_->contentsCO->setCurrentIndex(0);
303 widget_->autoUpdateCB->setChecked(
304 settings.value(sessionKey() + "/autoupdate", true).toBool());
305 widget_->updateView();
309 Dialog * createGuiViewSource(GuiView & lv)
311 return new GuiViewSource(lv);
315 } // namespace frontend
318 #include "moc_GuiViewSource.cpp"