#include "BufferView.h"
#include "Cursor.h"
#include "Format.h"
+#include "FuncRequest.h"
+#include "LyX.h"
#include "Paragraph.h"
+#include "TexRow.h"
#include "support/debug.h"
#include "support/lassert.h"
#include "support/docstream.h"
+#include "support/docstring_list.h"
#include "support/gettext.h"
#include <boost/crc.hpp>
namespace lyx {
namespace frontend {
-ViewSourceWidget::ViewSourceWidget()
- : bv_(0), document_(new QTextDocument(this)),
- highlighter_(new LaTeXHighlighter(document_)),
- update_timer_(new QTimer(this))
+ViewSourceWidget::ViewSourceWidget(QWidget * parent)
+ : QWidget(parent),
+ document_(new QTextDocument(this)),
+ highlighter_(new LaTeXHighlighter(document_))
{
setupUi(this);
connect(masterPerspectiveCB, SIGNAL(toggled(bool)),
this, SLOT(contentsChanged()));
connect(updatePB, SIGNAL(clicked()),
- this, SLOT(updateViewNow()));
+ this, SIGNAL(needUpdate()));
connect(outputFormatCO, SIGNAL(activated(int)),
this, SLOT(setViewFormat(int)));
- connect(outputFormatCO, SIGNAL(activated(int)),
- this, SLOT(contentsChanged()));
-
- // setting the update timer
- update_timer_->setSingleShot(true);
- connect(update_timer_, SIGNAL(timeout()),
- this, SLOT(realUpdateView()));
// setting a document at this point trigger an assertion in Qt
// so we disable the signals here:
viewSourceTV->setReadOnly(true);
///dialog_->viewSourceTV->setAcceptRichText(false);
// this is personal. I think source code should be in fixed-size font
- QFont font(guiApp->typewriterFontName());
- font.setFixedPitch(true);
- font.setStyleHint(QFont::TypeWriter);
- viewSourceTV->setFont(font);
+ viewSourceTV->setFont(guiApp->typewriterSystemFont());
// again, personal taste
viewSourceTV->setWordWrapMode(QTextOption::NoWrap);
+
+ // catch double click events
+ viewSourceTV->viewport()->installEventFilter(this);
}
-auto_ptr<TexRow> ViewSourceWidget::getContent(BufferView const * view,
+void ViewSourceWidget::getContent(BufferView const & view,
Buffer::OutputWhat output, docstring & str, string const & format,
bool master)
{
pit_type par_begin;
pit_type par_end;
- if (!view->cursor().selection()) {
- par_begin = view->cursor().bottom().pit();
+ 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();
+ 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;
- auto_ptr<TexRow> texrow = view->buffer().getSourceCode(ostr, format,
- par_begin, par_end + 1, output, master);
+ texrow_ = view.buffer()
+ .getSourceCode(ostr, format, par_begin, par_end + 1, output, master);
//ensure that the last line can always be selected in its full width
str = ostr.str() + "\n";
- return texrow;
-}
-
-
-void ViewSourceWidget::setBufferView(BufferView const * bv)
-{
- if (bv_ != bv) {
- setText();
- bv_ = bv;
- }
- setEnabled(bv ? true : false);
}
void ViewSourceWidget::contentsChanged()
{
if (autoUpdateCB->isChecked())
- updateViewNow();
+ Q_EMIT needUpdate();
}
void ViewSourceWidget::setViewFormat(int const index)
{
outputFormatCO->setCurrentIndex(index);
- view_format_ = outputFormatCO->itemData(index).toString();
+ string format = fromqstr(outputFormatCO->itemData(index).toString());
+ if (view_format_ != format) {
+ view_format_ = format;
+ Q_EMIT needUpdate();
+ }
}
-void ViewSourceWidget::updateView()
+int ViewSourceWidget::updateDelay() const
{
const int long_delay = 400;
const int short_delay = 60;
// a shorter delay if just the current paragraph is shown
- update_timer_->start((contentsCO->currentIndex() == 0) ?
- short_delay : long_delay);
+ return (contentsCO->currentIndex() == 0) ? short_delay : long_delay;
}
-void ViewSourceWidget::updateViewNow()
+
+void GuiViewSource::scheduleUpdate()
+{
+ update_timer_->start(widget_->updateDelay());
+}
+
+
+void GuiViewSource::scheduleUpdateNow()
{
update_timer_->start(0);
}
-void ViewSourceWidget::realUpdateView()
+
+void GuiViewSource::realUpdateView()
{
- if (!bv_) {
+ widget_->updateView(bufferview());
+ updateTitle();
+}
+
+
+void ViewSourceWidget::updateView(BufferView const * bv)
+{
+ if (!bv) {
setText();
setEnabled(false);
return;
// we will try to preserve this
int const h_scroll = viewSourceTV->horizontalScrollBar()->value();
- string const format = fromqstr(view_format_);
-
Buffer::OutputWhat output = Buffer::CurrentParagraph;
if (contentsCO->currentIndex() == 1)
output = Buffer::FullSource;
output = Buffer::OnlyBody;
docstring content;
- auto_ptr<TexRow> texrow = getContent(bv_, output, content, format,
- masterPerspectiveCB->isChecked());
+ getContent(*bv, output, content, view_format_,
+ masterPerspectiveCB->isChecked());
QString old = document_->toPlainText();
QString qcontent = toqstr(content);
+#ifdef DEVEL_VERSION
+ // output tex<->row correspondences in the source panel if the "-dbg latex"
+ // option is given.
+ if (texrow_ && lyx::lyxerr.debugging(Debug::LATEX)) {
+ QStringList list = qcontent.split(QChar('\n'));
+ docstring_list dlist;
+ for (QStringList::const_iterator it = list.begin(); it != list.end(); ++it)
+ dlist.push_back(from_utf8(fromqstr(*it)));
+ texrow_->prepend(dlist);
+ qcontent.clear();
+ for (docstring_list::iterator it = dlist.begin(); it != dlist.end(); ++it)
+ qcontent += toqstr(*it) + '\n';
+ }
+#endif
+ // prevent gotoCursor()
+ QSignalBlocker blocker(viewSourceTV);
bool const changed = setText(qcontent);
- if (changed && !texrow.get()) {
+ if (changed && !texrow_) {
// position-to-row is unavailable
// we jump to the first modification
- const QChar * oc = old.constData();
- const QChar * nc = qcontent.constData();
+ int length = min(old.length(), qcontent.length());
int pos = 0;
- while (*oc != '\0' && *nc != '\0' && *oc == *nc) {
- ++oc;
- ++nc;
- ++pos;
- }
+ for (; pos < length && old.at(pos) == qcontent.at(pos); ++pos) {}
QTextCursor c = QTextCursor(viewSourceTV->document());
//get some space below the cursor
c.setPosition(pos);
//c.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor,1);
viewSourceTV->setTextCursor(c);
- } else if (texrow.get()) {
+ } else if (texrow_) {
// Use the available position-to-row conversion to highlight
// the current selection in the source
- int beg_row, end_row;
- {
- DocIterator beg = bv_->cursor().selectionBegin();
- DocIterator end = bv_->cursor().selectionEnd();
- std::pair<int,int> beg_rows = texrow->rowFromDocIterator(beg);
- beg_row = beg_rows.first;
- if (beg != end) {
- end.backwardChar();
- std::pair<int,int> end_rows = texrow->rowFromDocIterator(end);
- end_row = end_rows.second;
- } else {
- end_row = beg_rows.second;
- }
- }
+ std::pair<int,int> rows = texrow_->rowFromCursor(bv->cursor());
+ int const beg_row = rows.first;
+ int const end_row = rows.second;
QTextCursor c = QTextCursor(viewSourceTV->document());
//the real highlighting is done with an ExtraSelection
QTextCharFormat format;
+ {
+ // We create a new color with the lightness of AlternateBase and
+ // the hue and saturation of Highlight
QPalette palette = viewSourceTV->palette();
- //Alternative:
- // QColor bg = palette.color(QPalette::Active,QPalette::Highlight);
- // bg.setAlpha(64);
- // format.setBackground(QBrush(bg));
- //Other alternatives:
- //format.setBackground(palette.light());
- //format.setBackground(palette.alternateBase());
- format.setBackground(palette.toolTipBase());
+ QBrush alt = palette.alternateBase();
+ QColor high = palette.highlight().color().toHsl();
+ QColor col = QColor::fromHsl(high.hue(),
+ high.hslSaturation(),
+ alt.color().lightness());
+ alt.setColor(col);
+ format.setBackground(alt);
+ }
format.setProperty(QTextFormat::FullWidthSelection, true);
QTextEdit::ExtraSelection sel;
sel.format = format;
}
-void ViewSourceWidget::updateDefaultFormat()
+docstring ViewSourceWidget::currentFormatName(BufferView const * bv) const
{
- if (!bv_)
+ // Compute the actual format used
+ string const format = !bv ? ""
+ : flavor2format(bv->buffer().params().getOutputFlavor(view_format_));
+ Format const * f = formats.getFormat(format.empty() ? view_format_ : format);
+ return f ? f->prettyname() : from_utf8(view_format_);
+}
+
+
+bool ViewSourceWidget::eventFilter(QObject * obj, QEvent * ev)
+{
+ // this event filter is installed on the viewport of the QTextView
+ if (obj == viewSourceTV->viewport() &&
+ ev->type() == QEvent::MouseButtonDblClick) {
+ goToCursor();
+ return true;
+ }
+ return false;
+}
+
+
+void ViewSourceWidget::goToCursor() const
+{
+ if (!texrow_)
return;
+ int row = viewSourceTV->textCursor().blockNumber() + 1;
+ dispatch(texrow_->goToFuncFromRow(row));
+}
+
- outputFormatCO->blockSignals(true);
+
+void ViewSourceWidget::updateDefaultFormat(BufferView const & bv)
+{
+ QSignalBlocker blocker(outputFormatCO);
outputFormatCO->clear();
outputFormatCO->addItem(qt_("Default"),
QVariant(QString("default")));
int index = 0;
- vector<string> tmp = bv_->buffer().params().backends();
+ vector<string> tmp = bv.buffer().params().backends();
vector<string>::const_iterator it = tmp.begin();
vector<string>::const_iterator en = tmp.end();
for (; it != en; ++it) {
continue;
}
- QString const pretty = qt_(fmt->prettyname());
- QString const qformat = toqstr(format);
- outputFormatCO->addItem(pretty, QVariant(qformat));
- if (qformat == view_format_)
+ QString const pretty = toqstr(translateIfPossible(fmt->prettyname()));
+ outputFormatCO->addItem(pretty, QVariant(toqstr(format)));
+ if (format == view_format_)
index = outputFormatCO->count() -1;
}
setViewFormat(index);
-
- outputFormatCO->blockSignals(false);
}
void ViewSourceWidget::saveSession(QString const & session_key) const
{
QSettings settings;
- settings.setValue(session_key + "/output", view_format_);
+ settings.setValue(session_key + "/output", toqstr(view_format_));
settings.setValue(session_key + "/contents", contentsCO->currentIndex());
settings.setValue(session_key + "/autoupdate", autoUpdateCB->isChecked());
settings.setValue(session_key + "/masterview",
void ViewSourceWidget::restoreSession(QString const & session_key)
{
QSettings settings;
- view_format_ = settings.value(session_key + "/output", 0).toString();
+ view_format_ = fromqstr(settings.value(session_key + "/output", 0)
+ .toString());
contentsCO->setCurrentIndex(settings
.value(session_key + "/contents", 0)
.toInt());
.toBool();
autoUpdateCB->setChecked(checked);
if (checked)
- updateView();
+ Q_EMIT needUpdate();
}
GuiViewSource::GuiViewSource(GuiView & parent,
Qt::DockWidgetArea area, Qt::WindowFlags flags)
- : DockView(parent, "view-source", qt_("LaTeX Source"), area, flags)
+ : DockView(parent, "view-source", qt_("Code Preview"), area, flags),
+ widget_(new ViewSourceWidget(this)),
+ update_timer_(new QTimer(this))
{
- widget_ = new ViewSourceWidget;
setWidget(widget_);
+
+ // setting the update timer
+ update_timer_->setSingleShot(true);
+ connect(update_timer_, SIGNAL(timeout()),
+ this, SLOT(realUpdateView()));
+
+ connect(widget_, SIGNAL(needUpdate()), this, SLOT(scheduleUpdateNow()));
}
-GuiViewSource::~GuiViewSource()
+void GuiViewSource::onBufferViewChanged()
{
- delete widget_;
+ widget_->setText();
+ widget_->setEnabled((bool)bufferview());
}
void GuiViewSource::updateView()
{
if (widget_->autoUpdateCB->isChecked()) {
- widget_->setBufferView(bufferview());
- widget_->updateView();
+ widget_->setEnabled((bool)bufferview());
+ scheduleUpdate();
}
widget_->masterPerspectiveCB->setEnabled(buffer().parent());
+ updateTitle();
}
void GuiViewSource::enableView(bool enable)
{
- widget_->setBufferView(bufferview());
- widget_->updateDefaultFormat();
+ widget_->setEnabled((bool)bufferview());
+ if (bufferview())
+ widget_->updateDefaultFormat(*bufferview());
if (!enable)
// In the opposite case, updateView() will be called anyway.
widget_->contentsChanged();
bool GuiViewSource::initialiseParams(string const & /*source*/)
{
- setWindowTitle(title());
+ updateTitle();
return true;
}
-QString GuiViewSource::title() const
+void GuiViewSource::updateTitle()
{
- switch (docType()) {
- case LATEX:
- //FIXME: this is shown for LyXHTML source, LyX source, etc.
- return qt_("LaTeX Source");
- case DOCBOOK:
- return qt_("DocBook Source");
- case LITERATE:
- return qt_("Literate Source");
- }
- LATTEST(false);
- return QString();
+ docstring const format = widget_->currentFormatName(bufferview());
+ QString const title = format.empty() ? qt_("Code Preview")
+ : qt_("%1[[preview format name]] Preview")
+ .arg(toqstr(translateIfPossible(format)));
+ setTitle(title);
+ setWindowTitle(title);
}