X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ffrontends%2Fqt4%2FGuiViewSource.cpp;h=a5beae5da691e673c05fa55d77e9ae9274527128;hb=425d092204118ea6c24c28e85fdf03fcf2bb51a4;hp=0a6d13544f22d8af551f98904c1b6244abe1a7f2;hpb=9a95d2a936748c057db94a3083c4b9e6587eea0b;p=lyx.git diff --git a/src/frontends/qt4/GuiViewSource.cpp b/src/frontends/qt4/GuiViewSource.cpp index 0a6d13544f..a5beae5da6 100644 --- a/src/frontends/qt4/GuiViewSource.cpp +++ b/src/frontends/qt4/GuiViewSource.cpp @@ -12,44 +12,58 @@ #include +#include "GuiApplication.h" #include "GuiViewSource.h" +#include "LaTeXHighlighter.h" #include "qt_helpers.h" -#include +#include "BufferView.h" +#include "Buffer.h" +#include "Cursor.h" +#include "Paragraph.h" +#include "TexRow.h" +#include "support/debug.h" +#include "support/lassert.h" +#include "support/docstream.h" +#include "support/gettext.h" + +#include + +#include #include #include +#include + +using namespace std; namespace lyx { namespace frontend { -///////////////////////////////////////////////////////////////////// -// -// GuiViewSourceDialog -// -///////////////////////////////////////////////////////////////////// - -GuiViewSourceDialog::GuiViewSourceDialog(GuiViewSource * form) - : form_(form) +ViewSourceWidget::ViewSourceWidget() + : bv_(0), document_(new QTextDocument(this)), + highlighter_(new LaTeXHighlighter(document_)) { setupUi(this); connect(viewFullSourceCB, SIGNAL(clicked()), - this, SLOT(update())); + this, SLOT(updateView())); connect(autoUpdateCB, SIGNAL(toggled(bool)), updatePB, SLOT(setDisabled(bool))); + connect(autoUpdateCB, SIGNAL(toggled(bool)), + this, SLOT(updateView())); connect(updatePB, SIGNAL(clicked()), - this, SLOT(update())); + this, SLOT(updateView())); // setting a document at this point trigger an assertion in Qt // so we disable the signals here: - form_->document()->blockSignals(true); - viewSourceTV->setDocument(form_->document()); - form_->document()->blockSignals(false); + document_->blockSignals(true); + viewSourceTV->setDocument(document_); + document_->blockSignals(false); viewSourceTV->setReadOnly(true); ///dialog_->viewSourceTV->setAcceptRichText(false); // this is personal. I think source code should be in fixed-size font - QFont font(toqstr(theApp()->typewriterFontName())); + QFont font(guiApp->typewriterFontName()); font.setKerning(false); font.setFixedPitch(true); font.setStyleHint(QFont::TypeWriter); @@ -59,128 +73,175 @@ GuiViewSourceDialog::GuiViewSourceDialog(GuiViewSource * form) } -void GuiViewSourceDialog::updateView() +static size_t crcCheck(docstring const & s) +{ + boost::crc_32_type crc; + crc.process_bytes(&s[0], sizeof(char_type) * s.size()); + return crc.checksum(); +} + + +/** get the source code of selected paragraphs, or the whole document + \param fullSource get full source code + \return true if the content has changed since last call. + */ +static bool getContent(BufferView const * view, bool fullSource, QString & qstr) +{ + // get the *top* level paragraphs that contain the cursor, + // or the selected text + pit_type par_begin; + pit_type par_end; + + if (!view->cursor().selection()) { + par_begin = view->cursor().bottom().pit(); + par_end = par_begin; + } else { + par_begin = view->cursor().selectionBegin().bottom().pit(); + par_end = view->cursor().selectionEnd().bottom().pit(); + } + if (par_begin > par_end) + swap(par_begin, par_end); + odocstringstream ostr; + view->buffer().getSourceCode(ostr, par_begin, par_end + 1, fullSource); + docstring s = ostr.str(); + static size_t crc = 0; + size_t newcrc = crcCheck(s); + if (newcrc == crc) + return false; + crc = newcrc; + qstr = toqstr(s); + return true; +} + + +void ViewSourceWidget::setBufferView(BufferView const * bv) { - if (autoUpdateCB->isChecked()) - form_->update(viewFullSourceCB->isChecked()); + bv_ = bv; + setEnabled(bv ? true : false); +} + + +void ViewSourceWidget::updateView() +{ + if (!bv_) { + document_->setPlainText(QString()); + setEnabled(false); + return; + } + + setEnabled(true); + + QString content; + if (getContent(bv_, viewFullSourceCB->isChecked(), content)) + document_->setPlainText(content); + + CursorSlice beg = bv_->cursor().selectionBegin().bottom(); + CursorSlice end = bv_->cursor().selectionEnd().bottom(); + int const begrow = bv_->buffer().texrow(). + getRowFromIdPos(beg.paragraph().id(), beg.pos()); + int endrow = bv_->buffer().texrow(). + getRowFromIdPos(end.paragraph().id(), end.pos()); + int const nextendrow = bv_->buffer().texrow(). + getRowFromIdPos(end.paragraph().id(), end.pos() + 1); + if (endrow != nextendrow) + endrow = nextendrow - 1; - int beg, end; - boost::tie(beg, end) = form_->getRows(); QTextCursor c = QTextCursor(viewSourceTV->document()); - c.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor, beg); + c.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor, begrow); c.select(QTextCursor::BlockUnderCursor); - c.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor, end - beg + 1); + c.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor, + endrow - begrow + 1); viewSourceTV->setTextCursor(c); - QWidget::update(); } -///////////////////////////////////////////////////////////////////// -// -// LaTeXHighlighter -// -///////////////////////////////////////////////////////////////////// +GuiViewSource::GuiViewSource(GuiView & parent, + Qt::DockWidgetArea area, Qt::WindowFlags flags) + : DockView(parent, "view-source", qt_("LaTeX Source"), area, flags) +{ + widget_ = new ViewSourceWidget(); + setWidget(widget_); +} -LaTeXHighlighter::LaTeXHighlighter(QTextDocument * parent) - : QSyntaxHighlighter(parent) +GuiViewSource::~GuiViewSource() { - keywordFormat.setForeground(Qt::darkBlue); - keywordFormat.setFontWeight(QFont::Bold); - commentFormat.setForeground(Qt::darkGray); - mathFormat.setForeground(Qt::red); + delete widget_; } -void LaTeXHighlighter::highlightBlock(QString const & text) +void GuiViewSource::updateView() { - // $ $ - QRegExp exprMath("\\$[^\\$]*\\$"); - int index = text.indexOf(exprMath); - while (index >= 0) { - int length = exprMath.matchedLength(); - setFormat(index, length, mathFormat); - index = text.indexOf(exprMath, index + length); - } - // [ ] - QRegExp exprStartDispMath("(\\\\\\[|" - "\\\\begin\\{equation\\**\\}|" - "\\\\begin\\{eqnarray\\**\\}|" - "\\\\begin\\{align(ed|at)*\\**\\}|" - "\\\\begin\\{flalign\\**\\}|" - "\\\\begin\\{gather\\**\\}|" - "\\\\begin\\{multline\\**\\}|" - "\\\\begin\\{array\\**\\}|" - "\\\\begin\\{cases\\**\\}" - ")"); - QRegExp exprEndDispMath("(\\\\\\]|" - "\\\\end\\{equation\\**\\}|" - "\\\\end\\{eqnarray\\**\\}|" - "\\\\end\\{align(ed|at)*\\**\\}|" - "\\\\end\\{flalign\\**\\}|" - "\\\\end\\{gather\\**\\}|" - "\\\\end\\{multline\\**\\}|" - "\\\\end\\{array\\**\\}|" - "\\\\end\\{cases\\**\\}" - ")"); - int startIndex = 0; - // if previous block was in 'disp math' - // start search from 0 (for end disp math) - // otherwise, start search from 'begin disp math' - if (previousBlockState() != 1) - startIndex = text.indexOf(exprStartDispMath); - while (startIndex >= 0) { - int endIndex = text.indexOf(exprEndDispMath, startIndex); - int length; - if (endIndex == -1) { - setCurrentBlockState(1); - length = text.length() - startIndex; - } else { - length = endIndex - startIndex + exprEndDispMath.matchedLength(); - } - setFormat(startIndex, length, mathFormat); - startIndex = text.indexOf(exprStartDispMath, startIndex + length); + if (widget_->autoUpdateCB->isChecked()) { + widget_->setBufferView(bufferview()); + widget_->updateView(); } - // \whatever - QRegExp exprKeyword("\\\\[A-Za-z]+"); - index = text.indexOf(exprKeyword); - while (index >= 0) { - int length = exprKeyword.matchedLength(); - setFormat(index, length, keywordFormat); - index = text.indexOf(exprKeyword, index + length); - } - // comment - QRegExp exprComment("(^|[^\\\\])%.*$"); - index = text.indexOf(exprComment); - while (index >= 0) { - int const length = exprComment.matchedLength(); - setFormat(index, length, commentFormat); - index = text.indexOf(exprComment, index + length); +} + + +void GuiViewSource::enableView(bool enable) +{ + widget_->setBufferView(bufferview()); + if (!enable) + // In the opposite case, updateView() will be called anyway. + widget_->updateView(); +} + + +bool GuiViewSource::initialiseParams(string const & /*source*/) +{ + setWindowTitle(title()); + return true; +} + + +QString GuiViewSource::title() const +{ + switch (docType()) { + case LATEX: + return qt_("LaTeX Source"); + case DOCBOOK: + return qt_("DocBook Source"); + case LITERATE: + return qt_("Literate Source"); } + LASSERT(false, /**/); + return QString(); } -GuiViewSource::GuiViewSource(GuiDialog & parent) - : ControlViewSource(parent) +void GuiViewSource::saveSession() const { - document_ = new QTextDocument(this); - highlighter_ = new LaTeXHighlighter(document_); + Dialog::saveSession(); + QSettings settings; + settings.setValue( + sessionKey() + "/fullsource", widget_->viewFullSourceCB->isChecked()); + settings.setValue( + sessionKey() + "/autoupdate", widget_->autoUpdateCB->isChecked()); } -///////////////////////////////////////////////////////////////////// -// -// GuiViewSource -// -///////////////////////////////////////////////////////////////////// +void GuiViewSource::restoreSession() +{ + DockView::restoreSession(); + // FIXME: Full source updating is too slow to be done at startup. + //widget_->viewFullSourceCB->setChecked( + // settings.value(sessionKey() + "/fullsource", false).toBool()); + widget_->viewFullSourceCB->setChecked(false); + QSettings settings; + widget_->autoUpdateCB->setChecked( + settings.value(sessionKey() + "/autoupdate", true).toBool()); + widget_->updateView(); +} + -void GuiViewSource::update(bool full_source) +Dialog * createGuiViewSource(GuiView & lv) { - document_->setPlainText(toqstr(updateContent(full_source))); + return new GuiViewSource(lv); } } // namespace frontend } // namespace lyx -#include "GuiViewSource_moc.cpp" +#include "moc_GuiViewSource.cpp"