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(updateView()));
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::updateView()
142 document_->setPlainText(QString());
149 string const format = fromqstr(outputFormatCO->itemData(
150 outputFormatCO->currentIndex()).toString());
153 Buffer::OutputWhat output = Buffer::CurrentParagraph;
154 if (contentsCO->currentIndex() == 1)
155 output = Buffer::FullSource;
156 else if (contentsCO->currentIndex() == 2)
157 output = Buffer::OnlyPreamble;
158 else if (contentsCO->currentIndex() == 3)
159 output = Buffer::OnlyBody;
161 if (getContent(bv_, output, content, format, force_getcontent_))
162 document_->setPlainText(content);
164 CursorSlice beg = bv_->cursor().selectionBegin().bottom();
165 CursorSlice end = bv_->cursor().selectionEnd().bottom();
166 int const begrow = bv_->buffer().texrow().
167 getRowFromIdPos(beg.paragraph().id(), beg.pos());
168 int endrow = bv_->buffer().texrow().
169 getRowFromIdPos(end.paragraph().id(), end.pos());
170 int const nextendrow = bv_->buffer().texrow().
171 getRowFromIdPos(end.paragraph().id(), end.pos() + 1);
172 if (endrow != nextendrow)
173 endrow = nextendrow - 1;
175 QTextCursor c = QTextCursor(viewSourceTV->document());
176 c.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor, begrow);
177 c.select(QTextCursor::BlockUnderCursor);
178 c.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor,
179 endrow - begrow + 1);
180 viewSourceTV->setTextCursor(c);
184 void ViewSourceWidget::updateDefaultFormat()
189 outputFormatCO->blockSignals(true);
190 outputFormatCO->clear();
191 outputFormatCO->addItem(qt_("Default"),
192 QVariant(QString("default")));
193 typedef vector<Format const *> Formats;
194 Formats formats = bv_->buffer().params().exportableFormats(true);
195 Formats::const_iterator cit = formats.begin();
196 Formats::const_iterator end = formats.end();
197 for (; cit != end; ++cit)
198 outputFormatCO->addItem(qt_((*cit)->prettyname()),
199 QVariant(toqstr((*cit)->name())));
200 outputFormatCO->blockSignals(false);
204 GuiViewSource::GuiViewSource(GuiView & parent,
205 Qt::DockWidgetArea area, Qt::WindowFlags flags)
206 : DockView(parent, "view-source", qt_("LaTeX Source"), area, flags)
208 widget_ = new ViewSourceWidget();
213 GuiViewSource::~GuiViewSource()
219 void GuiViewSource::updateView()
221 if (widget_->autoUpdateCB->isChecked()) {
222 widget_->setBufferView(bufferview());
223 widget_->updateView();
228 void GuiViewSource::enableView(bool enable)
230 widget_->setBufferView(bufferview());
231 widget_->updateDefaultFormat();
233 // In the opposite case, updateView() will be called anyway.
234 widget_->updateView();
238 bool GuiViewSource::initialiseParams(string const & /*source*/)
240 setWindowTitle(title());
245 QString GuiViewSource::title() const
249 return qt_("LaTeX Source");
251 return qt_("DocBook Source");
253 return qt_("Literate Source");
255 LASSERT(false, /**/);
260 void GuiViewSource::saveSession() const
262 Dialog::saveSession();
265 // settings.setValue(
266 // sessionKey() + "/output", widget_->contentsCO->currentIndex());
268 sessionKey() + "/autoupdate", widget_->autoUpdateCB->isChecked());
272 void GuiViewSource::restoreSession()
274 DockView::restoreSession();
275 // FIXME: Full source updating is too slow to be done at startup.
276 //widget_->outputCO-setCurrentIndex(
277 // settings.value(sessionKey() + "/output", false).toInt());
278 widget_->contentsCO->setCurrentIndex(0);
280 widget_->autoUpdateCB->setChecked(
281 settings.value(sessionKey() + "/autoupdate", true).toBool());
282 widget_->updateView();
286 Dialog * createGuiViewSource(GuiView & lv)
288 return new GuiViewSource(lv);
292 } // namespace frontend
295 #include "moc_GuiViewSource.cpp"