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(viewFullSourceCB, SIGNAL(clicked()),
53 this, SLOT(fullSourceChanged()));
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, bool fullSource,
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, fullSource);
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::fullSourceChanged()
134 if (autoUpdateCB->isChecked())
139 void ViewSourceWidget::updateView()
142 document_->setPlainText(QString());
149 string const format = fromqstr(outputFormatCO->itemData(
150 outputFormatCO->currentIndex()).toString());
153 if (getContent(bv_, viewFullSourceCB->isChecked(), content,
154 format, force_getcontent_))
155 document_->setPlainText(content);
157 CursorSlice beg = bv_->cursor().selectionBegin().bottom();
158 CursorSlice end = bv_->cursor().selectionEnd().bottom();
159 int const begrow = bv_->buffer().texrow().
160 getRowFromIdPos(beg.paragraph().id(), beg.pos());
161 int endrow = bv_->buffer().texrow().
162 getRowFromIdPos(end.paragraph().id(), end.pos());
163 int const nextendrow = bv_->buffer().texrow().
164 getRowFromIdPos(end.paragraph().id(), end.pos() + 1);
165 if (endrow != nextendrow)
166 endrow = nextendrow - 1;
168 QTextCursor c = QTextCursor(viewSourceTV->document());
169 c.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor, begrow);
170 c.select(QTextCursor::BlockUnderCursor);
171 c.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor,
172 endrow - begrow + 1);
173 viewSourceTV->setTextCursor(c);
177 void ViewSourceWidget::updateDefaultFormat()
182 outputFormatCO->blockSignals(true);
183 outputFormatCO->clear();
184 outputFormatCO->addItem(qt_("Default"),
185 QVariant(QString("default")));
186 typedef vector<Format const *> Formats;
187 Formats formats = bv_->buffer().params().exportableFormats(true);
188 Formats::const_iterator cit = formats.begin();
189 Formats::const_iterator end = formats.end();
190 for (; cit != end; ++cit)
191 outputFormatCO->addItem(qt_((*cit)->prettyname()),
192 QVariant(toqstr((*cit)->name())));
193 outputFormatCO->blockSignals(false);
197 GuiViewSource::GuiViewSource(GuiView & parent,
198 Qt::DockWidgetArea area, Qt::WindowFlags flags)
199 : DockView(parent, "view-source", qt_("LaTeX Source"), area, flags)
201 widget_ = new ViewSourceWidget();
206 GuiViewSource::~GuiViewSource()
212 void GuiViewSource::updateView()
214 if (widget_->autoUpdateCB->isChecked()) {
215 widget_->setBufferView(bufferview());
216 widget_->updateView();
221 void GuiViewSource::enableView(bool enable)
223 widget_->setBufferView(bufferview());
224 widget_->updateDefaultFormat();
226 // In the opposite case, updateView() will be called anyway.
227 widget_->updateView();
231 bool GuiViewSource::initialiseParams(string const & /*source*/)
233 setWindowTitle(title());
238 QString GuiViewSource::title() const
242 return qt_("LaTeX Source");
244 return qt_("DocBook Source");
246 return qt_("Literate Source");
248 LASSERT(false, /**/);
253 void GuiViewSource::saveSession() const
255 Dialog::saveSession();
258 sessionKey() + "/fullsource", widget_->viewFullSourceCB->isChecked());
260 sessionKey() + "/autoupdate", widget_->autoUpdateCB->isChecked());
264 void GuiViewSource::restoreSession()
266 DockView::restoreSession();
267 // FIXME: Full source updating is too slow to be done at startup.
268 //widget_->viewFullSourceCB->setChecked(
269 // settings.value(sessionKey() + "/fullsource", false).toBool());
270 widget_->viewFullSourceCB->setChecked(false);
272 widget_->autoUpdateCB->setChecked(
273 settings.value(sessionKey() + "/autoupdate", true).toBool());
274 widget_->updateView();
278 Dialog * createGuiViewSource(GuiView & lv)
280 return new GuiViewSource(lv);
284 } // namespace frontend
287 #include "moc_GuiViewSource.cpp"