view-source feature, from Bo Peng <ben.bob@gmail.com>

* src/buffer.h buffer.C - getSourceCode()
	* src/lyxfunc.C -  open view-source dialog
	* src/text3.C - change LFUN_MOUSE_RELEASE
	* src/output_linuxdoc.C, src/output_docbook.C, src/output_latex.C 
		- intercept output
	* src/outputparams.h, outputparams.C - add par_begin, par_end, dryrun
	* src/insets/insetgraphics.C  - add dryrun mode of file conversion
	* lib/ui/stdmenus.ui - add view-source menu item under view
	* Add view-source dialog, add 
	    src/frontends/qt2/QViewSourceDialog.h, QViewSource.C, QViewSource.h, QViewSourceDialog.C
	    src/frontends/qt2/ui/QViewSourceDialogBase.ui
	    src/frontends/controllers/ControlViewSource.h ControlViewSource.C
	  modify
	    src/frontends/qt2/Makefile.dialogs, Makefile.am, Dialogs.C,
	    src/frontends/controllers/Makefile.am, po.POTFILES.in


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@13610 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Bo Peng 2006-04-09 02:48:54 +00:00
parent 618ca28af6
commit eb485caa96
23 changed files with 562 additions and 3 deletions

View File

@ -217,6 +217,7 @@ Menuset
# Item "Close All Footnotes|C" "close-footnotes"
Item "Display Tooltips|i" "toggle-tooltips"
Separator
Item "View source|s" "dialog-show view-source"
Submenu "Update|U" "document_update"
ViewFormats
Separator

View File

@ -26,6 +26,7 @@ src/frontends/controllers/ControlExternal.C
src/frontends/controllers/ControlGraphics.C
src/frontends/controllers/ControlInclude.C
src/frontends/controllers/ControlLog.C
src/frontends/controllers/ControlViewSource.C
src/frontends/controllers/ControlPrefs.C
src/frontends/controllers/ControlPrint.C
src/frontends/controllers/ControlSpellchecker.C

View File

@ -64,6 +64,7 @@
#include "graphics/Previews.h"
#include "support/types.h"
#include "support/lyxalgo.h"
#include "support/filetools.h"
#include "support/fs_extras.h"
@ -1575,3 +1576,40 @@ void Buffer::changeRefsIfUnique(string const & from, string const & to)
}
}
}
void Buffer::getSourceCode(ostream& os, lyx::pit_type par_begin, lyx::pit_type par_end)
{
OutputParams runparams;
runparams.nice = true;
runparams.flavor = OutputParams::LATEX;
runparams.linelen = lyxrc.ascii_linelen;
runparams.par_begin = par_begin;
runparams.par_end = par_end;
// No side effect of file copying and image conversion
runparams.dryrun = true;
// set source type for the view-source dialog
if (isLatex())
os << "%LaTeX\n";
else if (isLinuxDoc())
os << "%LinuxDoc\n";
else if (isDocBook())
os << "%DocBook\n";
else
BOOST_ASSERT(false);
// start text
if (par_begin + 1 == par_end)
os << "% Preview source code for paragraph " << par_begin << "\n\n";
else
os << "% Preview source code from paragraph " << par_begin << " to " << par_end - 1 << "\n\n";
// output paragraphs
if (isLatex()) {
texrow().reset();
latexParagraphs(*this, paragraphs(), os, texrow(), runparams);
} else if (isLinuxDoc())
linuxdocParagraphs(*this, paragraphs(), os, runparams);
else // DocBook
docbookParagraphs(paragraphs(), *this, os, runparams);
}

View File

@ -333,6 +333,8 @@ public:
StableDocIterator getAnchor() const { return anchor_; }
///
void changeRefsIfUnique(std::string const & from, std::string const & to);
/// get source code (latex/docbook/linuxdoc) for some paragraphs
void getSourceCode(std::ostream & os, lyx::pit_type par_begin, lyx::pit_type par_end);
private:
/** Inserts a file into a document

View File

@ -0,0 +1,66 @@
/**
* \file ControlViewSource.C
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author John Levon
* \author Angus Leeming
* \author Bo Peng
*
* Full author contact details are available in file CREDITS.
*/
#include <config.h>
#include "ControlViewSource.h"
#include "gettext.h"
using std::string;
namespace lyx {
namespace frontend {
ControlViewSource::ControlViewSource(Dialog & parent)
: Dialog::Controller(parent)
{}
bool ControlViewSource::initialiseParams(string const & source)
{
string sourcetype = source.substr(1, 5);
if (sourcetype == "LaTeX") {
type_ = LatexSource;
source_ = source.substr(7);
} else if (sourcetype == "Linux") {
type_ = LinuxDocSource;
source_ = source.substr(10);
} else if (sourcetype == "DocBo") {
type_ = DocBookSource;
source_ = source.substr(9);
} else
return false;
return true;
}
void ControlViewSource::clearParams()
{
source_.erase();
}
string const ControlViewSource::title() const
{
switch (type_) {
case LatexSource:
return _("LaTeX Source");
case LinuxDocSource:
return _("LinuxDoc Source");
case DocBookSource:
return _("DocBook Source");
}
}
} // namespace frontend
} // namespace lyx

