diff --git a/development/FORMAT b/development/FORMAT index a038fab6be..541522062a 100644 --- a/development/FORMAT +++ b/development/FORMAT @@ -1,6 +1,9 @@ LyX file-format changes ----------------------- +2009-04-15 Jürgen Spitzmüller + * Format incremented to 352: splitindex support. + 2009-04-11 Uwe Stöhr * Format incremented to 351: support to set a page background color. diff --git a/development/scons/scons_manifest.py b/development/scons/scons_manifest.py index a1d44edc4e..5e62aa2340 100644 --- a/development/scons/scons_manifest.py +++ b/development/scons/scons_manifest.py @@ -72,6 +72,7 @@ src_header_files = Split(''' FuncRequest.h FuncStatus.h Graph.h + IndicesList.h InsetIterator.h InsetList.h Intl.h @@ -172,6 +173,7 @@ src_pre_files = Split(''' FuncRequest.cpp FuncStatus.cpp Graph.cpp + IndicesList.cpp InsetIterator.cpp InsetList.cpp Intl.cpp @@ -725,6 +727,7 @@ src_frontends_qt4_header_files = Split(''' GuiIdListModel.h GuiImage.h GuiInclude.h + GuiIndices.h GuiInfo.h GuiKeySymbol.h GuiLabel.h @@ -817,6 +820,7 @@ src_frontends_qt4_files = Split(''' GuiIdListModel.cpp GuiImage.cpp GuiInclude.cpp + GuiIndices.cpp GuiInfo.cpp GuiKeySymbol.cpp GuiLabel.cpp @@ -900,6 +904,7 @@ src_frontends_qt4_ui_files = Split(''' HSpaceUi.ui HyperlinkUi.ui IncludeUi.ui + IndicesUi.ui InfoUi.ui LabelUi.ui LaTeXUi.ui diff --git a/lib/chkconfig.ltx b/lib/chkconfig.ltx index 8d7960c0cd..2a91d5e11f 100644 --- a/lib/chkconfig.ltx +++ b/lib/chkconfig.ltx @@ -268,6 +268,7 @@ \TestPackage{setspace} \TestPackage{slashed} \TestPackage{soul} +\TestPackage{splitidx} \TestPackage{subfig} \TestPackage{textcomp} \TestPackage{ulem} diff --git a/lib/configure.py b/lib/configure.py index e369b68e14..05f4c3b226 100644 --- a/lib/configure.py +++ b/lib/configure.py @@ -599,6 +599,8 @@ def checkOtherEntries(): rc_entry = [ r'\index_command "%%"' ]) checkProg('an index processor appropriate to Japanese', ['mendex -c -q', 'makeindex -c -q'], rc_entry = [ r'\jindex_command "%%"' ]) + checkProg('the splitindex processor', ['splitindex.pl', 'java splitindex', 'splitindex'], + rc_entry = [ r'\splitindex_command "%%"' ]) checkProg('a nomenclature processor', ['makeindex'], rc_entry = [ r'\nomencl_command "makeindex -s nomencl.ist"' ]) ## FIXME: OCTAVE is not used anywhere diff --git a/lib/doc/LaTeXConfig.lyx b/lib/doc/LaTeXConfig.lyx index 2c7b866e9a..0f494e0c56 100644 --- a/lib/doc/LaTeXConfig.lyx +++ b/lib/doc/LaTeXConfig.lyx @@ -1,5 +1,5 @@ #LyX 2.0.0svn created this file. For more info see http://www.lyx.org/ -\lyxformat 347 +\lyxformat 352 \begin_document \begin_header \textclass article @@ -10,12 +10,14 @@ \font_sans default \font_typewriter default \font_default_family default +\use_xetex false \font_sc false \font_osf false \font_sf_scale 100 \font_tt_scale 100 \graphics default +\default_output_format default \paperfontsize default \spacing single \use_hyperref false @@ -25,7 +27,9 @@ \use_esint 0 \cite_engine basic \use_bibtopic false +\use_indices false \paperorientation portrait +\backgroundcolor #ffffff \secnumdepth 3 \tocdepth 3 \paragraph_separation indent @@ -4583,6 +4587,39 @@ slashed is needed by LyX to correctly typeset unicode symbols with slashes in math. \end_layout +\begin_layout Subsection +splitidx +\end_layout + +\begin_layout Description +Found: +\begin_inset Info +type "package" +arg "splitidx" +\end_inset + + +\end_layout + +\begin_layout Description +CTAN: +\family typewriter +macros/latex/contrib/splitindex/ +\end_layout + +\begin_layout Description +Notes: The package +\family sans +splitidx +\family default + is needed by LyX to generate multiple and subdivided indices. + Note that you also need to install one of the included +\family sans +splitindex +\family default + converter programs. +\end_layout + \begin_layout Subsection subfig \end_layout diff --git a/lib/lyx2lyx/lyx_2_0.py b/lib/lyx2lyx/lyx_2_0.py index 646a7c519a..b1f5cd5d25 100644 --- a/lib/lyx2lyx/lyx_2_0.py +++ b/lib/lyx2lyx/lyx_2_0.py @@ -19,6 +19,8 @@ """ Convert files to the file format generated by lyx 2.0""" import re, string +import unicodedata +import sys, os from parser_tools import find_token, find_end_of, find_tokens, get_value, get_value_string @@ -46,6 +48,133 @@ def insert_to_preamble(index, document, text): document.preamble.insert(index, text) +def read_unicodesymbols(): + " Read the unicodesymbols list of unicode characters and corresponding commands." + pathname = os.path.abspath(os.path.dirname(sys.argv[0])) + fp = open(os.path.join(pathname.strip('lyx2lyx'), 'unicodesymbols')) + spec_chars = [] + # Two backslashes, followed by some non-word character, and then a character + # in brackets. The idea is to check for constructs like: \"{u}, which is how + # they are written in the unicodesymbols file; but they can also be written + # as: \"u or even \" u. + r = re.compile(r'\\\\(\W)\{(\w)\}') + for line in fp.readlines(): + if line[0] != '#' and line.strip() != "": + line=line.replace(' "',' ') # remove all quotation marks with spaces before + line=line.replace('" ',' ') # remove all quotation marks with spaces after + line=line.replace(r'\"','"') # replace \" by " (for characters with diaeresis) + try: + [ucs4,command,dead] = line.split(None,2) + if command[0:1] != "\\": + continue + spec_chars.append([command, unichr(eval(ucs4))]) + except: + continue + m = r.match(command) + if m != None: + command = "\\\\" + # If the character is a double-quote, then we need to escape it, too, + # since it is done that way in the LyX file. + if m.group(1) == "\"": + command += "\\" + commandbl = command + command += m.group(1) + m.group(2) + commandbl += m.group(1) + ' ' + m.group(2) + spec_chars.append([command, unichr(eval(ucs4))]) + spec_chars.append([commandbl, unichr(eval(ucs4))]) + fp.close() + return spec_chars + + +unicode_reps = read_unicodesymbols() + + +def put_cmd_in_ert(string): + for rep in unicode_reps: + string = string.replace(rep[1], rep[0].replace('\\\\', '\\')) + string = string.replace('\\', "\\backslash\n") + string = "\\begin_inset ERT\nstatus collapsed\n\\begin_layout Standard\n" \ + + string + "\n\\end_layout\n\\end_inset" + return string + + +def lyx2latex(document, lines): + 'Convert some LyX stuff into corresponding LaTeX stuff, as best we can.' + # clean up multiline stuff + content = "" + ert_end = 0 + + for curline in range(len(lines)): + line = lines[curline] + if line.startswith("\\begin_inset ERT"): + # We don't want to replace things inside ERT, so figure out + # where the end of the inset is. + ert_end = find_end_of_inset(lines, curline + 1) + continue + elif line.startswith("\\begin_inset Formula"): + line = line[20:] + elif line.startswith("\\begin_inset Quotes"): + # For now, we do a very basic reversion. Someone who understands + # quotes is welcome to fix it up. + qtype = line[20:].strip() + # lang = qtype[0] + side = qtype[1] + dbls = qtype[2] + if side == "l": + if dbls == "d": + line = "``" + else: + line = "`" + else: + if dbls == "d": + line = "''" + else: + line = "'" + elif line.isspace() or \ + line.startswith("\\begin_layout") or \ + line.startswith("\\end_layout") or \ + line.startswith("\\begin_inset") or \ + line.startswith("\\end_inset") or \ + line.startswith("\\lang") or \ + line.strip() == "status collapsed" or \ + line.strip() == "status open": + #skip all that stuff + continue + + # this needs to be added to the preamble because of cases like + # \textmu, \textbackslash, etc. + add_to_preamble(document, ['% added by lyx2lyx for converted index entries', + '\\@ifundefined{textmu}', + ' {\\usepackage{textcomp}}{}']) + # a lossless reversion is not possible + # try at least to handle some common insets and settings + if ert_end >= curline: + line = line.replace(r'\backslash', r'\\') + else: + line = line.replace('&', '\\&{}') + line = line.replace('#', '\\#{}') + line = line.replace('^', '\\^{}') + line = line.replace('%', '\\%{}') + line = line.replace('_', '\\_{}') + line = line.replace('$', '\\${}') + + # Do the LyX text --> LaTeX conversion + for rep in unicode_reps: + line = line.replace(rep[1], rep[0] + "{}") + line = line.replace(r'\backslash', r'\textbackslash{}') + line = line.replace(r'\series bold', r'\bfseries{}').replace(r'\series default', r'\mdseries{}') + line = line.replace(r'\shape italic', r'\itshape{}').replace(r'\shape smallcaps', r'\scshape{}') + line = line.replace(r'\shape slanted', r'\slshape{}').replace(r'\shape default', r'\upshape{}') + line = line.replace(r'\emph on', r'\em{}').replace(r'\emph default', r'\em{}') + line = line.replace(r'\noun on', r'\scshape{}').replace(r'\noun default', r'\upshape{}') + line = line.replace(r'\bar under', r'\underbar{').replace(r'\bar default', r'}') + line = line.replace(r'\family sans', r'\sffamily{}').replace(r'\family default', r'\normalfont{}') + line = line.replace(r'\family typewriter', r'\ttfamily{}').replace(r'\family roman', r'\rmfamily{}') + line = line.replace(r'\InsetSpace ', r'').replace(r'\SpecialChar ', r'') + content += line + return content + + #################################################################### @@ -297,7 +426,7 @@ def revert_outputformat(document): def revert_backgroundcolor(document): - " Reverts backgrund color to preamble code " + " Reverts background color to preamble code " i = 0 colorcode = "" while True: @@ -331,6 +460,100 @@ def revert_backgroundcolor(document): + '\\pagecolor{page_backgroundcolor}\n') +def revert_splitindex(document): + " Reverts splitindex-aware documents " + i = find_token(document.header, '\\use_indices', 0) + if i == -1: + document.warning("Malformed LyX document: Missing \\use_indices.") + return + indices = get_value(document.header, "\\use_indices", i) + preamble = "" + if indices == "true": + preamble += "\\usepackage{splitidx}\n" + del document.header[i] + i = 0 + while True: + i = find_token(document.header, "\\index", i) + if i == -1: + break + k = find_token(document.header, "\\end_index", i) + if k == -1: + document.warning("Malformed LyX document: Missing \\end_index.") + return + line = document.header[i] + l = re.compile(r'\\index (.*)$') + m = l.match(line) + iname = m.group(1) + ishortcut = get_value(document.header, '\\shortcut', i, k) + if ishortcut != "" and indices == "true": + preamble += "\\newindex[" + iname + "]{" + ishortcut + "}\n" + del document.header[i:k+1] + i = 0 + if preamble != "": + insert_to_preamble(0, document, preamble) + i = 0 + while True: + i = find_token(document.body, "\\begin_inset Index", i) + if i == -1: + break + line = document.body[i] + l = re.compile(r'\\begin_inset Index (.*)$') + m = l.match(line) + itype = m.group(1) + if itype == "idx" or indices == "false": + document.body[i] = "\\begin_inset Index" + else: + k = find_end_of_inset(document.body, i) + if k == -1: + return + content = lyx2latex(document, document.body[i:k]) + # escape quotes + content = content.replace('"', r'\"') + subst = [put_cmd_in_ert("\\sindex[" + itype + "]{" + content + "}")] + document.body[i:k+1] = subst + i = i + 1 + i = 0 + while True: + i = find_token(document.body, "\\begin_inset CommandInset index_print", i) + if i == -1: + return + k = find_end_of_inset(document.body, i) + ptype = get_value(document.body, 'type', i, k).strip('"') + if ptype == "idx": + j = find_token(document.body, "type", i, k) + del document.body[j] + elif indices == "false": + del document.body[i:k+1] + else: + subst = [put_cmd_in_ert("\\printindex[" + ptype + "]{}")] + document.body[i:k+1] = subst + i = i + 1 + + +def convert_splitindex(document): + " Converts index and printindex insets to splitindex-aware format " + i = 0 + while True: + i = find_token(document.body, "\\begin_inset Index", i) + if i == -1: + break + document.body[i] = document.body[i].replace("\\begin_inset Index", + "\\begin_inset Index idx") + i = i + 1 + i = 0 + while True: + i = find_token(document.body, "\\begin_inset CommandInset index_print", i) + if i == -1: + return + if document.body[i + 1].find('LatexCommand printindex') == -1: + document.warning("Malformed LyX document: Incomplete printindex inset.") + return + subst = ["LatexCommand printindex", + "type \"idx\""] + document.body[i + 1:i + 2] = subst + i = i + 1 + + ## # Conversion hub # @@ -341,10 +564,12 @@ convert = [[346, []], [348, []], [349, []], [350, []], - [351, []] + [351, []], + [352, [convert_splitindex]] ] -revert = [[350, [revert_backgroundcolor]], +revert = [[351, [revert_splitindex]], + [350, [revert_backgroundcolor]], [349, [revert_outputformat]], [348, [revert_xetex]], [347, [revert_phantom, revert_hphantom, revert_vphantom]], diff --git a/lib/ui/stdcontext.inc b/lib/ui/stdcontext.inc index 84122b20d2..e0db52cb4b 100644 --- a/lib/ui/stdcontext.inc +++ b/lib/ui/stdcontext.inc @@ -469,4 +469,25 @@ Menuset Item "Settings...|S" "inset-settings" End +# +# Index context menu +# + + Menu "context-index" + IndicesContext + Separator + OptItem "Open Inset|O" "inset-toggle open" + OptItem "Close Inset|C" "inset-toggle close" + Separator + Item "Dissolve Inset|D" "inset-dissolve" + End + +# +# Index Lists context menu +# + + Menu "context-indexprint" + IndicesListsContext + End + End diff --git a/lib/ui/stdmenus.inc b/lib/ui/stdmenus.inc index 3188b6fd92..85ecdf445c 100644 --- a/lib/ui/stdmenus.inc +++ b/lib/ui/stdmenus.inc @@ -346,7 +346,7 @@ Menuset Item "Cross-Reference...|R" "dialog-show-new-inset ref" Item "Label...|L" "label-insert" Item "Caption" "caption-insert" - Item "Index Entry|d" "index-insert" + Indices Item "Nomenclature Entry...|y" "nomencl-insert" Separator Item "Table...|T" "tabular-insert" @@ -430,7 +430,7 @@ Menuset Menu "insert_toc" Item "Table of Contents|C" "toc-insert" FloatListInsert - Item "Index List|I" "index-print" + IndicesLists Item "Nomenclature|N" "nomencl-print" Item "BibTeX Bibliography...|B" "dialog-show-new-inset bibtex" End diff --git a/src/Buffer.cpp b/src/Buffer.cpp index eb03f06bf6..d277d96c06 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -32,6 +32,7 @@ #include "Format.h" #include "FuncRequest.h" #include "FuncStatus.h" +#include "IndicesList.h" #include "InsetIterator.h" #include "InsetList.h" #include "Language.h" @@ -124,7 +125,7 @@ namespace { // Do not remove the comment below, so we get merge conflict in // independent branches. Instead add your own. -int const LYX_FORMAT = 351; // uwestoehr: support for page background color +int const LYX_FORMAT = 352; // jspitzm: splitindex support typedef map DepClean; typedef map > RefCache; @@ -523,6 +524,7 @@ int Buffer::readHeader(Lexer & lex) params().clearLayoutModules(); params().clearRemovedModules(); params().pdfoptions().clear(); + params().indiceslist().clear(); for (int i = 0; i < 4; ++i) { params().user_defined_bullet(i) = ITEMIZE_DEFAULTS[i]; diff --git a/src/BufferParams.cpp b/src/BufferParams.cpp index 9492f00f15..31a24469e9 100644 --- a/src/BufferParams.cpp +++ b/src/BufferParams.cpp @@ -25,6 +25,7 @@ #include "Color.h" #include "ColorSet.h" #include "Encoding.h" +#include "IndicesList.h" #include "Language.h" #include "LaTeXFeatures.h" #include "ModuleList.h" @@ -283,6 +284,7 @@ public: BranchList branchlist; Bullet temp_bullets[4]; Bullet user_defined_bullets[4]; + IndicesList indiceslist; Spacing spacing; /** This is the amount of space used for paragraph_separation "skip", * and for detached paragraphs in "indented" documents. @@ -334,6 +336,7 @@ BufferParams::BufferParams() use_esint = package_auto; cite_engine_ = ENGINE_BASIC; use_bibtopic = false; + use_indices = false; trackChanges = false; outputChanges = false; use_default_options = true; @@ -363,6 +366,8 @@ BufferParams::BufferParams() user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter]; temp_bullet(iter) = ITEMIZE_DEFAULTS[iter]; } + // default index + indiceslist().addDefault(B_("Index")); } @@ -397,6 +402,18 @@ BranchList const & BufferParams::branchlist() const } +IndicesList & BufferParams::indiceslist() +{ + return pimpl_->indiceslist; +} + + +IndicesList const & BufferParams::indiceslist() const +{ + return pimpl_->indiceslist; +} + + Bullet & BufferParams::temp_bullet(lyx::size_type const index) { LASSERT(index < 4, /**/); @@ -572,6 +589,8 @@ string BufferParams::readToken(Lexer & lex, string const & token, cite_engine_ = citeenginetranslator().find(engine); } else if (token == "\\use_bibtopic") { lex >> use_bibtopic; + } else if (token == "\\use_indices") { + lex >> use_indices; } else if (token == "\\tracking_changes") { lex >> trackChanges; } else if (token == "\\output_changes") { @@ -604,6 +623,34 @@ string BufferParams::readToken(Lexer & lex, string const & token, lcolor.setColor(to_utf8(branch), color); } } + } else if (token == "\\index") { + lex.eatLine(); + docstring index = lex.getDocString(); + indiceslist().add(index); + while (true) { + lex.next(); + string const tok = lex.getString(); + if (tok == "\\end_index") + break; + Index * index_ptr = indiceslist().find(index); + if (tok == "\\shortcut") { + lex.next(); + if (index_ptr) + index_ptr->setShortcut(lex.getDocString()); + } + // not yet operational + if (tok == "\\color") { + lex.eatLine(); + string color = lex.getString(); + if (index_ptr) + index_ptr->setColor(color); + // Update also the Color table: + if (color == "none") + color = lcolor.getX11Name(Color_background); + // FIXME UNICODE + lcolor.setColor(to_utf8(index), color); + } + } } else if (token == "\\author") { lex.eatLine(); istringstream ss(lex.getString()); @@ -781,6 +828,7 @@ void BufferParams::writeFile(ostream & os) const << "\n\\use_esint " << use_esint << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_) << "\n\\use_bibtopic " << convert(use_bibtopic) + << "\n\\use_indices " << convert(use_indices) << "\n\\paperorientation " << string_orientation[orientation] << "\n\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n'; @@ -795,6 +843,16 @@ void BufferParams::writeFile(ostream & os) const << "\n"; } + IndicesList::const_iterator iit = indiceslist().begin(); + IndicesList::const_iterator iend = indiceslist().end(); + for (; iit != iend; ++iit) { + os << "\\index " << to_utf8(iit->index()) + << "\n\\shortcut " << to_utf8(iit->shortcut()) + << "\n\\color " << lyx::X11hexname(iit->color()) + << "\n\\end_index" + << "\n"; + } + if (!paperwidth.empty()) os << "\\paperwidth " << VSpace(paperwidth).asLyXCommand() << '\n'; @@ -1345,6 +1403,19 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, // The optional packages; lyxpreamble += from_ascii(features.getPackages()); + // Additional Indices + if (features.isRequired("splitidx")) { + IndicesList::const_iterator iit = indiceslist().begin(); + IndicesList::const_iterator iend = indiceslist().end(); + for (; iit != iend; ++iit) { + lyxpreamble += "\\newindex["; + lyxpreamble += iit->index(); + lyxpreamble += "]{"; + lyxpreamble += iit->shortcut(); + lyxpreamble += "}\n"; + } + } + // Line spacing lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace"))); diff --git a/src/BufferParams.h b/src/BufferParams.h index 40fee96f60..43beea44d4 100644 --- a/src/BufferParams.h +++ b/src/BufferParams.h @@ -36,6 +36,7 @@ class BranchList; class Bullet; class DocumentClass; class Encoding; +class IndicesList; class Language; class LatexFeatures; class LayoutFile; @@ -215,6 +216,9 @@ public: /// BranchList: BranchList & branchlist(); BranchList const & branchlist() const; + /// IndicesList: + IndicesList & indiceslist(); + IndicesList const & indiceslist() const; /** * The input encoding for LaTeX. This can be one of * - \c auto: find out the input encoding from the used languages @@ -278,8 +282,10 @@ public: Package use_amsmath; /// Whether and how to load esint Package use_esint; - /// + /// Split bibliography? bool use_bibtopic; + /// Split the index? + bool use_indices; /// revision tracking for this buffer ? bool trackChanges; /** This param decides whether change tracking marks should be used diff --git a/src/Converter.cpp b/src/Converter.cpp index a970faf38d..7c71cff525 100644 --- a/src/Converter.cpp +++ b/src/Converter.cpp @@ -325,6 +325,8 @@ bool Converters::convert(Buffer const * buffer, // used anyway. OutputParams runparams(buffer ? &buffer->params().encoding() : 0); runparams.flavor = getFlavor(edgepath); + + runparams.use_indices = buffer->params().use_indices; if (buffer) runparams.use_japanese = buffer->bufferFormat() == "platex"; diff --git a/src/IndicesList.cpp b/src/IndicesList.cpp new file mode 100644 index 0000000000..a73dbb90b0 --- /dev/null +++ b/src/IndicesList.cpp @@ -0,0 +1,235 @@ +/** + * \file IndicesList.cpp + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Jürgen Spitzmüller + * + * Full author contact details are available in file CREDITS. + */ + +#include + +#include "IndicesList.h" +#include "Color.h" + +#include "frontends/Application.h" + +#include "support/convert.h" +#include "support/lstrings.h" + +#include + +using namespace std; +using namespace lyx::support; + +namespace lyx { + +namespace { + +class IndexNamesEqual : public std::unary_function +{ +public: + IndexNamesEqual(docstring const & name) : name_(name) {} + + bool operator()(Index const & index) const + { + return index.index() == name_; + } +private: + docstring name_; +}; + + +class IndexHasShortcut : public std::unary_function +{ +public: + IndexHasShortcut(docstring const & shortcut) : shortc_(shortcut) {} + + bool operator()(Index const & index) const + { + return index.shortcut() == shortc_; + } +private: + docstring shortc_; +}; + +} + + +///////////////////////////////////////////////////////////////////// +// +// Index +// +///////////////////////////////////////////////////////////////////// + + +Index::Index() +{ + // no theApp() with command line export + if (theApp()) + theApp()->getRgbColor(Color_indexlabel, color_); +} + + +docstring const & Index::index() const +{ + return index_; +} + + +void Index::setIndex(docstring const & s) +{ + index_ = s; +} + + +docstring const & Index::shortcut() const +{ + return shortcut_; +} + + +void Index::setShortcut(docstring const & s) +{ + shortcut_ = s; +} + + +RGBColor const & Index::color() const +{ + return color_; +} + + +void Index::setColor(RGBColor const & c) +{ + color_ = c; +} + + +void Index::setColor(string const & str) +{ + if (str.size() == 7 && str[0] == '#') + color_ = rgbFromHexName(str); + else + // no color set or invalid color -- use predefined color + theApp()->getRgbColor(Color_indexlabel, color_); +} + + +///////////////////////////////////////////////////////////////////// +// +// IndicesList +// +///////////////////////////////////////////////////////////////////// + + +Index * IndicesList::find(docstring const & name) +{ + List::iterator it = + find_if(list.begin(), list.end(), IndexNamesEqual(name)); + return it == list.end() ? 0 : &*it; +} + + +Index const * IndicesList::find(docstring const & name) const +{ + List::const_iterator it = + find_if(list.begin(), list.end(), IndexNamesEqual(name)); + return it == list.end() ? 0 : &*it; +} + + +Index * IndicesList::findShortcut(docstring const & shortcut) +{ + List::iterator it = + find_if(list.begin(), list.end(), IndexHasShortcut(shortcut)); + return it == list.end() ? 0 : &*it; +} + + +Index const * IndicesList::findShortcut(docstring const & shortcut) const +{ + List::const_iterator it = + find_if(list.begin(), list.end(), IndexHasShortcut(shortcut)); + return it == list.end() ? 0 : &*it; +} + + +bool IndicesList::add(docstring const & n, docstring const & s) +{ + bool added = false; + size_t i = 0; + while (true) { + size_t const j = n.find_first_of(separator_, i); + docstring name; + if (j == docstring::npos) + name = n.substr(i); + else + name = n.substr(i, j - i); + // Is this name already in the list? + bool const already = + find_if(list.begin(), list.end(), + IndexNamesEqual(name)) != list.end(); + if (!already) { + added = true; + Index in; + in.setIndex(name); + docstring sc = s.empty() ? + trim(lowercase(name.substr(0, 3))) : s; + if (findShortcut(sc) != 0) { + int i = 1; + docstring scn = sc + convert(i); + while (findShortcut(scn) != 0) { + ++i; + scn = sc + convert(i); + } + in.setShortcut(scn); + } else + in.setShortcut(sc); + list.push_back(in); + } + if (j == docstring::npos) + break; + i = j + 1; + } + return added; +} + + +bool IndicesList::addDefault(docstring const & n) +{ + if (findShortcut(from_ascii("idx")) != 0) + // we already have a default + return false; + return add(n, from_ascii("idx")); +} + +bool IndicesList::remove(docstring const & s) +{ + size_t const size = list.size(); + list.remove_if(IndexNamesEqual(s)); + return size != list.size(); +} + + +bool IndicesList::rename(docstring const & oldname, + docstring const & newname) +{ + if (newname.empty()) + return false; + if (find_if(list.begin(), list.end(), + IndexNamesEqual(newname)) != list.end()) + // new name already taken + return false; + + Index * index = find(oldname); + if (!index) + return false; + index->setIndex(newname); + return true; +} + + +} // namespace lyx diff --git a/src/IndicesList.h b/src/IndicesList.h new file mode 100644 index 0000000000..019c54835d --- /dev/null +++ b/src/IndicesList.h @@ -0,0 +1,128 @@ +// -*- C++ -*- +/** + * \file IndicesList.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * \author Jürgen Spitzmüller + * + * Full author contact details are available in file CREDITS. + * + * + * \class Index + * + * A class describing an Index type, such as "Index of Names". + * Different Index types are used in splitted Indices + * + * An Index has a name and a shortcut notation. It uses a + * user-specifyable GUI colour. All these can be set and + * queried. + * + * \class IndicesList + * + * A class containing a vector of all defined indices within a + * document. Has methods for outputting a '|'-separated string + * of all elements, and for adding, removing and renaming elements. + */ + + +#ifndef INDICESLIST_H +#define INDICESLIST_H + +#include "ColorCode.h" + +#include "support/docstring.h" + +#include + + +namespace lyx { + +class Index { +public: + /// + Index(); + /// + docstring const & index() const; + /// + void setIndex(docstring const &); + /// + docstring const & shortcut() const; + /// + void setShortcut(docstring const &); + /// + RGBColor const & color() const; + /// + void setColor(RGBColor const &); + /** + * Set color from a string "#rrggbb". + * Use Color:background if the string is no valid color. + * This ensures compatibility with LyX 1.4.0 that had the symbolic + * color "none" that was displayed as Color:background. + */ + void setColor(std::string const &); + +private: + /// + docstring index_; + /// + docstring shortcut_; + /// + RGBColor color_; +}; + + +class IndicesList { + /// + typedef std::list List; +public: + typedef List::const_iterator const_iterator; + + /// + IndicesList() : separator_(from_ascii("|")) {} + + /// + bool empty() const { return list.empty(); } + /// + void clear() { list.clear(); } + /// + const_iterator begin() const { return list.begin(); } + const_iterator end() const { return list.end(); } + + /** \returns the Index with \c name. If not found, returns 0. + */ + Index * find(docstring const & name); + Index const * find(docstring const & name) const; + + /** \returns the Index with the shortcut \c shortcut. + * If not found, returns 0. + */ + Index * findShortcut(docstring const & shortcut); + Index const * findShortcut(docstring const & shortcut) const; + + /** Add (possibly multiple (separated by separator())) indices to list + * \returns true if an index is added. + */ + bool add(docstring const & n, docstring const & s = docstring()); + /** Add the default index (if not already there) + * \returns true if an index is added. + */ + bool addDefault(docstring const & n); + /** remove an index from list by name + * \returns true if an index is removed. + */ + bool remove(docstring const &); + /** rename an index in list + * \returns true if renaming succeeded. + */ + bool rename(docstring const &, docstring const &); + +private: + /// + List list; + /// + docstring separator_; +}; + +} // namespace lyx + +#endif // INDICESLIST_H diff --git a/src/LaTeX.cpp b/src/LaTeX.cpp index d7fe03f770..6bd55e8216 100644 --- a/src/LaTeX.cpp +++ b/src/LaTeX.cpp @@ -416,9 +416,11 @@ bool LaTeX::runMakeIndex(string const & f, OutputParams const & runparams, "idx file has been made, running makeindex on file " << f); string tmp = runparams.use_japanese ? lyxrc.jindex_command : lyxrc.index_command; - tmp += ' '; tmp = subst(tmp, "$$lang", runparams.document_language); + if (runparams.use_indices) + tmp = lyxrc.splitindex_command + " -m " + quoteName(tmp); + tmp += ' '; tmp += quoteName(f); tmp += params; Systemcall one; diff --git a/src/LaTeXFeatures.cpp b/src/LaTeXFeatures.cpp index 79ef3e4520..efc3fc6a3b 100644 --- a/src/LaTeXFeatures.cpp +++ b/src/LaTeXFeatures.cpp @@ -619,9 +619,11 @@ string const LaTeXFeatures::getPackages() const // [x]color and pdfcolmk are handled in getColorOptions() above // makeidx.sty - if (isRequired("makeidx")) { - if (!tclass.provides("makeidx")) + if (isRequired("makeidx") || isRequired("splitidx")) { + if (!tclass.provides("makeidx") && !isRequired("splitidx")) packages << "\\usepackage{makeidx}\n"; + if (!tclass.provides("splitidx") && isRequired("splitidx")) + packages << "\\usepackage{splitidx}\n"; packages << "\\makeindex\n"; } diff --git a/src/LyXAction.cpp b/src/LyXAction.cpp index 36a79cc5c9..5f0bdae955 100644 --- a/src/LyXAction.cpp +++ b/src/LyXAction.cpp @@ -515,7 +515,9 @@ void LyXAction::init() * \var lyx::FuncCode lyx::LFUN_INDEX_INSERT * \li Action: Inserts Index entry. * \li Notion: It automatically takes the word on the cursor position. - * \li Syntax: index-insert + * \li Syntax: index-insert [] + * \li Params: : name of the index, if multiple indices are defined. + with an empty argument, the default index is selected. * \li Origin: leeming, 3 Aug 2000 * \endvar */ @@ -523,7 +525,9 @@ void LyXAction::init() /*! * \var lyx::FuncCode lyx::LFUN_INDEX_PRINT * \li Action: Inserts list of Index entries on a new page. - * \li Syntax: index-print + * \li Syntax: index-print [] + * \li Params: : name of the index, if multiple indices are defined. + with an empty argument, the default index is selected. * \li Origin: Lgb, 27 Feb 1997 * \endvar */ diff --git a/src/LyXFunc.cpp b/src/LyXFunc.cpp index 59d6215989..4c1d579c42 100644 --- a/src/LyXFunc.cpp +++ b/src/LyXFunc.cpp @@ -1977,6 +1977,7 @@ void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new) case LyXRC::RC_OPEN_BUFFERS_IN_TABS: case LyXRC::RC_SPELL_COMMAND: case LyXRC::RC_SPELLCHECK_CONTINUOUSLY: + case LyXRC::RC_SPLITINDEX_COMMAND: case LyXRC::RC_TEMPDIRPATH: case LyXRC::RC_TEMPLATEPATH: case LyXRC::RC_TEX_ALLOWS_SPACES: diff --git a/src/LyXRC.cpp b/src/LyXRC.cpp index b1240cd069..121b9f896e 100644 --- a/src/LyXRC.cpp +++ b/src/LyXRC.cpp @@ -165,6 +165,7 @@ LexerKeyword lyxrcTags[] = { { "\\sort_layouts", LyXRC::RC_SORT_LAYOUTS }, { "\\spell_command", LyXRC::RC_SPELL_COMMAND }, { "\\spellcheck_continuously", LyXRC::RC_SPELLCHECK_CONTINUOUSLY }, + { "\\splitindex_command", LyXRC::RC_SPLITINDEX_COMMAND }, { "\\tempdir_path", LyXRC::RC_TEMPDIRPATH }, { "\\template_path", LyXRC::RC_TEMPLATEPATH }, { "\\tex_allows_spaces", LyXRC::RC_TEX_ALLOWS_SPACES }, @@ -615,6 +616,12 @@ int LyXRC::read(Lexer & lexrc) } break; + case RC_SPLITINDEX_COMMAND: + if (lexrc.next(true)) { + splitindex_command = lexrc.getString(); + } + break; + case RC_NOMENCL_COMMAND: if (lexrc.next(true)) { nomencl_command = lexrc.getString(); @@ -1372,6 +1379,13 @@ void LyXRC::write(ostream & os, bool ignore_system_lyxrc, string const & name) c } if (tag != RC_LAST) break; + case RC_SPLITINDEX_COMMAND: + if (ignore_system_lyxrc || + splitindex_command != system_lyxrc.splitindex_command) { + os << "\\splitindex_command \"" << escapeCommand(splitindex_command) << "\"\n"; + } + if (tag != RC_LAST) + break; case RC_NOMENCL_COMMAND: if (ignore_system_lyxrc || nomencl_command != system_lyxrc.nomencl_command) { diff --git a/src/LyXRC.h b/src/LyXRC.h index d8fee9d082..a51d63fffc 100644 --- a/src/LyXRC.h +++ b/src/LyXRC.h @@ -149,6 +149,7 @@ public: RC_SORT_LAYOUTS, RC_SPELL_COMMAND, RC_SPELLCHECK_CONTINUOUSLY, + RC_SPLITINDEX_COMMAND, RC_TEMPDIRPATH, RC_TEMPLATEPATH, RC_TEX_ALLOWS_SPACES, @@ -252,6 +253,8 @@ public: std::string index_command; /// command to run japanese index program incl. options std::string jindex_command; + /// command to generate multiple indices + std::string splitindex_command; /// command to run makeindex incl. options for nomencl std::string nomencl_command; /// diff --git a/src/Makefile.am b/src/Makefile.am index d4f233b5f9..f0263553d4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -111,6 +111,7 @@ SOURCEFILESCORE = \ FuncRequest.cpp \ FuncStatus.cpp \ Graph.cpp \ + IndicesList.cpp \ InsetIterator.cpp \ InsetList.cpp \ Intl.cpp \ @@ -209,6 +210,7 @@ HEADERFILESCORE = \ FuncRequest.h \ FuncStatus.h \ Graph.h \ + IndicesList.h \ InsetIterator.h \ InsetList.h \ Intl.h \ diff --git a/src/OutputParams.cpp b/src/OutputParams.cpp index 498c65148c..564232b4ba 100644 --- a/src/OutputParams.cpp +++ b/src/OutputParams.cpp @@ -21,7 +21,7 @@ namespace lyx { OutputParams::OutputParams(Encoding const * enc) : flavor(LATEX), nice(false), moving_arg(false), local_font(0), encoding(enc), free_spacing(false), use_babel(false), - use_japanese(false), linelen(0), depth(0), + use_indices(false), use_japanese(false), linelen(0), depth(0), exportdata(new ExportData), inComment(false), inTableCell(NO), inFloat(NONFLOAT), inDeletedInset(0), changeOfDeletedInset(Change::UNCHANGED), diff --git a/src/OutputParams.h b/src/OutputParams.h index cc0f01548e..f0c06dc846 100644 --- a/src/OutputParams.h +++ b/src/OutputParams.h @@ -111,6 +111,10 @@ public: */ bool use_babel; + /** Are we generating multiple indices? + */ + bool use_indices; + /** Are we using japanese (pLaTeX)? */ bool use_japanese; diff --git a/src/Text3.cpp b/src/Text3.cpp index 3ac094d033..1b9b40aa00 100644 --- a/src/Text3.cpp +++ b/src/Text3.cpp @@ -1537,7 +1537,18 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) break; } - case LFUN_INDEX_PRINT: + case LFUN_INDEX_PRINT: { + InsetCommandParams p(INDEX_PRINT_CODE); + if (cmd.argument().empty()) + p["type"] = from_ascii("idx"); + else + p["type"] = cmd.argument(); + string const data = InsetCommand::params2string("index_print", p); + FuncRequest fr(LFUN_INSET_INSERT, data); + dispatch(cur, fr); + break; + } + case LFUN_NOMENCL_PRINT: case LFUN_TOC_INSERT: case LFUN_LINE_INSERT: diff --git a/src/factory.cpp b/src/factory.cpp index e390b228c8..641d96cfb6 100644 --- a/src/factory.cpp +++ b/src/factory.cpp @@ -177,8 +177,10 @@ Inset * createInsetHelper(Buffer & buf, FuncRequest const & cmd) return 0; } - case LFUN_INDEX_INSERT: - return new InsetIndex(buf); + case LFUN_INDEX_INSERT: { + docstring arg = cmd.argument(); + return new InsetIndex(buf, InsetIndexParams(arg)); + } case LFUN_NOMENCL_INSERT: { InsetCommandParams icp(NOMENCL_CODE); @@ -202,8 +204,11 @@ Inset * createInsetHelper(Buffer & buf, FuncRequest const & cmd) case LFUN_CAPTION_INSERT: return new InsetCaption(buf); - case LFUN_INDEX_PRINT: - return new InsetPrintIndex(InsetCommandParams(INDEX_PRINT_CODE)); + case LFUN_INDEX_PRINT: { + InsetCommandParams icp(INDEX_PRINT_CODE); + icp["type"] = cmd.argument(); + return new InsetPrintIndex(icp); + } case LFUN_NOMENCL_PRINT: return new InsetPrintNomencl(InsetCommandParams(NOMENCL_PRINT_CODE)); @@ -283,8 +288,16 @@ Inset * createInsetHelper(Buffer & buf, FuncRequest const & cmd) return new InsetInclude(icp); } - case INDEX_CODE: - return new InsetIndex(buf); + case INDEX_CODE: { + docstring arg = cmd.argument(); + return new InsetIndex(buf, InsetIndexParams(arg)); + } + + case INDEX_PRINT_CODE: { + InsetCommandParams icp(code); + InsetCommand::string2params(name, to_utf8(cmd.argument()), icp); + return new InsetPrintIndex(icp); + } case NOMENCL_CODE: { InsetCommandParams icp(code); @@ -566,7 +579,7 @@ Inset * readInset(Lexer & lex, Buffer const & buf) } else if (tmptok == "Caption") { inset.reset(new InsetCaption(buf)); } else if (tmptok == "Index") { - inset.reset(new InsetIndex(buf)); + inset.reset(new InsetIndex(buf, InsetIndexParams())); } else if (tmptok == "FloatList") { inset.reset(new InsetFloatList); } else if (tmptok == "Info") { diff --git a/src/frontends/qt4/GuiDocument.cpp b/src/frontends/qt4/GuiDocument.cpp index b74e6536f0..c5a63ce661 100644 --- a/src/frontends/qt4/GuiDocument.cpp +++ b/src/frontends/qt4/GuiDocument.cpp @@ -15,6 +15,7 @@ #include "GuiApplication.h" #include "GuiBranches.h" +#include "GuiIndices.h" #include "GuiSelectionManager.h" #include "LaTeXHighlighter.h" #include "LengthCombo.h" @@ -33,6 +34,7 @@ #include "FloatPlacement.h" #include "Format.h" #include "FuncRequest.h" +#include "IndicesList.h" #include "Language.h" #include "LaTeXFeatures.h" #include "Layout.h" @@ -862,6 +864,11 @@ GuiDocument::GuiDocument(GuiView & lv) biblioModule->citeStyleCO->addItem(qt_("Numerical")); biblioModule->citeStyleCO->setCurrentIndex(0); + // indices + indicesModule = new GuiIndices; + connect(indicesModule, SIGNAL(changed()), + this, SLOT(change_adaptor())); + mathsModule = new UiWidget; connect(mathsModule->amsautoCB, SIGNAL(toggled(bool)), @@ -1006,6 +1013,7 @@ GuiDocument::GuiDocument(GuiView & lv) docPS->addPanel(langModule, qt_("Language")); docPS->addPanel(numberingModule, qt_("Numbering & TOC")); docPS->addPanel(biblioModule, qt_("Bibliography")); + docPS->addPanel(indicesModule, qt_("Indices")); docPS->addPanel(pdfSupportModule, qt_("PDF Properties")); docPS->addPanel(mathsModule, qt_("Math Options")); docPS->addPanel(floatModule, qt_("Float Placement")); @@ -1713,6 +1721,9 @@ void GuiDocument::applyView() bp_.use_bibtopic = biblioModule->bibtopicCB->isChecked(); + // Indices + indicesModule->apply(bp_); + // language & quotes if (langModule->defaultencodingRB->isChecked()) { bp_.inputenc = "auto"; @@ -2047,6 +2058,9 @@ void GuiDocument::paramsToDialog() biblioModule->bibtopicCB->setChecked( bp_.use_bibtopic); + // indices + indicesModule->update(bp_); + // language & quotes int const pos = langModule->languageCO->findData(toqstr( bp_.language->lang())); @@ -2618,6 +2632,20 @@ void GuiDocument::dispatchParams() dispatch(FuncRequest(LFUN_ALL_INSETS_TOGGLE, "assign branch")); } + // Generate the colours requested by indices. + IndicesList & indiceslist = params().indiceslist(); + if (!indiceslist.empty()) { + IndicesList::const_iterator it = indiceslist.begin(); + IndicesList::const_iterator const end = indiceslist.end(); + for (; it != end; ++it) { + docstring const & current_index = it->index(); + Index const * index = indiceslist.find(current_index); + string const x11hexname = X11hexname(index->color()); + // display the new color + docstring const str = current_index + ' ' + from_ascii(x11hexname); + dispatch(FuncRequest(LFUN_SET_COLOR, str)); + } + } // FIXME: If we used an LFUN, we would not need those two lines: BufferView * bv = const_cast(bufferview()); bv->processUpdateFlags(Update::Force | Update::FitCursor); diff --git a/src/frontends/qt4/GuiDocument.h b/src/frontends/qt4/GuiDocument.h index 43cb9a265b..e2075759c5 100644 --- a/src/frontends/qt4/GuiDocument.h +++ b/src/frontends/qt4/GuiDocument.h @@ -48,6 +48,7 @@ class TextClass; namespace frontend { class GuiBranches; +class GuiIndices; class ModuleSelectionManager; class PreambleModule; @@ -119,9 +120,10 @@ private: UiWidget *pdfSupportModule; UiWidget *modulesModule; UiWidget *outputModule; - PreambleModule *preambleModule; + PreambleModule * preambleModule; - GuiBranches *branchesModule; + GuiBranches * branchesModule; + GuiIndices * indicesModule; BulletsModule * bulletsModule; FloatPlacement * floatModule; diff --git a/src/frontends/qt4/GuiIndices.cpp b/src/frontends/qt4/GuiIndices.cpp new file mode 100644 index 0000000000..ef7632134a --- /dev/null +++ b/src/frontends/qt4/GuiIndices.cpp @@ -0,0 +1,217 @@ +/** + * \file GuiIndices.cpp + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Edwin Leuven + * \author Jürgen Spitzmüller + * \author Abdelrazak Younes + * + * Full author contact details are available in file CREDITS. + */ + +#include + +#include "GuiIndices.h" + +#include "ColorCache.h" +#include "GuiApplication.h" +#include "Validator.h" +#include "qt_helpers.h" + +#include "frontends/alert.h" + +#include "BufferParams.h" + +#include "support/gettext.h" +#include "support/lstrings.h" + +#include +#include +#include +#include +#include +#include + + +namespace lyx { +namespace frontend { + + +GuiIndices::GuiIndices(QWidget * parent) + : QWidget(parent) +{ + setupUi(this); + indicesTW->setColumnCount(2); + indicesTW->headerItem()->setText(0, qt_("Name")); + indicesTW->headerItem()->setText(1, qt_("Label Color")); + indicesTW->setSortingEnabled(true); +} + +void GuiIndices::update(BufferParams const & params) +{ + indiceslist_ = params.indiceslist(); + multipleIndicesCB->setChecked( + params.use_indices); + bool const state = params.use_indices; + indicesTW->setEnabled(state); + newIndexLE->setEnabled(state); + newIndexLA->setEnabled(state); + addIndexPB->setEnabled(state); + availableLA->setEnabled(state); + removePB->setEnabled(state); + colorPB->setEnabled(state); + updateView(); +} + + +void GuiIndices::updateView() +{ + // store the selected index + QTreeWidgetItem * item = indicesTW->currentItem(); + QString sel_index; + if (item != 0) + sel_index = item->text(0); + + indicesTW->clear(); + + IndicesList::const_iterator it = indiceslist_.begin(); + IndicesList::const_iterator const end = indiceslist_.end(); + for (; it != end; ++it) { + QTreeWidgetItem * newItem = new QTreeWidgetItem(indicesTW); + + QString const iname = toqstr(it->index()); + newItem->setText(0, iname); + + QColor const itemcolor = rgb2qcolor(it->color()); + if (itemcolor.isValid()) { + QPixmap coloritem(30, 10); + coloritem.fill(itemcolor); + newItem->setIcon(1, QIcon(coloritem)); + } + // restore selected index + if (iname == sel_index) { + indicesTW->setCurrentItem(newItem); + indicesTW->setItemSelected(newItem, true); + } + } + // emit signal + changed(); +} + + +void GuiIndices::apply(BufferParams & params) const +{ + params.use_indices = multipleIndicesCB->isChecked(); + params.indiceslist() = indiceslist_; +} + + +void GuiIndices::on_addIndexPB_pressed() +{ + QString const new_index = newIndexLE->text(); + if (!new_index.isEmpty()) { + indiceslist_.add(qstring_to_ucs4(new_index)); + newIndexLE->clear(); + updateView(); + } +} + + +void GuiIndices::on_removePB_pressed() +{ + QTreeWidgetItem * selItem = indicesTW->currentItem(); + QString sel_index; + if (selItem != 0) + sel_index = selItem->text(0); + if (!sel_index.isEmpty()) { + if (indiceslist_.find(qstring_to_ucs4(sel_index)) == + indiceslist_.findShortcut(from_ascii("idx"))) { + Alert::error(_("Cannot remove standard index"), + _("The default index cannot be removed.")); + return; + } + indiceslist_.remove(qstring_to_ucs4(sel_index)); + newIndexLE->clear(); + updateView(); + } +} + + +void GuiIndices::on_renamePB_clicked() +{ + QTreeWidgetItem * selItem = indicesTW->currentItem(); + QString sel_index; + if (selItem != 0) + sel_index = selItem->text(0); + if (!sel_index.isEmpty()) { + docstring newname; + bool success = false; + if (Alert::askForText(newname, _("Enter new index name"))) { + success = indiceslist_.rename(qstring_to_ucs4(sel_index), newname); + newIndexLE->clear(); + updateView(); + } + if (!success) + Alert::error(_("Renaming failed"), + _("The index could not be renamed. " + "Check if the new name already exists.")); + } +} + + +void GuiIndices::on_indicesTW_itemDoubleClicked(QTreeWidgetItem * item, int /*col*/) +{ + toggleColor(item); +} + + +void GuiIndices::on_colorPB_clicked() +{ + toggleColor(indicesTW->currentItem()); +} + + +void GuiIndices::on_multipleIndicesCB_toggled(bool const state) +{ + indicesTW->setEnabled(state); + newIndexLE->setEnabled(state); + newIndexLA->setEnabled(state); + addIndexPB->setEnabled(state); + availableLA->setEnabled(state); + removePB->setEnabled(state); + colorPB->setEnabled(state); + // emit signal + changed(); +} + + +void GuiIndices::toggleColor(QTreeWidgetItem * item) +{ + if (item == 0) + return; + + QString sel_index = item->text(0); + if (sel_index.isEmpty()) + return; + + docstring current_index = qstring_to_ucs4(sel_index); + Index * index = indiceslist_.find(current_index); + if (!index) + return; + + QColor const initial = rgb2qcolor(index->color()); + QColor ncol = QColorDialog::getColor(initial, qApp->focusWidget()); + if (!ncol.isValid()) + return; + + // add the color to the indiceslist + index->setColor(fromqstr(ncol.name())); + newIndexLE->clear(); + updateView(); +} + +} // namespace frontend +} // namespace lyx + +#include "moc_GuiIndices.cpp" diff --git a/src/frontends/qt4/GuiIndices.h b/src/frontends/qt4/GuiIndices.h new file mode 100644 index 0000000000..87d946fa51 --- /dev/null +++ b/src/frontends/qt4/GuiIndices.h @@ -0,0 +1,62 @@ +// -*- C++ -*- +/** + * \file GuiIndices.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Edwin Leuven + * \author Jürgen Spitzmüller + * + * Full author contact details are available in file CREDITS. + */ + +#ifndef GUIINDICES_H +#define GUIINDICES_H + +#include "GuiDocument.h" +#include "ui_IndicesUi.h" +#include "IndicesList.h" + +#include + +class QTreeWidgetItem; + +namespace lyx { + +class BufferParams; + +namespace frontend { + +class GuiIndices : public QWidget, public Ui::IndicesUi +{ + Q_OBJECT +public: + GuiIndices(QWidget * parent = 0); + + void update(BufferParams const & params); + void apply(BufferParams & params) const; + +Q_SIGNALS: + void changed(); + +protected: + void toggleColor(QTreeWidgetItem *); + void updateView(); + +protected Q_SLOTS: + void on_addIndexPB_pressed(); + void on_renamePB_clicked(); + void on_removePB_pressed(); + void on_indicesTW_itemDoubleClicked(QTreeWidgetItem *, int); + void on_colorPB_clicked(); + void on_multipleIndicesCB_toggled(bool); + +private: + /// Contains all legal indices for this doc + IndicesList indiceslist_; +}; + +} // namespace frontend +} // namespace lyx + +#endif // GUIINDICES_H diff --git a/src/frontends/qt4/Makefile.am b/src/frontends/qt4/Makefile.am index d44cfe4579..084cf8f2eb 100644 --- a/src/frontends/qt4/Makefile.am +++ b/src/frontends/qt4/Makefile.am @@ -90,6 +90,7 @@ SOURCEFILES = \ GuiIdListModel.cpp \ GuiImage.cpp \ GuiInclude.cpp \ + GuiIndices.cpp \ GuiInfo.cpp \ GuiKeySymbol.cpp \ GuiLabel.cpp \ @@ -186,6 +187,7 @@ MOCHEADER = \ GuiHSpace.h \ GuiHyperlink.h \ GuiInclude.h \ + GuiIndices.h \ GuiInfo.h \ GuiLabel.h \ GuiListings.h \ @@ -254,6 +256,7 @@ UIFILES = \ HSpaceUi.ui \ HyperlinkUi.ui \ IncludeUi.ui \ + IndicesUi.ui \ InfoUi.ui \ LabelUi.ui \ LanguageUi.ui \ diff --git a/src/frontends/qt4/Menus.cpp b/src/frontends/qt4/Menus.cpp index 3aae083995..5df6e4e8c4 100644 --- a/src/frontends/qt4/Menus.cpp +++ b/src/frontends/qt4/Menus.cpp @@ -36,6 +36,7 @@ #include "Format.h" #include "FuncRequest.h" #include "FuncStatus.h" +#include "IndicesList.h" #include "KeyMap.h" #include "Lexer.h" #include "LyXAction.h" @@ -148,6 +149,14 @@ public: Toolbars, /** Available branches in document */ Branches, + /** Available indices in document */ + Indices, + /** Context menu for indices in document */ + IndicesContext, + /** Available index lists in document */ + IndicesLists, + /** Context menu for available indices lists in document */ + IndicesListsContext, /** Available citation styles for a given citation */ CiteStyles, /** Available graphics groups */ @@ -304,6 +313,8 @@ public: void expandPasteRecent(Buffer const * buf); void expandToolbars(); void expandBranches(Buffer const * buf); + void expandIndices(Buffer const * buf, bool listof = false); + void expandIndicesContext(Buffer const * buf, bool listof = false); void expandCiteStyles(BufferView const *); void expandGraphicsGroups(BufferView const *); /// @@ -395,6 +406,10 @@ void MenuDefinition::read(Lexer & lex) md_endmenu, md_exportformats, md_importformats, + md_indices, + md_indicescontext, + md_indiceslists, + md_indiceslistscontext, md_lastfiles, md_optitem, md_optsubmenu, @@ -424,6 +439,10 @@ void MenuDefinition::read(Lexer & lex) { "floatlistinsert", md_floatlistinsert }, { "graphicsgroups", md_graphicsgroups }, { "importformats", md_importformats }, + { "indices", md_indices }, + { "indicescontext", md_indicescontext }, + { "indiceslists", md_indiceslists }, + { "indiceslistscontext", md_indiceslistscontext }, { "item", md_item }, { "lastfiles", md_lastfiles }, { "optitem", md_optitem }, @@ -538,6 +557,22 @@ void MenuDefinition::read(Lexer & lex) add(MenuItem(MenuItem::GraphicsGroups)); break; + case md_indices: + add(MenuItem(MenuItem::Indices)); + break; + + case md_indicescontext: + add(MenuItem(MenuItem::IndicesContext)); + break; + + case md_indiceslists: + add(MenuItem(MenuItem::IndicesLists)); + break; + + case md_indiceslistscontext: + add(MenuItem(MenuItem::IndicesListsContext)); + break; + case md_optsubmenu: optional = true; // fallback to md_submenu @@ -1099,6 +1134,78 @@ void MenuDefinition::expandBranches(Buffer const * buf) } +void MenuDefinition::expandIndices(Buffer const * buf, bool listof) +{ + if (!buf) + return; + + BufferParams const & params = buf->masterBuffer()->params(); + if (!params.use_indices) { + if (listof) + addWithStatusCheck(MenuItem(MenuItem::Command, + qt_("Index List|I"), + FuncRequest(LFUN_INDEX_PRINT, + from_ascii("idx")))); + else + addWithStatusCheck(MenuItem(MenuItem::Command, + qt_("Index Entry|d"), + FuncRequest(LFUN_INDEX_INSERT, + from_ascii("idx")))); + return; + } + + if (params.indiceslist().empty()) + return; + + IndicesList::const_iterator cit = params.indiceslist().begin(); + IndicesList::const_iterator end = params.indiceslist().end(); + + for (int ii = 1; cit != end; ++cit, ++ii) { + if (listof) + addWithStatusCheck(MenuItem(MenuItem::Command, toqstr(cit->index()), + FuncRequest(LFUN_INDEX_PRINT, + cit->shortcut()))); + else { + docstring label = _("Index Entry"); + label += " (" + cit->index() + ")"; + addWithStatusCheck(MenuItem(MenuItem::Command, toqstr(label), + FuncRequest(LFUN_INDEX_INSERT, + cit->shortcut()))); + } + } +} + + +void MenuDefinition::expandIndicesContext(Buffer const * buf, bool listof) +{ + if (!buf) + return; + + BufferParams const & params = buf->masterBuffer()->params(); + if (!params.use_indices || params.indiceslist().empty()) + return; + + IndicesList::const_iterator cit = params.indiceslist().begin(); + IndicesList::const_iterator end = params.indiceslist().end(); + + for (int ii = 1; cit != end; ++cit, ++ii) { + if (listof) { + InsetCommandParams p(INDEX_PRINT_CODE); + p["type"] = cit->shortcut(); + string const data = InsetCommand::params2string("index_print", p); + addWithStatusCheck(MenuItem(MenuItem::Command, toqstr(cit->index()), + FuncRequest(LFUN_NEXT_INSET_MODIFY, data))); + } else { + docstring label = _("Index Entry"); + label += " (" + cit->index() + ")"; + addWithStatusCheck(MenuItem(MenuItem::Command, toqstr(label), + FuncRequest(LFUN_NEXT_INSET_MODIFY, + from_ascii("changetype ") + cit->shortcut()))); + } + } +} + + void MenuDefinition::expandCiteStyles(BufferView const * bv) { if (!bv) @@ -1251,7 +1358,7 @@ struct Menus::Impl { /// Expands some special entries of the menu /** The entries with the following kind are expanded to a sequence of Command MenuItems: Lastfiles, Documents, - ViewFormats, ExportFormats, UpdateFormats, Branches + ViewFormats, ExportFormats, UpdateFormats, Branches, Indices */ void expand(MenuDefinition const & frommenu, MenuDefinition & tomenu, BufferView const *) const; @@ -1426,6 +1533,22 @@ void Menus::Impl::expand(MenuDefinition const & frommenu, tomenu.expandBranches(buf); break; + case MenuItem::Indices: + tomenu.expandIndices(buf); + break; + + case MenuItem::IndicesContext: + tomenu.expandIndicesContext(buf); + break; + + case MenuItem::IndicesLists: + tomenu.expandIndices(buf, true); + break; + + case MenuItem::IndicesListsContext: + tomenu.expandIndicesContext(buf, true); + break; + case MenuItem::CiteStyles: tomenu.expandCiteStyles(bv); break; diff --git a/src/frontends/qt4/ui/IndicesUi.ui b/src/frontends/qt4/ui/IndicesUi.ui new file mode 100644 index 0000000000..c9407d783d --- /dev/null +++ b/src/frontends/qt4/ui/IndicesUi.ui @@ -0,0 +1,142 @@ + + IndicesUi + + + + 0 + 0 + 401 + 340 + + + + + + + + 9 + + + 6 + + + + + 0 + + + 6 + + + + + &New: + + + newIndexLE + + + + + + + Enter the name of the desired index (e.g. "Index of Names") and hit "Add" + + + + + + + Add a new branch to the list + + + &Add + + + + + + + + + Remove the selected index + + + &Remove + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 121 + + + + + + + + A&vailable Indices: + + + indicesTW + + + + + + + + + + Check if you need multiple indices (e.g., an Index of Names) + + + &Use multiple indices + + + + + + + Qt::Horizontal + + + + + + + Define or change button color + + + Alter Co&lor... + + + + + + + Rename the selected index + + + R&ename... + + + + + + + qt_i18n.h + + + + diff --git a/src/insets/InsetIndex.cpp b/src/insets/InsetIndex.cpp index 998089be3a..495b612e9f 100644 --- a/src/insets/InsetIndex.cpp +++ b/src/insets/InsetIndex.cpp @@ -4,6 +4,7 @@ * Licence details can be found in the file COPYING. * * \author Lars Gullik Bjønnes + * \author Jürgen Spitzmüller * * Full author contact details are available in file CREDITS. */ @@ -12,11 +13,15 @@ #include "InsetIndex.h" #include "Buffer.h" +#include "BufferParams.h" +#include "ColorSet.h" #include "DispatchResult.h" #include "Encoding.h" #include "FuncRequest.h" #include "FuncStatus.h" +#include "IndicesList.h" #include "LaTeXFeatures.h" +#include "Lexer.h" #include "MetricsInfo.h" #include "sgml.h" #include "TocBackend.h" @@ -42,16 +47,23 @@ namespace lyx { /////////////////////////////////////////////////////////////////////// -InsetIndex::InsetIndex(Buffer const & buf) - : InsetCollapsable(buf) +InsetIndex::InsetIndex(Buffer const & buf, InsetIndexParams const & params) + : InsetCollapsable(buf), params_(params) {} int InsetIndex::latex(odocstream & os, OutputParams const & runparams) const { - os << "\\index"; - os << '{'; + if (buffer().masterBuffer()->params().use_indices && !params_.index.empty() + && params_.index != "idx") { + os << "\\sindex["; + os << params_.index; + os << "]{"; + } else { + os << "\\index"; + os << '{'; + } int i = 0; // get contents of InsetText as LaTeX and plaintext @@ -158,13 +170,99 @@ int InsetIndex::docbook(odocstream & os, OutputParams const & runparams) const } +void InsetIndex::doDispatch(Cursor & cur, FuncRequest & cmd) +{ + switch (cmd.action) { + + case LFUN_INSET_MODIFY: { + if (cmd.getArg(0) == "changetype") { + params_.index = from_utf8(cmd.getArg(1)); + setLayout(cur.buffer()->params()); + break; + } + } + + default: + InsetCollapsable::doDispatch(cur, cmd); + break; + } +} + + +bool InsetIndex::getStatus(Cursor & cur, FuncRequest const & cmd, + FuncStatus & flag) const +{ + switch (cmd.action) { + + case LFUN_INSET_MODIFY: + if (cmd.getArg(0) == "changetype") { + docstring const newtype = from_utf8(cmd.getArg(1)); + Buffer const & realbuffer = *buffer().masterBuffer(); + IndicesList const & indiceslist = realbuffer.params().indiceslist(); + Index const * index = indiceslist.findShortcut(newtype); + flag.setEnabled(index != 0); + flag.setOnOff( + from_utf8(cmd.getArg(1)) == params_.index); + return true; + } + + default: + return InsetCollapsable::getStatus(cur, cmd, flag); + } +} + + +docstring const InsetIndex::buttonLabel(BufferView const & bv) const +{ + docstring s = _("Idx"); + if (decoration() == InsetLayout::CLASSIC) + return isOpen(bv) ? s : getNewLabel(s); + else + return getNewLabel(s); +} + + +docstring InsetIndex::toolTip(BufferView const &, int, int) const +{ + docstring tip = _("Index Entry"); + if (buffer().params().use_indices && !params_.index.empty()) { + Buffer const & realbuffer = *buffer().masterBuffer(); + IndicesList const & indiceslist = realbuffer.params().indiceslist(); + tip += " ("; + Index const * index = indiceslist.findShortcut(params_.index); + if (!index) + tip += _("unknown type!"); + else + tip += index->index(); + tip += ")"; + } + tip += ": "; + OutputParams rp(&buffer().params().encoding()); + odocstringstream ods; + InsetText::plaintext(ods, rp); + tip += ods.str(); + // shorten it if necessary + if (tip.size() > 200) + tip = tip.substr(0, 200) + "..."; + return tip; +} + + void InsetIndex::write(ostream & os) const { - os << to_utf8(name()) << "\n"; + os << to_utf8(name()); + params_.write(os); InsetCollapsable::write(os); } +void InsetIndex::read(Lexer & lex) +{ + params_.read(lex); + InsetCollapsable::read(lex); +} + + void InsetIndex::addToToc(DocIterator const & cpit) { DocIterator pit = cpit; @@ -176,6 +274,41 @@ void InsetIndex::addToToc(DocIterator const & cpit) } +void InsetIndex::validate(LaTeXFeatures & features) const +{ + if (buffer().masterBuffer()->params().use_indices + && !params_.index.empty() + && params_.index != "idx") + features.require("splitidx"); +} + + +docstring InsetIndex::contextMenu(BufferView const &, int, int) const +{ + return from_ascii("context-index"); +} + + +void InsetIndexParams::write(ostream & os) const +{ + os << ' '; + if (!index.empty()) + os << to_utf8(index); + else + os << "idx"; + os << '\n'; +} + + +void InsetIndexParams::read(Lexer & lex) +{ + if (lex.eatLine()) + index = lex.getDocString(); + else + index = from_ascii("idx"); +} + + ///////////////////////////////////////////////////////////////////// // // InsetPrintIndex @@ -183,34 +316,85 @@ void InsetIndex::addToToc(DocIterator const & cpit) /////////////////////////////////////////////////////////////////////// InsetPrintIndex::InsetPrintIndex(InsetCommandParams const & p) - : InsetCommand(p, string()) + : InsetCommand(p, "index_print") {} ParamInfo const & InsetPrintIndex::findInfo(string const & /* cmdName */) { static ParamInfo param_info_; - if (param_info_.empty()) + if (param_info_.empty()) { + param_info_.add("type", ParamInfo::LATEX_OPTIONAL); param_info_.add("name", ParamInfo::LATEX_REQUIRED); + } return param_info_; } docstring InsetPrintIndex::screenLabel() const { - return _("Index"); + if ((!buffer().masterBuffer()->params().use_indices + && getParam("type") == from_ascii("idx")) + || getParam("type").empty()) + return _("Index"); + Buffer const & realbuffer = *buffer().masterBuffer(); + IndicesList const & indiceslist = realbuffer.params().indiceslist(); + Index const * index = indiceslist.findShortcut(getParam("type")); + if (!index) + return _("Unknown index type!"); + docstring res = index->index(); + if (!buffer().masterBuffer()->params().use_indices) + res += " (" + _("non-active") + ")"; + return res; +} + + +bool InsetPrintIndex::getStatus(Cursor & cur, FuncRequest const & cmd, + FuncStatus & status) const +{ + switch (cmd.action) { + + case LFUN_INSET_MODIFY: { + InsetCommandParams p(INDEX_PRINT_CODE); + InsetCommand::string2params("index_print", to_utf8(cmd.argument()), p); + Buffer const & realbuffer = *buffer().masterBuffer(); + IndicesList const & indiceslist = realbuffer.params().indiceslist(); + Index const * index = indiceslist.findShortcut(p["type"]); + status.setEnabled(index != 0); + status.setOnOff(p["type"] == getParam("type")); + return true; + } + + default: + return InsetCommand::getStatus(cur, cmd, status); + } +} + + +int InsetPrintIndex::latex(odocstream & os, OutputParams const &) const +{ + if (!buffer().masterBuffer()->params().use_indices) { + if (getParam("type") == from_ascii("idx")) + os << "\\printindex{}"; + return 0; + } + os << getCommand(); + return 0; } void InsetPrintIndex::validate(LaTeXFeatures & features) const { features.require("makeidx"); + if (buffer().masterBuffer()->params().use_indices) + features.require("splitidx"); } -InsetCode InsetPrintIndex::lyxCode() const +docstring InsetPrintIndex::contextMenu(BufferView const &, int, int) const { - return INDEX_PRINT_CODE; + return buffer().masterBuffer()->params().use_indices ? + from_ascii("context-indexprint") : docstring(); } } // namespace lyx diff --git a/src/insets/InsetIndex.h b/src/insets/InsetIndex.h index 19f61a49fc..15c5e7e3fd 100644 --- a/src/insets/InsetIndex.h +++ b/src/insets/InsetIndex.h @@ -19,12 +19,26 @@ namespace lyx { +class InsetIndexParams { +public: + /// + explicit InsetIndexParams(docstring const & b = docstring()) + : index(b) {} + /// + void write(std::ostream & os) const; + /// + void read(Lexer & lex); + /// + docstring index; +}; + + /** Used to insert index labels */ class InsetIndex : public InsetCollapsable { public: /// - InsetIndex(Buffer const &); + InsetIndex(Buffer const &, InsetIndexParams const &); private: /// EDITABLE editable() const { return HIGHLY_EDITABLE; } @@ -35,15 +49,34 @@ private: /// void write(std::ostream & os) const; /// + void read(Lexer & lex); + /// int docbook(odocstream &, OutputParams const &) const; /// int latex(odocstream &, OutputParams const &) const; + /// + bool getStatus(Cursor &, FuncRequest const &, FuncStatus &) const; + /// + void doDispatch(Cursor & cur, FuncRequest & cmd); /// should paragraph indendation be omitted in any case? bool neverIndent() const { return true; } /// void addToToc(DocIterator const &); /// + docstring const buttonLabel(BufferView const & bv) const; + /// + docstring toolTip(BufferView const & bv, int x, int y) const; + /// Updates needed features for this inset. + void validate(LaTeXFeatures & features) const; + /// + docstring contextMenu(BufferView const & bv, int x, int y) const; + /// Inset * clone() const { return new InsetIndex(*this); } + + /// + friend class InsetIndexParams; + /// + InsetIndexParams params_; }; @@ -51,6 +84,8 @@ class InsetPrintIndex : public InsetCommand { public: /// InsetPrintIndex(InsetCommandParams const &); + /// + InsetCode lyxCode() const { return INDEX_PRINT_CODE; } /// static ParamInfo const & findInfo(std::string const &); @@ -59,14 +94,18 @@ public: /// static bool isCompatibleCommand(std::string const & s) { return s == "printindex"; } + /// + int latex(odocstream &, OutputParams const &) const; + /// + bool getStatus(Cursor &, FuncRequest const &, FuncStatus &) const; + /// + virtual docstring contextMenu(BufferView const & bv, int x, int y) const; private: /// Updates needed features for this inset. void validate(LaTeXFeatures & features) const; /// EDITABLE editable() const { return NOT_EDITABLE; } /// - InsetCode lyxCode() const; - /// DisplayType display() const { return AlignCenter; } /// docstring screenLabel() const;