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::dockLocationChanged(Qt::DockWidgetArea area)
233 if (area == Qt::RightDockWidgetArea || area == Qt::LeftDockWidgetArea) {
234 layout_->setDirection(QBoxLayout::TopToBottom);
236 layout_->setDirection(QBoxLayout::LeftToRight);
241 GuiViewSource::GuiViewSource(GuiView & parent,
242 Qt::DockWidgetArea area, Qt::WindowFlags flags)
243 : DockView(parent, "view-source", qt_("LaTeX Source"), area, flags)
245 widget_ = new ViewSourceWidget;
247 connect(this, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)),
248 widget_, SLOT(dockLocationChanged(Qt::DockWidgetArea)));
252 GuiViewSource::~GuiViewSource()
258 void GuiViewSource::updateView()
260 if (widget_->autoUpdateCB->isChecked()) {
261 widget_->setBufferView(bufferview());
262 widget_->updateView();
264 widget_->masterPerspectiveCB->setEnabled(buffer().parent());
268 void GuiViewSource::enableView(bool enable)
270 widget_->setBufferView(bufferview());
271 widget_->updateDefaultFormat();
273 // In the opposite case, updateView() will be called anyway.
274 widget_->updateView();
278 bool GuiViewSource::initialiseParams(string const & /*source*/)
280 setWindowTitle(title());
285 QString GuiViewSource::title() const
289 return qt_("LaTeX Source");
291 return qt_("DocBook Source");
293 return qt_("Literate Source");
300 void GuiViewSource::saveSession() const
302 Dialog::saveSession();
305 // settings.setValue(
306 // sessionKey() + "/output", widget_->contentsCO->currentIndex());
308 sessionKey() + "/autoupdate", widget_->autoUpdateCB->isChecked());
312 void GuiViewSource::restoreSession()
314 DockView::restoreSession();
315 // FIXME: Full source updating is too slow to be done at startup.
316 //widget_->outputCO-setCurrentIndex(
317 // settings.value(sessionKey() + "/output", false).toInt());
318 widget_->contentsCO->setCurrentIndex(0);
320 widget_->autoUpdateCB->setChecked(
321 settings.value(sessionKey() + "/autoupdate", true).toBool());
322 widget_->updateView();
326 Dialog * createGuiViewSource(GuiView & lv)
328 return new GuiViewSource(lv);
332 } // namespace frontend
335 #include "moc_GuiViewSource.cpp"