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")));
201 typedef vector<Format const *> Formats;
202 Formats formats = bv_->buffer().params().exportableFormats(true);
203 Formats::const_iterator cit = formats.begin();
204 Formats::const_iterator end = formats.end();
205 for (; cit != end; ++cit) {
206 QString const fname = toqstr((*cit)->name());
207 outputFormatCO->addItem(qt_((*cit)->prettyname()),
209 if (fname == view_format_)
210 index = outputFormatCO->count() -1;
212 outputFormatCO->setCurrentIndex(index);
213 outputFormatCO->blockSignals(false);
217 GuiViewSource::GuiViewSource(GuiView & parent,
218 Qt::DockWidgetArea area, Qt::WindowFlags flags)
219 : DockView(parent, "view-source", qt_("LaTeX Source"), area, flags)
221 widget_ = new ViewSourceWidget();
226 GuiViewSource::~GuiViewSource()
232 void GuiViewSource::updateView()
234 if (widget_->autoUpdateCB->isChecked()) {
235 widget_->setBufferView(bufferview());
236 widget_->updateView();
241 void GuiViewSource::enableView(bool enable)
243 widget_->setBufferView(bufferview());
244 widget_->updateDefaultFormat();
246 // In the opposite case, updateView() will be called anyway.
247 widget_->updateView();
251 bool GuiViewSource::initialiseParams(string const & /*source*/)
253 setWindowTitle(title());
258 QString GuiViewSource::title() const
262 return qt_("LaTeX Source");
264 return qt_("DocBook Source");
266 return qt_("Literate Source");
268 LASSERT(false, /**/);
273 void GuiViewSource::saveSession() const
275 Dialog::saveSession();
278 // settings.setValue(
279 // sessionKey() + "/output", widget_->contentsCO->currentIndex());
281 sessionKey() + "/autoupdate", widget_->autoUpdateCB->isChecked());
285 void GuiViewSource::restoreSession()
287 DockView::restoreSession();
288 // FIXME: Full source updating is too slow to be done at startup.
289 //widget_->outputCO-setCurrentIndex(
290 // settings.value(sessionKey() + "/output", false).toInt());
291 widget_->contentsCO->setCurrentIndex(0);
293 widget_->autoUpdateCB->setChecked(
294 settings.value(sessionKey() + "/autoupdate", true).toBool());
295 widget_->updateView();
299 Dialog * createGuiViewSource(GuiView & lv)
301 return new GuiViewSource(lv);
305 } // namespace frontend
308 #include "moc_GuiViewSource.cpp"