View File

@ -0,0 +1,60 @@
// -*- C++ -*-
/**
* \file ControlViewSource.h
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author John Levon
* \author Angus Leeming
* \Bo Peng
*
* Full author contact details are available in file CREDITS.
*/
#ifndef CONTROLVIEWSOURCE_H
#define CONTROLVIEWSOURCE_H
#include "Dialog.h"
namespace lyx {
namespace frontend {
/**
* A controller for a read-only text browser.
*/
class ControlViewSource : public Dialog::Controller {
public:
///
ControlViewSource(Dialog &);
/** \param source source code to be displayed
*/
virtual bool initialiseParams(std::string const & source);
///
virtual void clearParams();
///
virtual void dispatchParams() {}
///
virtual bool isBufferDependent() const { return true; }
/// The title displayed by the dialog reflects the \c VIEWSOURCETYPE
std::string const title() const;
/// get the source code
std::string const str() const { return source_; }
private:
/// Recognized source code type
enum SOURCETYPE {
LatexSource,
LinuxDocSource,
DocBookSource
};
SOURCETYPE type_;
std::string source_;
};
} // namespace frontend
} // namespace lyx
#endif // CONTROLVIEWSOURCE_H

View File

@ -63,6 +63,8 @@ libcontrollers_la_SOURCES= \
ControlInclude.h \
ControlLog.C \
ControlLog.h \
ControlViewSource.C \
ControlViewSource.h \
ControlMath.C \
ControlMath.h \
ControlNote.C \

View File

