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 << "!");
213 QString const pretty = qt_(fmt->prettyname());
214 QString const qformat = toqstr(format);
215 outputFormatCO->addItem(pretty, QVariant(qformat));
216 if (qformat == view_format_)
217 index = outputFormatCO->count() -1;
219 outputFormatCO->setCurrentIndex(index);
221 outputFormatCO->blockSignals(false);
225 GuiViewSource::GuiViewSource(GuiView & parent,
226 Qt::DockWidgetArea area, Qt::WindowFlags flags)
227 : DockView(parent, "view-source", qt_("LaTeX Source"), area, flags)
229 widget_ = new ViewSourceWidget();
234 GuiViewSource::~GuiViewSource()
240 void GuiViewSource::updateView()
242 if (widget_->autoUpdateCB->isChecked()) {
243 widget_->setBufferView(bufferview());
244 widget_->updateView();
249 void GuiViewSource::enableView(bool enable)
251 widget_->setBufferView(bufferview());
252 widget_->updateDefaultFormat();
254 // In the opposite case, updateView() will be called anyway.
255 widget_->updateView();
259 bool GuiViewSource::initialiseParams(string const & /*source*/)
261 setWindowTitle(title());
266 QString GuiViewSource::title() const
270 return qt_("LaTeX Source");
272 return qt_("DocBook Source");
274 return qt_("Literate Source");
276 LASSERT(false, /**/);
281 void GuiViewSource::saveSession() const
283 Dialog::saveSession();
286 // settings.setValue(
287 // sessionKey() + "/output", widget_->contentsCO->currentIndex());
289 sessionKey() + "/autoupdate", widget_->autoUpdateCB->isChecked());
293 void GuiViewSource::restoreSession()
295 DockView::restoreSession();
296 // FIXME: Full source updating is too slow to be done at startup.
297 //widget_->outputCO-setCurrentIndex(
298 // settings.value(sessionKey() + "/output", false).toInt());
299 widget_->contentsCO->setCurrentIndex(0);
301 widget_->autoUpdateCB->setChecked(
302 settings.value(sessionKey() + "/autoupdate", true).toBool());
303 widget_->updateView();
307 Dialog * createGuiViewSource(GuiView & lv)
309 return new GuiViewSource(lv);
313 } // namespace frontend
316 #include "moc_GuiViewSource.cpp"