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>
37 #include <QTextCursor>
38 #include <QTextDocument>
46 ViewSourceWidget::ViewSourceWidget()
47 : bv_(0), document_(new QTextDocument(this)),
48 highlighter_(new LaTeXHighlighter(document_)),
49 force_getcontent_(true)
53 connect(contentsCO, SIGNAL(activated(int)),
54 this, SLOT(contentsChanged()));
55 connect(autoUpdateCB, SIGNAL(toggled(bool)),
56 updatePB, SLOT(setDisabled(bool)));
57 connect(autoUpdateCB, SIGNAL(toggled(bool)),
58 this, SLOT(updateView()));
59 connect(masterPerspectiveCB, SIGNAL(toggled(bool)),
60 this, SLOT(updateView()));
61 connect(updatePB, SIGNAL(clicked()),
62 this, SLOT(updateView()));
63 connect(outputFormatCO, SIGNAL(activated(int)),
64 this, SLOT(setViewFormat()));
66 // setting a document at this point trigger an assertion in Qt
67 // so we disable the signals here:
68 document_->blockSignals(true);
69 viewSourceTV->setDocument(document_);
70 document_->blockSignals(false);
71 viewSourceTV->setReadOnly(true);
72 ///dialog_->viewSourceTV->setAcceptRichText(false);
73 // this is personal. I think source code should be in fixed-size font
74 QFont font(guiApp->typewriterFontName());
75 font.setKerning(false);
76 font.setFixedPitch(true);
77 font.setStyleHint(QFont::TypeWriter);
78 viewSourceTV->setFont(font);
79 // again, personal taste
80 viewSourceTV->setWordWrapMode(QTextOption::NoWrap);
84 static size_t crcCheck(docstring const & s)
86 boost::crc_32_type crc;
87 crc.process_bytes(&s[0], sizeof(char_type) * s.size());
88 return crc.checksum();
92 /** get the source code of selected paragraphs, or the whole document
93 \param fullSource get full source code
94 \return true if the content has changed since last call.
96 static bool getContent(BufferView const * view, Buffer::OutputWhat output,
97 QString & qstr, string const format, bool force_getcontent,
100 // get the *top* level paragraphs that contain the cursor,
101 // or the selected text
105 if (!view->cursor().selection()) {
106 par_begin = view->cursor().bottom().pit();
109 par_begin = view->cursor().selectionBegin().bottom().pit();
110 par_end = view->cursor().selectionEnd().bottom().pit();
112 if (par_begin > par_end)
113 swap(par_begin, par_end);
114 odocstringstream ostr;
115 view->buffer().getSourceCode(ostr, format, par_begin, par_end + 1,
117 docstring s = ostr.str();
118 static size_t crc = 0;
119 size_t newcrc = crcCheck(s);
120 if (newcrc == crc && !force_getcontent)
128 void ViewSourceWidget::setBufferView(BufferView const * bv)
131 force_getcontent_ = true;
133 setEnabled(bv ? true : false);
137 void ViewSourceWidget::contentsChanged()
139 if (autoUpdateCB->isChecked())
144 void ViewSourceWidget::setViewFormat()
146 view_format_ = outputFormatCO->itemData(
147 outputFormatCO->currentIndex()).toString();
152 void ViewSourceWidget::updateView()
155 document_->setPlainText(QString());
162 string const format = fromqstr(view_format_);
165 Buffer::OutputWhat output = Buffer::CurrentParagraph;
166 if (contentsCO->currentIndex() == 1)
167 output = Buffer::FullSource;
168 else if (contentsCO->currentIndex() == 2)
169 output = Buffer::OnlyPreamble;
170 else if (contentsCO->currentIndex() == 3)
171 output = Buffer::OnlyBody;
173 if (getContent(bv_, output, content, format,
174 force_getcontent_, masterPerspectiveCB->isChecked()))
175 document_->setPlainText(content);
177 CursorSlice beg = bv_->cursor().selectionBegin().bottom();
178 CursorSlice end = bv_->cursor().selectionEnd().bottom();
179 int const begrow = bv_->buffer().texrow().
180 getRowFromIdPos(beg.paragraph().id(), beg.pos());
181 int endrow = bv_->buffer().texrow().
182 getRowFromIdPos(end.paragraph().id(), end.pos());
183 int const nextendrow = bv_->buffer().texrow().
184 getRowFromIdPos(end.paragraph().id(), end.pos() + 1);
185 if (endrow != nextendrow)
186 endrow = nextendrow - 1;
188 QTextCursor c = QTextCursor(viewSourceTV->document());
189 c.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor, begrow);
190 c.select(QTextCursor::BlockUnderCursor);
191 c.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor,
192 endrow - begrow + 1);
193 viewSourceTV->setTextCursor(c);
197 void ViewSourceWidget::updateDefaultFormat()
202 outputFormatCO->blockSignals(true);
203 outputFormatCO->clear();
204 outputFormatCO->addItem(qt_("Default"),
205 QVariant(QString("default")));
208 vector<string> tmp = bv_->buffer().params().backends();
209 vector<string>::const_iterator it = tmp.begin();
210 vector<string>::const_iterator en = tmp.end();
211 for (; it != en; ++it) {
212 string const format = *it;
213 Format const * fmt = formats.getFormat(format);
215 LYXERR0("Can't find format for backend " << format << "!");
219 QString const pretty = qt_(fmt->prettyname());
220 QString const qformat = toqstr(format);
221 outputFormatCO->addItem(pretty, QVariant(qformat));
222 if (qformat == view_format_)
223 index = outputFormatCO->count() -1;
225 outputFormatCO->setCurrentIndex(index);
227 outputFormatCO->blockSignals(false);
231 void ViewSourceWidget::resizeEvent (QResizeEvent * event)
233 QSize const & formSize = formLayout->sizeHint();
234 // minimize the size of the part that contains the buttons
235 if (width() * formSize.height() < height() * formSize.width()) {
236 layout_->setDirection(QBoxLayout::TopToBottom);
238 layout_->setDirection(QBoxLayout::LeftToRight);
240 QWidget::resizeEvent(event);
244 GuiViewSource::GuiViewSource(GuiView & parent,
245 Qt::DockWidgetArea area, Qt::WindowFlags flags)
246 : DockView(parent, "view-source", qt_("LaTeX Source"), area, flags)
248 widget_ = new ViewSourceWidget;
253 GuiViewSource::~GuiViewSource()
259 void GuiViewSource::updateView()
261 if (widget_->autoUpdateCB->isChecked()) {
262 widget_->setBufferView(bufferview());
263 widget_->updateView();
265 widget_->masterPerspectiveCB->setEnabled(buffer().parent());
269 void GuiViewSource::enableView(bool enable)
271 widget_->setBufferView(bufferview());
272 widget_->updateDefaultFormat();
274 // In the opposite case, updateView() will be called anyway.
275 widget_->updateView();
279 bool GuiViewSource::initialiseParams(string const & /*source*/)
281 setWindowTitle(title());
286 QString GuiViewSource::title() const
290 return qt_("LaTeX Source");
292 return qt_("DocBook Source");
294 return qt_("Literate Source");
301 void GuiViewSource::saveSession() const
303 Dialog::saveSession();
306 // settings.setValue(
307 // sessionKey() + "/output", widget_->contentsCO->currentIndex());
309 sessionKey() + "/autoupdate", widget_->autoUpdateCB->isChecked());
313 void GuiViewSource::restoreSession()
315 DockView::restoreSession();
316 // FIXME: Full source updating is too slow to be done at startup.
317 //widget_->outputCO-setCurrentIndex(
318 // settings.value(sessionKey() + "/output", false).toInt());
319 widget_->contentsCO->setCurrentIndex(0);
321 widget_->autoUpdateCB->setChecked(
322 settings.value(sessionKey() + "/autoupdate", true).toBool());
323 widget_->updateView();
327 Dialog * createGuiViewSource(GuiView & lv)
329 return new GuiViewSource(lv);
333 } // namespace frontend
336 #include "moc_GuiViewSource.cpp"