@ -27,6 +27,7 @@
#include "ControlGraphics.h"
#include "ControlInclude.h"
#include "ControlLog.h"
#include "ControlViewSource.h"
#include "ControlMath.h"
#include "ControlNote.h"
#include "ControlParagraph.h"
@ -66,6 +67,7 @@
#include "QInclude.h"
#include "QIndex.h"
#include "QLog.h"
#include "QViewSource.h"
#include "QMath.h"
#include "QNote.h"
#include "QParagraph.h"
@ -102,7 +104,7 @@ namespace {
char const * const dialognames[] = {
"aboutlyx", "bibitem", "bibtex", "box", "branch", "changes", "character",
"citation", "document", "errorlist", "ert", "external", "file",
"findreplace", "float", "graphics", "include", "index", "label", "log",
"findreplace", "float", "graphics", "include", "index", "label", "log", "view-source",
"mathpanel", "mathdelimiter", "mathmatrix", "note", "paragraph", "preamble",
"prefs", "print", "ref", "sendto", "spellchecker","tabular", "tabularcreate",
@ -242,6 +244,10 @@ Dialogs::DialogPtr Dialogs::build(string const & name)
dialog->setController(new ControlLog(*dialog));
dialog->setView(new QLog(*dialog));
dialog->bc().bp(new OkCancelPolicy);
} else if (name == "view-source") {
dialog->setController(new ControlViewSource(*dialog));
dialog->setView(new QViewSource(*dialog));
dialog->bc().bp(new OkCancelPolicy);
} else if (name == "mathpanel") {
dialog->setController(new ControlMath(*dialog));
dialog->setView(new QMath(*dialog));

View File

@ -49,6 +49,7 @@ libqt2_la_SOURCES = \
QIndex.C QIndex.h \
QLImage.C QLImage.h \
QLog.C QLog.h \
QViewSource.C QViewSource.h \
QLPainter.C QLPainter.h \
QLyXKeySym.C QLyXKeySym.h \
QMath.C QMath.h \

View File

@ -33,6 +33,7 @@ UIFILES = \
QIncludeDialogBase.ui \
QIndexDialogBase.ui \
QLogDialogBase.ui \
QViewSourceDialogBase.ui \
QMathDialogBase.ui \
QMathMatrixDialogBase.ui \
QNoteDialogBase.ui \
@ -100,6 +101,7 @@ MOCFILES = \
QIncludeDialog.C QIncludeDialog.h \
QIndexDialog.C QIndexDialog.h \
QLogDialog.C QLogDialog.h \
QViewSourceDialog.C QViewSourceDialog.h \
QLPopupMenu.C QLPopupMenu.h \
QLPrintDialog.C QLPrintDialog.h \
QMathDialog.C QMathDialog.h \

View File

@ -0,0 +1,58 @@
/**
* \file QViewSource.C
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author John Levon
* \author Bo Peng
*
* Full author contact details are available in file CREDITS.
*/
#include <config.h>
#include "QViewSource.h"
#include "QViewSourceDialog.h"
#include "qt_helpers.h"
#include "controllers/ControlViewSource.h"
#include <sstream>
#include <qtextview.h>
#include <qpushbutton.h>
namespace lyx {
namespace frontend {
typedef QController<ControlViewSource, QView<QViewSourceDialog> > base_class;
QViewSource::QViewSource(Dialog & parent)
: base_class(parent, "")
{}
void QViewSource::build_dialog()
{
dialog_.reset(new QViewSourceDialog(this));
dialog_->viewSourceTV->setReadOnly(true);
dialog_->viewSourceTV->setTextFormat(Qt::PlainText);
// this is personal. I think source code should be in fixed-size font
QFont font("Courier New");
font.setFixedPitch(true);
font.setStyleHint(QFont::TypeWriter);
dialog_->viewSourceTV->setFont(font);
// again, personal taste
dialog_->viewSourceTV->setWordWrap(QTextEdit::NoWrap);
}
void QViewSource::update_contents()
{
setTitle(controller().title());
dialog_->viewSourceTV->setText(toqstr(controller().str()));
}
} // namespace frontend
} // namespace lyx

View File

@ -0,0 +1,45 @@
// -*- C++ -*-
/**
* \file QViewSource.h
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author John Levon
* \author Bo Peng
*
* Full author contact details are available in file CREDITS.
*/
#ifndef QVIEWSOURCE_H
#define QVIEWSOURCE_H
#include "QDialogView.h"
namespace lyx {
namespace frontend {
class ControlViewSource;
class QViewSourceDialog;
///
class QViewSource
: public QController<ControlViewSource, QView<QViewSourceDialog> >
{
public:
///
friend class QViewSourceDialog;
///
QViewSource(Dialog &);
private:
/// Apply changes
virtual void apply() {}
/// update
virtual void update_contents();
/// build the dialog
virtual void build_dialog();
};
} // namespace frontend
} // namespace lyx
#endif // QVIEWSOURCE_H

View File

@ -0,0 +1,40 @@
/**
* \file QViewSourceDialog.C
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author John Levon
* \author Bo Peng
*
* Full author contact details are available in file CREDITS.
*/
#include <config.h>
#include "QViewSourceDialog.h"
#include "QViewSource.h"
#include <qpushbutton.h>
namespace lyx {
namespace frontend {
QViewSourceDialog::QViewSourceDialog(QViewSource * form)
: QViewSourceDialogBase(0, 0, false, 0),
form_(form)
{
connect(closePB, SIGNAL(clicked()),
form, SLOT(slotClose()));
}
void QViewSourceDialog::closeEvent(QCloseEvent * e)
{
form_->slotWMHide();
e->accept();
}
} // namespace frontend
} // namespace lyx

View File

@ -0,0 +1,36 @@
// -*- C++ -*-
/**
* \file QViewSourceDialog.h
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author John Levon
* \author Bo Peng
*
* Full author contact details are available in file CREDITS.
*/
#ifndef QVIEWSOURCEDIALOG_H
#define QVIEWSOURCEDIALOG_H
#include "ui/QViewSourceDialogBase.h"
namespace lyx {
namespace frontend {
class QViewSource;
class QViewSourceDialog : public QViewSourceDialogBase {
Q_OBJECT
public:
QViewSourceDialog(QViewSource * form);
protected:
virtual void closeEvent(QCloseEvent * e);
private:
QViewSource * form_;
};
} // namespace frontend
} // namespace lyx
#endif // QVIEWSOURCEDIALOG_H

View File

@ -0,0 +1,99 @@
<!DOCTYPE UI><UI>
<class>QViewSourceDialogBase</class>
<include location="global">config.h</include>
<include location="local">qt_helpers.h</include>
<widget>
<class>QDialog</class>
<property stdset="1">
<name>name</name>
<cstring>QViewSourceDialogBase</cstring>
</property>
<property stdset="1">
<name>geometry</name>
<rect>
<x>0</x>
<y>0</y>
<width>420</width>
<height>328</height>
</rect>
</property>
<property stdset="1">
<name>caption</name>
<string></string>
</property>
<property stdset="1">
<name>sizeGripEnabled</name>
<bool>true</bool>
</property>
<vbox>
<property stdset="1">
<name>margin</name>
<number>11</number>
</property>
<property stdset="1">
<name>spacing</name>
<number>6</number>
</property>
<widget>
<class>QTextEdit</class>
<property stdset="1">
<name>name</name>
<cstring>viewSourceTV</cstring>
</property>
</widget>
<widget>
<class>QLayoutWidget</class>
<property stdset="1">
<name>name</name>
<cstring>Layout27</cstring>
</property>
<hbox>
<property stdset="1">
<name>margin</name>
<number>0</number>
</property>
<property stdset="1">
<name>spacing</name>
<number>6</number>
</property>
<spacer>
<property>
<name>name</name>
<cstring>Spacer3</cstring>
</property>
<property stdset="1">
<name>orientation</name>
<enum>Horizontal</enum>
</property>
<property stdset="1">
<name>sizeType</name>
<enum>Expanding</enum>
</property>
<property>
<name>sizeHint</name>
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
<widget>
<class>QPushButton</class>
<property stdset="1">
<name>name</name>
<cstring>closePB</cstring>
</property>
<property stdset="1">
<name>text</name>
<string>&amp;Close</string>
</property>
</widget>
</hbox>
</widget>
</vbox>
</widget>
<tabstops>
<tabstop>viewSourceTV</tabstop>
<tabstop>closePB</tabstop>
</tabstops>
</UI>

View File

@ -559,6 +559,10 @@ string const InsetGraphics::prepareFile(Buffer const & buf,
string const orig_file = params().filename.absFilename();
string const rel_file = params().filename.relFilename(buf.filePath());
// previewing source code, no file copying or file format conversion
if (runparams.dryrun)
return stripExtensionIfPossible(rel_file);
// If the file is compressed and we have specified that it
// should not be uncompressed, then just return its name and
// let LaTeX do the rest!

View File

@ -131,6 +131,7 @@ using std::make_pair;
using std::pair;
using std::string;
using std::istringstream;
using std::ostringstream;
namespace biblio = lyx::biblio;
namespace fs = boost::filesystem;
@ -522,6 +523,8 @@ FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const
#endif
else if (name == "vclog")
enable = buf->lyxvc().inUse();
else if (name == "view-source")
enable = buf;
break;
}
@ -1183,6 +1186,25 @@ void LyXFunc::dispatch(FuncRequest const & cmd)
owner->buffer()->lyxvc().getLogFile();
owner->getDialogs().show("log", data);
}
else if (name == "view-source") {
// get the *top* level paragraphs that contain the cursor,
// or the selected text
lyx::pit_type par_begin;
lyx::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)
std::swap(par_begin, par_end);
ostringstream ostr;
view()->buffer()->getSourceCode(ostr, par_begin, par_end + 1);
// display the dialog and show source code
owner->getDialogs().show("view-source", ostr.str());
}
else
owner->getDialogs().show(name, data);
break;

