The attached patch adds basic support for \includeonly, which cannot be used
natively in the preamble, due to our file name mangling.
What it does not do yet is to check if all aux files are there (which is
necessary if the page numbers and references to the non-included children
should be maintained). I'd like to implement this in a subsequent step.
Comments?
Jürgen
Index: src/BufferParams.h
===================================================================
--- src/BufferParams.h (Revision 32790)
+++ src/BufferParams.h (Arbeitskopie)
@@ -23,6 +23,7 @@
#include "insets/InsetQuotes.h"
#include "support/copied_ptr.h"
+#include "support/FileName.h"
#include <list>
#include <map>
@@ -84,7 +85,8 @@
* the BufferParams and a LyXRC variable).
* This returned value can then be passed to the insets...
*/
- bool writeLaTeX(odocstream &, LaTeXFeatures &, TexRow &) const;
+ bool writeLaTeX(odocstream &, LaTeXFeatures &, TexRow &,
+ support::FileName const &) const;
///
void useClassDefaults();
@@ -154,6 +156,15 @@
/// Clear the removed module list
void clearRemovedModules() { removedModules_.clear(); }
+ /// List of included children (for includeonly)
+ std::list<std::string> const & getIncludedChildren() const
+ { return includedChildren_; }
+ ///
+ void addIncludedChildren(std::string const & child)
+ { includedChildren_.push_back(child); }
+ /// Clear the list of included children
+ void clearIncludedChildren() { includedChildren_.clear(); }
+
/// returns the main font for the buffer (document)
Font const getFont() const;
@@ -384,6 +395,8 @@
void readModules(Lexer &);
///
void readRemovedModules(Lexer &);
+ ///
+ void readIncludeonly(Lexer &);
/// for use with natbib
CiteEngine cite_engine_;
///
@@ -394,6 +407,9 @@
/// the user has chosen not to use
std::list<std::string> removedModules_;
+ /// the list of included children (for includeonly)
+ std::list<std::string> includedChildren_;
+
/** Use the Pimpl idiom to hide those member variables that would otherwise
* drag in other header files.
*/
Index: src/frontends/qt4/GuiDocument.h
===================================================================
--- src/frontends/qt4/GuiDocument.h (Revision 32790)
+++ src/frontends/qt4/GuiDocument.h (Arbeitskopie)
@@ -23,6 +23,7 @@
#include "ui_DocumentUi.h"
#include "ui_FontUi.h"
#include "ui_TextLayoutUi.h"
+#include "ui_MasterChildUi.h"
#include "ui_MathsUi.h"
#include "ui_LaTeXUi.h"
#include "ui_PageLayoutUi.h"
@@ -75,6 +76,7 @@
void updateFontlist();
void updateDefaultFormat();
void updatePagestyle(std::string const &, std::string const &);
+ bool isChildIncluded(std::string const &);
void showPreamble();
///
@@ -83,6 +85,7 @@
private Q_SLOTS:
void updateNumbering();
void change_adaptor();
+ void includeonlyClicked(QTreeWidgetItem * item, int);
void setListingsMessage();
void saveDefaultClicked();
void useDefaultsClicked();
@@ -115,6 +118,7 @@
QString validateListingsParameters();
UiWidget<Ui::TextLayoutUi> *textLayoutModule;
+ UiWidget<Ui::MasterChildUi> *masterChildModule;
UiWidget<Ui::FontUi> *fontModule;
UiWidget<Ui::PageLayoutUi> *pageLayoutModule;
UiWidget<Ui::MarginsUi> *marginsModule;
@@ -150,6 +154,8 @@
void updateAvailableModules();
///
void updateSelectedModules();
+ ///
+ void updateIncludeonlys();
/// save as default template
void saveDocDefault();
/// reset to default params
@@ -232,6 +238,8 @@
std::list<modInfoStruct> moduleNames_;
///
std::map<docstring, docstring> changedBranches_;
+ ///
+ std::list<std::string> includeonlys_;
};
Index: src/frontends/qt4/GuiDocument.cpp
===================================================================
--- src/frontends/qt4/GuiDocument.cpp (Revision 32790)
+++ src/frontends/qt4/GuiDocument.cpp (Arbeitskopie)
@@ -617,6 +617,23 @@
bc().addCheckedLineEdit(textLayoutModule->indentLE);
bc().addCheckedLineEdit(textLayoutModule->skipLE);
+ masterChildModule = new UiWidget<Ui::MasterChildUi>;
+ // master/child handling
+ connect(masterChildModule->childrenTW, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)),
+ this, SLOT(includeonlyClicked(QTreeWidgetItem *, int)));
+ connect(masterChildModule->includeonlyRB, SIGNAL(toggled(bool)),
+ masterChildModule->childrenTW, SLOT(setEnabled(bool)));
+ connect(masterChildModule->includeallRB, SIGNAL(clicked()),
+ this, SLOT(change_adaptor()));
+ connect(masterChildModule->includeonlyRB, SIGNAL(clicked()),
+ this, SLOT(change_adaptor()));
+ masterChildModule->childrenTW->setColumnCount(2);
+ masterChildModule->childrenTW->headerItem()->setText(0, qt_("Child Document"));
+ masterChildModule->childrenTW->headerItem()->setText(1, qt_("Include to Output"));
+ masterChildModule->childrenTW->setSortingEnabled(true);
+ masterChildModule->childrenTW->resizeColumnToContents(1);
+ masterChildModule->childrenTW->resizeColumnToContents(2);
+
// output
outputModule = new UiWidget<Ui::OutputUi>;
@@ -1065,6 +1082,7 @@
qt_("Input listings parameters below. Enter ? for a list of parameters."));
docPS->addPanel(latexModule, qt_("Document Class"));
+ docPS->addPanel(masterChildModule, qt_("Child Documents"));
docPS->addPanel(modulesModule, qt_("Modules"));
docPS->addPanel(fontModule, qt_("Fonts"));
docPS->addPanel(textLayoutModule, qt_("Text Layout"));
@@ -1115,6 +1133,26 @@
}
+void GuiDocument::includeonlyClicked(QTreeWidgetItem * item, int)
+{
+ if (item == 0)
+ return;
+
+ string child = fromqstr(item->text(0));
+ if (child.empty())
+ return;
+
+ if (std::find(includeonlys_.begin(),
+ includeonlys_.end(), child) != includeonlys_.end())
+ includeonlys_.remove(child);
+ else
+ includeonlys_.push_back(child);
+
+ updateIncludeonlys();
+ changed();
+}
+
+
QString GuiDocument::validateListingsParameters()
{
// use a cache here to avoid repeated validation
@@ -1805,6 +1843,15 @@
}
+bool GuiDocument::isChildIncluded(string const & child)
+{
+ if (includeonlys_.empty())
+ return true;
+ return (std::find(includeonlys_.begin(),
+ includeonlys_.end(), child) != includeonlys_.end());
+}
+
+
void GuiDocument::applyView()
{
// preamble
@@ -2043,6 +2090,15 @@
else
bp_.master = string();
+ // Master/Child
+ bp_.clearIncludedChildren();
+ if (masterChildModule->includeonlyRB->isChecked()) {
+ list<string>::const_iterator it = includeonlys_.begin();
+ for (; it != includeonlys_.end() ; ++it) {
+ bp_.addIncludedChildren(*it);
+ }
+ }
+
// Float Placement
bp_.float_placement = floatModule->get();
@@ -2422,6 +2478,17 @@
latexModule->childDocGB->setChecked(false);
}
+ // Master/Child
+ std::vector<Buffer *> children = buffer().getChildren(false);
+ if (children.empty()) {
+ masterChildModule->setEnabled(false);
+ includeonlys_.clear();
+ } else {
+ masterChildModule->setEnabled(true);
+ includeonlys_ = bp_.getIncludedChildren();
+ updateIncludeonlys();
+ }
+
// Float Settings
floatModule->set(bp_.float_placement);
@@ -2649,6 +2716,42 @@
}
+void GuiDocument::updateIncludeonlys()
+{
+ masterChildModule->childrenTW->clear();
+ QString const no = qt_("No");
+ QString const yes = qt_("Yes");
+
+ if (includeonlys_.empty()) {
+ masterChildModule->includeallRB->setChecked(true);
+ masterChildModule->childrenTW->setEnabled(false);
+ } else {
+ masterChildModule->includeonlyRB->setChecked(true);
+ masterChildModule->childrenTW->setEnabled(true);
+ }
+ QTreeWidgetItem * item = 0;
+ std::vector<Buffer *> children = buffer().getChildren(false);
+ vector<Buffer *>::const_iterator it = children.begin();
+ vector<Buffer *>::const_iterator end = children.end();
+ bool has_unincluded = false;
+ for (; it != end; ++it) {
+ item = new QTreeWidgetItem(masterChildModule->childrenTW);
+ // FIXME Unicode
+ string const name =
+ to_utf8(makeRelPath(from_utf8((*it)->fileName().absFilename()),
+ from_utf8(buffer().filePath())));
+ item->setText(0, toqstr(name));
+ item->setText(1, isChildIncluded(name) ? yes : no);
+ if (!isChildIncluded(name))
+ has_unincluded = true;
+ }
+ if (!has_unincluded) {
+ masterChildModule->includeallRB->setChecked(true);
+ masterChildModule->childrenTW->setEnabled(false);
+ }
+}
+
+
void GuiDocument::updateContents()
{
// Nothing to do here as the document settings is not cursor dependant.
Index: src/frontends/qt4/Makefile.am
===================================================================
--- src/frontends/qt4/Makefile.am (Revision 32790)
+++ src/frontends/qt4/Makefile.am (Arbeitskopie)
@@ -282,6 +282,7 @@
ListingsSettingsUi.ui \
LogUi.ui \
MarginsUi.ui \
+ MasterChildUi.ui \
MathMatrixUi.ui \
MathsUi.ui \
ModulesUi.ui \
Index: src/frontends/qt4/ui/MasterChildUi.ui
===================================================================
--- src/frontends/qt4/ui/MasterChildUi.ui (Revision 0)
+++ src/frontends/qt4/ui/MasterChildUi.ui (Revision 0)
@@ -0,0 +1,70 @@
+<ui version="4.0" >
+ <class>MasterChildUi</class>
+ <widget class="QWidget" name="MasterChildUi" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>348</width>
+ <height>327</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string/>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>9</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item row="0" column="0" >
+ <widget class="QGroupBox" name="includeonlyGB" >
+ <property name="title" >
+ <string>Master Document Output</string>
+ </property>
+ <property name="flat" >
+ <bool>true</bool>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>9</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item row="0" column="0" >
+ <widget class="QRadioButton" name="includeallRB" >
+ <property name="toolTip" >
+ <string>Include all included subdocuments in the output</string>
+ </property>
+ <property name="text" >
+ <string>&Include all children</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QRadioButton" name="includeonlyRB" >
+ <property name="toolTip" >
+ <string>Include only the selected subdocuments in the output</string>
+ </property>
+ <property name="text" >
+ <string>Include &only selected children</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" >
+ <widget class="QTreeWidget" name="childrenTW" />
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <includes>
+ <include location="local" >qt_i18n.h</include>
+ </includes>
+ <resources/>
+ <connections/>
+</ui>
Index: src/Buffer.cpp
===================================================================
--- src/Buffer.cpp (Revision 32790)
+++ src/Buffer.cpp (Arbeitskopie)
@@ -127,7 +127,7 @@
// Do not remove the comment below, so we get merge conflict in
// independent branches. Instead add your own.
-int const LYX_FORMAT = 374; // rgheck: HTML output options
+int const LYX_FORMAT = 375; // jspitzm: includeonly support
typedef map<string, bool> DepClean;
typedef map<docstring, pair<InsetLabel const *, Buffer::References> > RefCache;
@@ -607,6 +607,7 @@
params().listings_params.clear();
params().clearLayoutModules();
params().clearRemovedModules();
+ params().clearIncludedChildren();
params().pdfoptions().clear();
params().indiceslist().clear();
params().backgroundcolor = lyx::rgbFromHexName("#ffffff");
@@ -1259,7 +1260,9 @@
listParentMacros(parentMacros, features);
// Write the preamble
- runparams.use_babel = params().writeLaTeX(os, features, d->texrow);
+ runparams.use_babel = params().writeLaTeX(os, features,
+ d->texrow,
+ d->filename.onlyPath());
runparams.use_japanese = features.isRequired("japanese");
Index: src/BufferParams.cpp
===================================================================
--- src/BufferParams.cpp (Revision 32790)
+++ src/BufferParams.cpp (Arbeitskopie)
@@ -536,6 +536,8 @@
readModules(lex);
} else if (token == "\\begin_removed_modules") {
readRemovedModules(lex);
+ } else if (token == "\\begin_includeonly") {
+ readIncludeonly(lex);
} else if (token == "\\options") {
lex.eatLine();
options = lex.getString();
@@ -834,7 +836,17 @@
os << *it << '\n';
os << "\\end_modules" << '\n';
}
-
+
+ // includeonly
+ if (!includedChildren_.empty()) {
+ os << "\\begin_includeonly" << '\n';
+ list<string>::const_iterator it = includedChildren_.begin();
+ list<string>::const_iterator en = includedChildren_.end();
+ for (; it != en; it++)
+ os << *it << '\n';
+ os << "\\end_includeonly" << '\n';
+ }
+
// local layout information
if (!local_layout.empty()) {
// remove '\n' from the end
@@ -1080,7 +1092,7 @@
bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
- TexRow & texrow) const
+ TexRow & texrow, FileName const & filepath) const
{
os << "\\documentclass";
@@ -1249,6 +1261,31 @@
// handle inputenc etc.
writeEncodingPreamble(os, features, texrow);
+ // includeonly
+ if (!includedChildren_.empty()) {
+ os << "\\includeonly{%\n";
+ list<string>::const_iterator it = includedChildren_.begin();
+ bool first = true;
+ for (; it != includedChildren_.end() ; ++it) {
+ string incfile = *it;
+ FileName inc = makeAbsPath(incfile, filepath.absFilename());
+ string mangled = DocFileName(changeExtension(inc.absFilename(), ".tex")).
+ mangledFilename();
+ if (!features.runparams().nice)
+ incfile = mangled;
+ // \includeonly doesn't want an extension
+ incfile = changeExtension(incfile, string());
+ incfile = latex_path(incfile);
+ if (!incfile.empty()) {
+ if (!first)
+ os << ",\n";
+ os << from_utf8(incfile);
+ }
+ first = false;
+ }
+ os << "\n}\n";
+ }
+
if (!listings_params.empty() || features.isRequired("listings")) {
os << "\\usepackage{listings}\n";
texrow.newline();
@@ -1903,6 +1940,23 @@
}
+void BufferParams::readIncludeonly(Lexer & lex)
+{
+ if (!lex.eatLine()) {
+ lyxerr << "Error (BufferParams::readIncludeonly):"
+ "Unexpected end of input." << endl;
+ return;
+ }
+ while (true) {
+ string child = lex.getString();
+ if (child == "\\end_includeonly")
+ break;
+ includedChildren_.push_back(child);
+ lex.eatLine();
+ }
+}
+
+
string BufferParams::paperSizeName(PapersizePurpose purpose) const
{
char real_papersize = papersize;
Index: lib/lyx2lyx/lyx_2_0.py
===================================================================
--- lib/lyx2lyx/lyx_2_0.py (Revision 32790)
+++ lib/lyx2lyx/lyx_2_0.py (Arbeitskopie)
@@ -1141,6 +1141,19 @@
del document.header[i]
+def revert_includeonly(document):
+ i = 0
+ while True:
+ i = find_token(document.header, "\\begin_includeonly", i)
+ if i == -1:
+ return
+ j = find_end_of(document.header, i, "\\begin_includeonly", "\\end_includeonly")
+ if j == -1:
+ # this should not happen
+ break
+ document.header[i : j + 1] = []
+
+
##
# Conversion hub
#
@@ -1174,10 +1187,12 @@
[371, []],
[372, []],
[373, [merge_gbrief]],
- [374, []]
+ [374, []],
+ [375, []]
]
-revert = [[373, [revert_html_options]],
+revert = [[374, [revert_includeonly]],
+ [373, [revert_html_options]],
[372, [revert_gbrief]],
[371, [revert_fontenc]],
[370, [revert_mhchem]],
Index: development/scons/scons_manifest.py
===================================================================
--- development/scons/scons_manifest.py (Revision 32790)
+++ development/scons/scons_manifest.py (Arbeitskopie)
@@ -940,6 +940,7 @@
ListingsSettingsUi.ui
LogUi.ui
MarginsUi.ui
+ MasterChildUi.ui
MathMatrixUi.ui
MathsUi.ui
ModulesUi.ui
Index: development/FORMAT
===================================================================
--- development/FORMAT (Revision 32790)
+++ development/FORMAT (Arbeitskopie)
@@ -1,6 +1,18 @@
LyX file-format changes
-----------------------
+2010-01-06 Jürgen Spitzmüller <[email protected]>
+ * Format incremented to 375: add support for \includeonly
+ This adds a new buffer param list of relative filenames
+ which are output as \includeonly arguments, like this:
+ \begin_includeonly
+ child1.lyx
+ child2.lyx
+ \end_includeonly
+
+2009-??-?? Richard Heck <[email protected]>
+ * Format incremented to 374: FIXME: add Info!
+
2009-12-07 Jürgen Spitzmüller <[email protected]>
* Format incremented to 373: merge g-brief-de and g-brief-en
classes into one g-brief class.