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"
20 #include "BufferView.h"
24 #include "Paragraph.h"
27 #include "support/debug.h"
28 #include "support/lassert.h"
29 #include "support/docstream.h"
30 #include "support/gettext.h"
32 #include <boost/crc.hpp>
35 #include <QTextCursor>
36 #include <QTextDocument>
44 ViewSourceWidget::ViewSourceWidget()
45 : bv_(0), document_(new QTextDocument(this)),
46 highlighter_(new LaTeXHighlighter(document_)),
47 force_getcontent_(true)
51 connect(viewFullSourceCB, SIGNAL(clicked()),
52 this, SLOT(fullSourceChanged()));
53 connect(autoUpdateCB, SIGNAL(toggled(bool)),
54 updatePB, SLOT(setDisabled(bool)));
55 connect(autoUpdateCB, SIGNAL(toggled(bool)),
56 this, SLOT(updateView()));
57 connect(updatePB, SIGNAL(clicked()),
58 this, SLOT(updateView()));
59 connect(outputFormatCO, SIGNAL(activated(int)),
60 this, SLOT(updateView()));
62 // setting a document at this point trigger an assertion in Qt
63 // so we disable the signals here:
64 document_->blockSignals(true);
65 viewSourceTV->setDocument(document_);
66 document_->blockSignals(false);
67 viewSourceTV->setReadOnly(true);
68 ///dialog_->viewSourceTV->setAcceptRichText(false);
69 // this is personal. I think source code should be in fixed-size font
70 QFont font(guiApp->typewriterFontName());
71 font.setKerning(false);
72 font.setFixedPitch(true);
73 font.setStyleHint(QFont::TypeWriter);
74 viewSourceTV->setFont(font);
75 // again, personal taste
76 viewSourceTV->setWordWrapMode(QTextOption::NoWrap);
80 static size_t crcCheck(docstring const & s)
82 boost::crc_32_type crc;
83 crc.process_bytes(&s[0], sizeof(char_type) * s.size());
84 return crc.checksum();
88 /** get the source code of selected paragraphs, or the whole document
89 \param fullSource get full source code
90 \return true if the content has changed since last call.
92 static bool getContent(BufferView const * view, bool fullSource,
93 QString & qstr, string const format, bool force_getcontent)
95 // get the *top* level paragraphs that contain the cursor,
96 // or the selected text
100 if (!view->cursor().selection()) {
101 par_begin = view->cursor().bottom().pit();
104 par_begin = view->cursor().selectionBegin().bottom().pit();
105 par_end = view->cursor().selectionEnd().bottom().pit();
107 if (par_begin > par_end)
108 swap(par_begin, par_end);
109 odocstringstream ostr;
110 view->buffer().getSourceCode(ostr, format, par_begin, par_end + 1, fullSource);
111 docstring s = ostr.str();
112 static size_t crc = 0;
113 size_t newcrc = crcCheck(s);
114 if (newcrc == crc && !force_getcontent)
122 void ViewSourceWidget::setBufferView(BufferView const * bv)
125 force_getcontent_ = true;
127 setEnabled(bv ? true : false);
131 void ViewSourceWidget::fullSourceChanged()
133 if (autoUpdateCB->isChecked())
138 void ViewSourceWidget::updateView()
141 document_->setPlainText(QString());
148 string const format = fromqstr(outputFormatCO->itemData(
149 outputFormatCO->currentIndex()).toString());
152 if (getContent(bv_, viewFullSourceCB->isChecked(), content,
153 format, force_getcontent_))
154 document_->setPlainText(content);
156 CursorSlice beg = bv_->cursor().selectionBegin().bottom();
157 CursorSlice end = bv_->cursor().selectionEnd().bottom();
158 int const begrow = bv_->buffer().texrow().
159 getRowFromIdPos(beg.paragraph().id(), beg.pos());
160 int endrow = bv_->buffer().texrow().
161 getRowFromIdPos(end.paragraph().id(), end.pos());
162 int const nextendrow = bv_->buffer().texrow().
163 getRowFromIdPos(end.paragraph().id(), end.pos() + 1);
164 if (endrow != nextendrow)
165 endrow = nextendrow - 1;
167 QTextCursor c = QTextCursor(viewSourceTV->document());
168 c.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor, begrow);
169 c.select(QTextCursor::BlockUnderCursor);
170 c.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor,
171 endrow - begrow + 1);
172 viewSourceTV->setTextCursor(c);
176 void ViewSourceWidget::updateDefaultFormat()
181 outputFormatCO->blockSignals(true);
182 outputFormatCO->clear();
183 outputFormatCO->addItem(qt_("Default"),
184 QVariant(QString("default")));
185 typedef vector<Format const *> Formats;
186 Formats formats = bv_->buffer().exportableFormats(true);
187 Formats::const_iterator cit = formats.begin();
188 Formats::const_iterator end = formats.end();
189 for (; cit != end; ++cit)
190 outputFormatCO->addItem(qt_((*cit)->prettyname()),
191 QVariant(toqstr((*cit)->name())));
192 outputFormatCO->blockSignals(false);
196 GuiViewSource::GuiViewSource(GuiView & parent,
197 Qt::DockWidgetArea area, Qt::WindowFlags flags)
198 : DockView(parent, "view-source", qt_("LaTeX Source"), area, flags)
200 widget_ = new ViewSourceWidget();
205 GuiViewSource::~GuiViewSource()
211 void GuiViewSource::updateView()
213 if (widget_->autoUpdateCB->isChecked()) {
214 widget_->setBufferView(bufferview());
215 widget_->updateView();
220 void GuiViewSource::enableView(bool enable)
222 widget_->setBufferView(bufferview());
223 widget_->updateDefaultFormat();
225 // In the opposite case, updateView() will be called anyway.
226 widget_->updateView();
230 bool GuiViewSource::initialiseParams(string const & /*source*/)
232 setWindowTitle(title());
237 QString GuiViewSource::title() const
241 return qt_("LaTeX Source");
243 return qt_("DocBook Source");
245 return qt_("Literate Source");
247 LASSERT(false, /**/);
252 void GuiViewSource::saveSession() const
254 Dialog::saveSession();
257 sessionKey() + "/fullsource", widget_->viewFullSourceCB->isChecked());
259 sessionKey() + "/autoupdate", widget_->autoUpdateCB->isChecked());
263 void GuiViewSource::restoreSession()
265 DockView::restoreSession();
266 // FIXME: Full source updating is too slow to be done at startup.
267 //widget_->viewFullSourceCB->setChecked(
268 // settings.value(sessionKey() + "/fullsource", false).toBool());
269 widget_->viewFullSourceCB->setChecked(false);
271 widget_->autoUpdateCB->setChecked(
272 settings.value(sessionKey() + "/autoupdate", true).toBool());
273 widget_->updateView();
277 Dialog * createGuiViewSource(GuiView & lv)
279 return new GuiViewSource(lv);
283 } // namespace frontend
286 #include "moc_GuiViewSource.cpp"