View File

@ -16,6 +16,7 @@
#include "buffer.h"
#include "buffer_funcs.h"
#include "bufferparams.h"
#include "outputparams.h"
#include "counters.h"
#include "debug.h"
#include "paragraph.h"
@ -285,8 +286,20 @@ void docbookParagraphs(ParagraphList const & paragraphs,
ParagraphList::const_iterator par = paragraphs.begin();
ParagraphList::const_iterator pend = paragraphs.end();
BOOST_ASSERT(runparams.par_begin <= runparams.par_end);
// if only part of the paragraphs will be outputed
if (runparams.par_begin != runparams.par_end) {
par = boost::next(paragraphs.begin(), runparams.par_begin);
pend = boost::next(paragraphs.begin(), runparams.par_end);
// runparams will be passed to nested paragraphs, so
// we have to reset the range parameters.
const_cast<OutputParams&>(runparams).par_begin = 0;
const_cast<OutputParams&>(runparams).par_end = 0;
}
while (par != pend) {
LyXLayout_ptr const & style = par->layout();
ParagraphList::const_iterator lastpar = par;
ParagraphList::const_iterator send;
switch (style->latextype) {
@ -308,5 +321,8 @@ void docbookParagraphs(ParagraphList const & paragraphs,
default:
break;
}
// makeEnvironment may process more than one paragraphs and bypass pend
if (std::distance(lastpar, par) >= std::distance(lastpar, pend))
break;
}
}

View File

@ -463,8 +463,20 @@ void latexParagraphs(Buffer const & buf,
ParagraphList::const_iterator par = paragraphs.begin();
ParagraphList::const_iterator endpar = paragraphs.end();
BOOST_ASSERT(runparams.par_begin <= runparams.par_end);
// if only part of the paragraphs will be outputed
if (runparams.par_begin != runparams.par_end) {
par = boost::next(paragraphs.begin(), runparams.par_begin);
endpar = boost::next(paragraphs.begin(), runparams.par_end);
// runparams will be passed to nested paragraphs, so
// we have to reset the range parameters.
const_cast<OutputParams&>(runparams).par_begin = 0;
const_cast<OutputParams&>(runparams).par_end = 0;
}
// if only_body
while (par != endpar) {
ParagraphList::const_iterator lastpar = par;
// well we have to check if we are in an inset with unlimited
// length (all in one row) if that is true then we don't allow
// any special options in the paragraph and also we don't allow
@ -516,6 +528,8 @@ void latexParagraphs(Buffer const & buf,
par = TeXOnePar(buf, paragraphs, par, os, texrow,
runparams, everypar);
}
if (std::distance(lastpar, par) >= std::distance(lastpar, endpar))
break;
}
// It might be that we only have a title in this document
if (was_title && !already_title) {

View File

@ -15,6 +15,7 @@
#include "buffer.h"
#include "bufferparams.h"
#include "outputparams.h"
#include "paragraph.h"
#include "paragraph_funcs.h"
#include "ParagraphList.h"
@ -40,6 +41,18 @@ void linuxdocParagraphs(Buffer const & buf,
ParagraphList::const_iterator pit = paragraphs.begin();
ParagraphList::const_iterator pend = paragraphs.end();
BOOST_ASSERT(runparams.par_begin <= runparams.par_end);
// if only part of the paragraphs will be outputed
if (runparams.par_begin != runparams.par_end) {
pit = boost::next(paragraphs.begin(), runparams.par_begin);
pend = boost::next(paragraphs.begin(), runparams.par_end);
// runparams will be passed to nested paragraphs, so
// we have to reset the range parameters.
const_cast<OutputParams&>(runparams).par_begin = 0;
const_cast<OutputParams&>(runparams).par_end = 0;
}
for (; pit != pend; ++pit) {
LyXLayout_ptr const & style = pit->layout();
// treat <toc> as a special case for compatibility with old code

View File

@ -19,7 +19,9 @@ OutputParams::OutputParams()
local_font(0), free_spacing(false), use_babel(false),
linelen(0), depth(0),
exportdata(new ExportData),
inComment(false)
inComment(false),
par_begin(0), par_end(0),
dryrun(false)
{}

View File

@ -24,7 +24,6 @@ class LyXFont;
class OutputParams {
public:
//
enum FLAVOR {
LATEX,
PDFLATEX,
@ -97,6 +96,22 @@ public:
* if this flag is true, since they may not exist.
*/
bool inComment;
/** allow output of only part of the top-level paragraphs
* par_begin: beginning paragraph
*/
lyx::pit_type par_begin;
/** allow output of only part of the top-level paragraphs
* par_end: par_end-1 is the ending paragraph
* if par_begin=par_end, output all paragraphs
*/
lyx::pit_type par_end;
/** whether or not do actual file copying and image conversion
* This mode will be used to preview the source code
*/
bool dryrun;
};
#endif // NOT OUTPUTPARAMS_H

View File

@ -81,6 +81,7 @@ using lyx::support::token;
using std::endl;
using std::string;
using std::istringstream;
using std::ostringstream;
extern string current_layout;
@ -1107,6 +1108,21 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
bv->switchKeyMap();
bv->owner()->updateMenubar();
bv->owner()->updateToolbars();
// if view-source dialog is visible, send source code of selected
// text to the dialog
if (cmd.button() == mouse_button::button1 && cur.selection()
&& bv->owner()->getDialogs().visible("view-source")) {
// get *top* level paragraphs that contain the selection
lyx::pit_type par_begin = bv->cursor().selectionBegin().bottom().pit();
lyx::pit_type par_end = bv->cursor().selectionEnd().bottom().pit();
if (par_begin > par_end)
std::swap(par_begin, par_end);
ostringstream ostr;
bv->buffer()->getSourceCode(ostr, par_begin, par_end + 1);
// display the dialog and show source code
bv->owner()->getDialogs().update("view-source", ostr.str());
}
break;
}