From 1ccfe1491456c09d1ad8f6687d6fcdb68443c4d6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=BCrgen=20Spitzm=C3=BCller?= Date: Thu, 7 Jan 2010 10:01:26 +0000 Subject: [PATCH] * Add native support for \includeonly (bug 5360). File format change. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@32826 a592a061-630c-0410-9148-cb99ea01b6c8 --- development/FORMAT | 9 ++ development/scons/scons_manifest.py | 1 + lib/lyx2lyx/lyx_2_0.py | 19 ++++- src/Buffer.cpp | 7 +- src/BufferParams.cpp | 58 ++++++++++++- src/BufferParams.h | 18 +++- src/frontends/qt4/GuiDocument.cpp | 113 ++++++++++++++++++++++++++ src/frontends/qt4/GuiDocument.h | 8 ++ src/frontends/qt4/Makefile.am | 1 + src/frontends/qt4/ui/MasterChildUi.ui | 70 ++++++++++++++++ 10 files changed, 297 insertions(+), 7 deletions(-) create mode 100644 src/frontends/qt4/ui/MasterChildUi.ui diff --git a/development/FORMAT b/development/FORMAT index e3a04668bd..1d35830f9a 100644 --- a/development/FORMAT +++ b/development/FORMAT @@ -1,6 +1,15 @@ LyX file-format changes ----------------------- +2010-01-06 Jürgen Spitzmüller + * 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-12-30 Richard Heck * Format incremented to 374: add html output options. \html_use_mathml (boolean): whether to use MathML or images diff --git a/development/scons/scons_manifest.py b/development/scons/scons_manifest.py index dc660555f6..a65cebb1c6 100644 --- a/development/scons/scons_manifest.py +++ b/development/scons/scons_manifest.py @@ -940,6 +940,7 @@ src_frontends_qt4_ui_files = Split(''' ListingsSettingsUi.ui LogUi.ui MarginsUi.ui + MasterChildUi.ui MathMatrixUi.ui MathsUi.ui ModulesUi.ui diff --git a/lib/lyx2lyx/lyx_2_0.py b/lib/lyx2lyx/lyx_2_0.py index baa0fb6af5..67a5abc2ea 100644 --- a/lib/lyx2lyx/lyx_2_0.py +++ b/lib/lyx2lyx/lyx_2_0.py @@ -1141,6 +1141,19 @@ def revert_html_options(document): 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 @@ convert = [[346, []], [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]], diff --git a/src/Buffer.cpp b/src/Buffer.cpp index f8c53392a9..8c013a9fa2 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -127,7 +127,7 @@ namespace { // 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 DepClean; typedef map > RefCache; @@ -607,6 +607,7 @@ int Buffer::readHeader(Lexer & lex) 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 @@ void Buffer::writeLaTeXSource(odocstream & os, 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"); diff --git a/src/BufferParams.cpp b/src/BufferParams.cpp index ba261ec798..bf24b5937c 100644 --- a/src/BufferParams.cpp +++ b/src/BufferParams.cpp @@ -536,6 +536,8 @@ string BufferParams::readToken(Lexer & lex, string const & token, 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 @@ void BufferParams::writeFile(ostream & os) const os << *it << '\n'; os << "\\end_modules" << '\n'; } - + + // includeonly + if (!includedChildren_.empty()) { + os << "\\begin_includeonly" << '\n'; + list::const_iterator it = includedChildren_.begin(); + list::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 @@ void BufferParams::validate(LaTeXFeatures & features) const bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, - TexRow & texrow) const + TexRow & texrow, FileName const & filepath) const { os << "\\documentclass"; @@ -1249,6 +1261,31 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, // handle inputenc etc. writeEncodingPreamble(os, features, texrow); + // includeonly + if (!includedChildren_.empty()) { + os << "\\includeonly{"; + list::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 << ","; + os << from_utf8(incfile); + } + first = false; + } + os << "}\n"; + } + if (!listings_params.empty() || features.isRequired("listings")) { os << "\\usepackage{listings}\n"; texrow.newline(); @@ -1903,6 +1940,23 @@ void BufferParams::readRemovedModules(Lexer & lex) } +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; diff --git a/src/BufferParams.h b/src/BufferParams.h index 2973687d2d..bacda570b3 100644 --- a/src/BufferParams.h +++ b/src/BufferParams.h @@ -23,6 +23,7 @@ #include "insets/InsetQuotes.h" #include "support/copied_ptr.h" +#include "support/FileName.h" #include #include @@ -84,7 +85,8 @@ public: * 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 @@ public: /// Clear the removed module list void clearRemovedModules() { removedModules_.clear(); } + /// List of included children (for includeonly) + std::list 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 @@ private: void readModules(Lexer &); /// void readRemovedModules(Lexer &); + /// + void readIncludeonly(Lexer &); /// for use with natbib CiteEngine cite_engine_; /// @@ -394,6 +407,9 @@ private: /// the user has chosen not to use std::list removedModules_; + /// the list of included children (for includeonly) + std::list includedChildren_; + /** Use the Pimpl idiom to hide those member variables that would otherwise * drag in other header files. */ diff --git a/src/frontends/qt4/GuiDocument.cpp b/src/frontends/qt4/GuiDocument.cpp index 91137cbb22..6ed27ea4aa 100644 --- a/src/frontends/qt4/GuiDocument.cpp +++ b/src/frontends/qt4/GuiDocument.cpp @@ -617,6 +617,23 @@ GuiDocument::GuiDocument(GuiView & lv) bc().addCheckedLineEdit(textLayoutModule->indentLE); bc().addCheckedLineEdit(textLayoutModule->skipLE); + // master/child handling + masterChildModule = new UiWidget; + + 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->resizeColumnToContents(1); + masterChildModule->childrenTW->resizeColumnToContents(2); + // output outputModule = new UiWidget; @@ -1065,6 +1082,7 @@ GuiDocument::GuiDocument(GuiView & lv) 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::change_adaptor() } +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 @@ void GuiDocument::updateDefaultFormat() } +bool GuiDocument::isChildIncluded(string const & child) +{ + if (includeonlys_.empty()) + return false; + return (std::find(includeonlys_.begin(), + includeonlys_.end(), child) != includeonlys_.end()); +} + + void GuiDocument::applyView() { // preamble @@ -2043,6 +2090,15 @@ void GuiDocument::applyView() else bp_.master = string(); + // Master/Child + bp_.clearIncludedChildren(); + if (masterChildModule->includeonlyRB->isChecked()) { + list::const_iterator it = includeonlys_.begin(); + for (; it != includeonlys_.end() ; ++it) { + bp_.addIncludedChildren(*it); + } + } + // Float Placement bp_.float_placement = floatModule->get(); @@ -2422,6 +2478,17 @@ void GuiDocument::paramsToDialog() latexModule->childDocGB->setChecked(false); } + // Master/Child + std::vector 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,52 @@ void GuiDocument::updateSelectedModules() } +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 children = buffer().getChildren(false); + vector::const_iterator it = children.begin(); + vector::const_iterator end = children.end(); + bool has_unincluded = false; + bool all_unincluded = true; + 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; + else + all_unincluded = false; + } + // Both if all childs are included and if none is included + // is equal to "include all" (i.e., ommit \includeonly). + // Thus, reset the GUI. + if (!has_unincluded || all_unincluded) { + masterChildModule->includeallRB->setChecked(true); + masterChildModule->childrenTW->setEnabled(false); + includeonlys_.clear(); + } + // If all are included, we need to update again. + if (!has_unincluded) + updateIncludeonlys(); +} + + void GuiDocument::updateContents() { // Nothing to do here as the document settings is not cursor dependant. diff --git a/src/frontends/qt4/GuiDocument.h b/src/frontends/qt4/GuiDocument.h index 96e3433aed..920e95145d 100644 --- a/src/frontends/qt4/GuiDocument.h +++ b/src/frontends/qt4/GuiDocument.h @@ -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 @@ public: void updateFontlist(); void updateDefaultFormat(); void updatePagestyle(std::string const &, std::string const &); + bool isChildIncluded(std::string const &); void showPreamble(); /// @@ -83,6 +85,7 @@ public: private Q_SLOTS: void updateNumbering(); void change_adaptor(); + void includeonlyClicked(QTreeWidgetItem * item, int); void setListingsMessage(); void saveDefaultClicked(); void useDefaultsClicked(); @@ -115,6 +118,7 @@ private: QString validateListingsParameters(); UiWidget *textLayoutModule; + UiWidget *masterChildModule; UiWidget *fontModule; UiWidget *pageLayoutModule; UiWidget *marginsModule; @@ -150,6 +154,8 @@ private: void updateAvailableModules(); /// void updateSelectedModules(); + /// + void updateIncludeonlys(); /// save as default template void saveDocDefault(); /// reset to default params @@ -232,6 +238,8 @@ private: std::list moduleNames_; /// std::map changedBranches_; + /// + std::list includeonlys_; }; diff --git a/src/frontends/qt4/Makefile.am b/src/frontends/qt4/Makefile.am index 5eee3a6236..7882598110 100644 --- a/src/frontends/qt4/Makefile.am +++ b/src/frontends/qt4/Makefile.am @@ -282,6 +282,7 @@ UIFILES = \ ListingsSettingsUi.ui \ LogUi.ui \ MarginsUi.ui \ + MasterChildUi.ui \ MathMatrixUi.ui \ MathsUi.ui \ ModulesUi.ui \ diff --git a/src/frontends/qt4/ui/MasterChildUi.ui b/src/frontends/qt4/ui/MasterChildUi.ui new file mode 100644 index 0000000000..360cf5790e --- /dev/null +++ b/src/frontends/qt4/ui/MasterChildUi.ui @@ -0,0 +1,70 @@ + + MasterChildUi + + + + 0 + 0 + 348 + 327 + + + + + + + + 9 + + + 6 + + + + + Master Document Output + + + true + + + + 9 + + + 6 + + + + + Include all included subdocuments in the output + + + &Include all children + + + + + + + Include only the selected subdocuments in the output + + + Include &only selected children + + + + + + + + + + + + + qt_i18n.h + + + + -- 2.39.2