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 << "!");
212 if (fmt->name() == "lyx")
213 // we can't presently display the LyX format itself
216 QString const pretty = qt_(fmt->prettyname());
217 QString const qformat = toqstr(format);
218 outputFormatCO->addItem(pretty, QVariant(qformat));
219 if (qformat == view_format_)
220 index = outputFormatCO->count() -1;
222 outputFormatCO->setCurrentIndex(index);
224 outputFormatCO->blockSignals(false);
228 GuiViewSource::GuiViewSource(GuiView & parent,
229 Qt::DockWidgetArea area, Qt::WindowFlags flags)
230 : DockView(parent, "view-source", qt_("LaTeX Source"), area, flags)
232 widget_ = new ViewSourceWidget();
237 GuiViewSource::~GuiViewSource()
243 void GuiViewSource::updateView()
245 if (widget_->autoUpdateCB->isChecked()) {
246 widget_->setBufferView(bufferview());
247 widget_->updateView();
252 void GuiViewSource::enableView(bool enable)
254 widget_->setBufferView(bufferview());
255 widget_->updateDefaultFormat();
257 // In the opposite case, updateView() will be called anyway.
258 widget_->updateView();
262 bool GuiViewSource::initialiseParams(string const & /*source*/)
264 setWindowTitle(title());
269 QString GuiViewSource::title() const
273 return qt_("LaTeX Source");
275 return qt_("DocBook Source");
277 return qt_("Literate Source");
279 LASSERT(false, /**/);
284 void GuiViewSource::saveSession() const
286 Dialog::saveSession();
289 // settings.setValue(
290 // sessionKey() + "/output", widget_->contentsCO->currentIndex());
292 sessionKey() + "/autoupdate", widget_->autoUpdateCB->isChecked());
296 void GuiViewSource::restoreSession()
298 DockView::restoreSession();
299 // FIXME: Full source updating is too slow to be done at startup.
300 //widget_->outputCO-setCurrentIndex(
301 // settings.value(sessionKey() + "/output", false).toInt());
302 widget_->contentsCO->setCurrentIndex(0);
304 widget_->autoUpdateCB->setChecked(
305 settings.value(sessionKey() + "/autoupdate", true).toBool());
306 widget_->updateView();
310 Dialog * createGuiViewSource(GuiView & lv)
312 return new GuiViewSource(lv);
316 } // namespace frontend
319 #include "moc_GuiViewSource.cpp"