diff --git a/development/FORMAT b/development/FORMAT index 2de19fae70..fcf3fce47a 100644 --- a/development/FORMAT +++ b/development/FORMAT @@ -1,11 +1,14 @@ LyX file-format changes ----------------------- +2008-01-12 Richard Heck + * Format incremented to 313: change in how modules are represented + 2008-01-11 Jürgen Spitzmüller * Format incremented to 312: support for sidewaysalgorithm (rotfloat) and wide sideways{figure,table}. -2008-01-10 Richard Heck +2008-01-10 Richard Heck * Format incremented to 311: dummy format to drive the AMS conversion 2007-12-28 Bernhard Reiter diff --git a/development/scons/scons_manifest.py b/development/scons/scons_manifest.py index 28627d7242..71b727a4c2 100644 --- a/development/scons/scons_manifest.py +++ b/development/scons/scons_manifest.py @@ -730,6 +730,7 @@ src_frontends_qt4_header_files = Split(''' GuiGraphics.h GuiGraphicsUi.h GuiHyperlink.h + GuiIdListModel.h GuiImage.h GuiInclude.h GuiIndex.h @@ -818,6 +819,7 @@ src_frontends_qt4_files = Split(''' GuiFontMetrics.cpp GuiGraphics.cpp GuiHyperlink.cpp + GuiIdListModel.cpp GuiImage.cpp GuiInclude.cpp GuiIndex.cpp diff --git a/lib/configure.py b/lib/configure.py index e08032af81..1d3dd6185a 100644 --- a/lib/configure.py +++ b/lib/configure.py @@ -754,6 +754,8 @@ def processModuleFile(file, bool_docbook, bool_linuxdoc): modname = desc = pkgs = req = excl = "" readingDescription = False descLines = [] + filename = file.split(os.sep)[-1] + filename = filename[:-7] for line in open(file).readlines(): if readingDescription: @@ -776,8 +778,6 @@ def processModuleFile(file, bool_docbook, bool_linuxdoc): else: tmp = [s.strip() for s in pkgs.split(",")] pkgs = ",".join(tmp) - - filename = file.split(os.sep)[-1] continue res = r.search(line) if res != None: diff --git a/lib/doc/Customization.lyx b/lib/doc/Customization.lyx index cfa77fd0db..a58b98d180 100644 --- a/lib/doc/Customization.lyx +++ b/lib/doc/Customization.lyx @@ -1,5 +1,5 @@ #LyX 1.6.0svn created this file. For more info see http://www.lyx.org/ -\lyxformat 310 +\lyxformat 313 \begin_document \begin_header \textclass book @@ -58,7 +58,7 @@ \usepackage{multicol} \end_preamble \begin_modules -Logical Markup +logicalmkup \end_modules \language english \inputencoding default @@ -5907,11 +5907,11 @@ theendnotes in ERT where you \end_layout \begin_layout LyX-Code -#Requires: Some Module | Some Other Module +#Requires: somemodule | othermodule \end_layout \begin_layout LyX-Code -#Excludes: Bad Module +#Excludes: badmodule \end_layout \begin_layout Standard @@ -5936,6 +5936,32 @@ at least one no \emph default excluded module may be used. + Note that modules are identified here by their +\emph on +filenames +\emph default + without the .module extension. + So +\begin_inset Flex CharStyle:Code +status collapsed + +\begin_layout Standard +somemodule +\end_layout + +\end_inset + + is really +\begin_inset Flex CharStyle:Code +status collapsed + +\begin_layout Standard +somemodule.module +\end_layout + +\end_inset + +. \end_layout \begin_layout Standard @@ -5947,7 +5973,7 @@ After creating a new module, you will need to reconfigure and then restart Document\SpecialChar \menuseparator Settings \family default -, make some change (or even just highlight something), and then hit +, highlight something, and then hit \begin_inset Quotes eld \end_inset diff --git a/lib/layouts/theorems-ams-extended.module b/lib/layouts/theorems-ams-extended.module index c63a9a4479..f43b301e18 100644 --- a/lib/layouts/theorems-ams-extended.module +++ b/lib/layouts/theorems-ams-extended.module @@ -5,7 +5,7 @@ #Condition, Note, Notation, Summary, Acknowledgement, Conclusion, #Fact, Assumption, and Case, in both starred and non-starred forms. #DescriptionEnd -#Requires: Theorems (AMS) +#Requires: theorems-ams # Original Author : David L. Johnson # Probably broken by Jean-Marc Lasgouttes diff --git a/lib/layouts/theorems-ams.module b/lib/layouts/theorems-ams.module index 7b06b445b9..5947da46a7 100644 --- a/lib/layouts/theorems-ams.module +++ b/lib/layouts/theorems-ams.module @@ -5,7 +5,7 @@ #the theorems are numbered consecutively throughout the document. This can be #changed by loading one of the Theorems (Ordered By ...) modules. #DescriptionEnd -#Excludes: Theorems | Theorems (Starred) +#Excludes: theorems-std | theorems-starred # Original Author : David L. Johnson # Probably broken by Jean-Marc Lasgouttes diff --git a/lib/layouts/theorems-chap.module b/lib/layouts/theorems-chap.module index aae92e23f4..5a747ea6f6 100644 --- a/lib/layouts/theorems-chap.module +++ b/lib/layouts/theorems-chap.module @@ -2,7 +2,7 @@ #DescriptionBegin #Numbers theorems and the like by chapter. #DescriptionEnd -#Requires: Theorems | Theorems (AMS) +#Requires: theorems-std | theorems-ams # Author: Richard Heck diff --git a/lib/layouts/theorems-sec.module b/lib/layouts/theorems-sec.module index 704ac589ba..909a72baa8 100644 --- a/lib/layouts/theorems-sec.module +++ b/lib/layouts/theorems-sec.module @@ -2,7 +2,7 @@ #DescriptionBegin #Numbers theorems and the like by section. #DescriptionEnd -#Requires: Theorems | Theorems (AMS) +#Requires: theorems-std | theorems-ams # Author: Richard Heck diff --git a/lib/layouts/theorems-starred.module b/lib/layouts/theorems-starred.module index df751dbea6..0a7b63afa0 100644 --- a/lib/layouts/theorems-starred.module +++ b/lib/layouts/theorems-starred.module @@ -3,7 +3,7 @@ #Defines only unnumbered theorem environments, and the proof environment, using #the extended AMS machinery. ##DescriptionEnd -#Excludes: Theorems (AMS) | Theorems (Starred) | Theorems (Order By Section) | Theorems (Order By Chapter) +#Excludes: theorems-std | theorems-ams # Author: Richard Heck diff --git a/lib/layouts/theorems-std.module b/lib/layouts/theorems-std.module index 1c2d7dd679..0d111920ca 100644 --- a/lib/layouts/theorems-std.module +++ b/lib/layouts/theorems-std.module @@ -4,7 +4,7 @@ #the theorems are numbered consecutively throughout the document. This can be #changed by loading one of the Theorems (Ordered By ...) modules. #DescriptionEnd -#Excludes: Theorems (AMS) | Theorems (Starred) +#Excludes: theorems-ams | theorems-starred # Author: Richard Heck diff --git a/lib/lyx2lyx/LyX.py b/lib/lyx2lyx/LyX.py index 4c9bf8995a..8b3e069a5a 100644 --- a/lib/lyx2lyx/LyX.py +++ b/lib/lyx2lyx/LyX.py @@ -80,7 +80,7 @@ format_relation = [("0_06", [200], minor_versions("0.6" , 4)), ("1_3", [221], minor_versions("1.3" , 7)), ("1_4", range(222,246), minor_versions("1.4" , 5)), ("1_5", range(246,277), minor_versions("1.5" , 2)), - ("1_6", range(277,313), minor_versions("1.6" , 0))] # JSpitzm: rotfloat support + ("1_6", range(277,314), minor_versions("1.6" , 0))] # Richard Heck: conversion of module representations def formats_list(): @@ -412,6 +412,30 @@ class LyX_base: self.header.insert(j, module) + def get_module_list(self): + i = find_token(self.header, "\\begin_modules", 0) + if (i == -1): + return [] + j = find_token(self.header, "\\end_modules", i) + return self.header[i + 1 : j] + + + def set_module_list(self, mlist): + modbegin = find_token(self.header, "\\begin_modules", 0) + if (modbegin == -1): + #No modules yet included + modbegin = find_token(self.header, "\\textclass", 0) + if modbegin == -1: + self.warning("Malformed LyX document: No \\textclass!!") + return + modend = find_token(self.header, "\\end_modules", modbegin) + if modend == -1: + self.warning("Malformed LyX document: No \\end_modules.") + return + newmodlist = ['\\begin_modules'] + mlist + ['\\end_modules'] + self.header[modbegin:modend + 1] = newmodlist + + def set_parameter(self, param, value): " Set the value of the header parameter." i = find_token(self.header, '\\' + param, 0) diff --git a/lib/lyx2lyx/lyx_1_6.py b/lib/lyx2lyx/lyx_1_6.py index 3996b883bc..a3bf1a788a 100644 --- a/lib/lyx2lyx/lyx_1_6.py +++ b/lib/lyx2lyx/lyx_1_6.py @@ -922,6 +922,40 @@ def convert_framed_notes(document): i = i + 1 +def convert_module_names(document): + modulemap = { 'Braille' : 'braille', 'Endnote' : 'endnotes', 'Foot to End' : 'foottoend',\ + 'Hanging' : 'hanging', 'Linguistics' : 'linguistics', 'Logical Markup' : 'logicalmkup', \ + 'Theorems (AMS-Extended)' : 'theorems-ams-extended', 'Theorems (AMS)' : 'theorems-ams', \ + 'Theorems (Order By Chapter)' : 'theorems-chap', 'Theorems (Order By Section)' : 'theorems-sec', \ + 'Theorems (Starred)' : 'theorems-starred', 'Theorems' : 'theorems-std' } + modlist = document.get_module_list() + newmodlist = [] + for mod in modlist: + if modulemap.has_key(mod): + newmodlist.append(modulemap[mod]) + else: + document.warning("Can't find module %s in the module map!" % mod) + newmodlist.append(mod) + document.set_module_list(newmodlist) + + +def revert_module_names(document): + modulemap = { 'braille' : 'Braille', 'endnotes' : 'Endnote', 'foottoend' : 'Foot to End',\ + 'hanging' : 'Hanging', 'linguistics' : 'Linguistics', 'logicalmkup' : 'Logical Markup', \ + 'theorems-ams-extended' : 'Theorems (AMS-Extended)', 'theorems-ams' : 'Theorems (AMS)', \ + 'theorems-chap' : 'Theorems (Order By Chapter)', 'theorems-sec' : 'Theorems (Order By Section)', \ + 'theorems-starred' : 'Theorems (Starred)', 'theorems-std' : 'Theorems'} + modlist = document.get_module_list() + newmodlist = [] + for mod in modlist: + if modulemap.has_key(mod): + newmodlist.append(modulemap[mod]) + else: + document.warning("Can't find module %s in the module map!" % mod) + newmodlist.append(mod) + document.set_module_list(newmodlist) + + def revert_framed_notes(document): "Revert framed boxes to notes. " i = 0 @@ -1213,9 +1247,11 @@ convert = [[277, [fix_wrong_tables]], [310, []], [311, [convert_ams_classes]], [312, []], + [313, [convert_module_names]] ] -revert = [[311, [revert_rotfloat, revert_widesideways]], +revert = [[312, [revert_module_names]], + [311, [revert_rotfloat, revert_widesideways]], [310, []], [309, [revert_btprintall]], [308, [revert_nocite]], diff --git a/src/Buffer.cpp b/src/Buffer.cpp index d33fa3f31a..7cef49baef 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -118,7 +118,7 @@ namespace os = support::os; namespace { -int const LYX_FORMAT = 312; // JSpitzm: rotfloat support +int const LYX_FORMAT = 313; // Richard Heck: conversion of module representations } // namespace anon diff --git a/src/ModuleList.cpp b/src/ModuleList.cpp index 0b88a8e8f2..3b7e8134cb 100644 --- a/src/ModuleList.cpp +++ b/src/ModuleList.cpp @@ -34,13 +34,15 @@ namespace lyx { ModuleList moduleList; -LyXModule::LyXModule(string const & n, string const & f, +LyXModule::LyXModule(string const & n, string const & i, string const & d, vector const & p, vector const & r, vector const & e): - name(n), filename(f), description(d), + name(n), id(i), description(d), packageList(p), requiredModules(r), excludedModules(e), checked(false) -{} +{ + filename = id + ".module"; +} bool LyXModule::isAvailable() { @@ -204,7 +206,7 @@ LyXModuleList::iterator ModuleList::end() } -LyXModule * ModuleList::operator[](string const & str) +LyXModule * ModuleList::getModuleByName(string const & str) { LyXModuleList::iterator it = modlist_.begin(); for (; it != modlist_.end(); ++it) @@ -215,4 +217,15 @@ LyXModule * ModuleList::operator[](string const & str) return 0; } +LyXModule * ModuleList::operator[](string const & str) +{ + LyXModuleList::iterator it = modlist_.begin(); + for (; it != modlist_.end(); ++it) + if (it->getID() == str) { + LyXModule & mod = *it; + return &mod; + } + return 0; +} + } // namespace lyx diff --git a/src/ModuleList.h b/src/ModuleList.h index 2281a5d74c..804cce1dea 100644 --- a/src/ModuleList.h +++ b/src/ModuleList.h @@ -28,7 +28,7 @@ namespace lyx { class LyXModule { public: /// - LyXModule(std::string const & n, std::string const & f, + LyXModule(std::string const & n, std::string const & i, std::string const & d, std::vector const & p, std::vector const & r, std::vector const & e); @@ -37,6 +37,8 @@ public: /// std::string const & getName() const { return name; } /// + std::string const & getID() const { return id; } + /// std::string const & getFilename() const { return filename; } /// std::string const & getDescription() const { return description; } @@ -53,7 +55,10 @@ public: private: /// what appears in the ui std::string name; - /// the filename, without any path + /// the module's unique identifier + /// at present, this is the filename, without the extension + std::string id; + /// the filename std::string filename; /// a short description for use in the ui std::string description; @@ -93,8 +98,11 @@ public: bool empty() const { return modlist_.empty(); } /// Returns a pointer to the LyXModule with name str. /// Returns a null pointer if no such module is found. + LyXModule * getModuleByName(std::string const & str); + /// Returns a pointer to the LyXModule with filename str. + /// Returns a null pointer if no such module is found. LyXModule * operator[](std::string const & str); -private: + private: /// noncopyable ModuleList(ModuleList const &); /// diff --git a/src/frontends/qt4/GuiDocument.cpp b/src/frontends/qt4/GuiDocument.cpp index 872cb4499f..5736964641 100644 --- a/src/frontends/qt4/GuiDocument.cpp +++ b/src/frontends/qt4/GuiDocument.cpp @@ -189,16 +189,29 @@ ModuleSelMan::ModuleSelMan( QPushButton * delPB, QPushButton * upPB, QPushButton * downPB, - QStringListModel * availableModel, - QStringListModel * selectedModel) : + GuiIdListModel * availableModel, + GuiIdListModel * selectedModel) : GuiSelectionManager(availableLV, selectedLV, addPB, delPB, upPB, downPB, availableModel, selectedModel) {} +namespace { +QModelIndex getSelectedIndex(QListView * lv) +{ + QModelIndex retval = QModelIndex(); + QModelIndexList selIdx = + lv->selectionModel()->selectedIndexes(); + if (!selIdx.empty()) + retval = selIdx.first(); + return retval; +} +} + + void ModuleSelMan::updateAddPB() { - int const arows = availableModel->stringList().size(); + int const arows = availableModel->rowCount(); QModelIndexList const availSels = availableLV->selectionModel()->selectedIndexes(); if (arows == 0 || availSels.isEmpty() || isSelected(availSels.first())) { @@ -207,7 +220,7 @@ void ModuleSelMan::updateAddPB() } QModelIndex const & idx = availableLV->selectionModel()->currentIndex(); - string const modName = fromqstr(idx.data().toString()); + string const modName = getAvailableModel()->getIDString(idx.row()); vector reqs = getRequiredList(modName); vector excl = getExcludedList(modName); @@ -216,7 +229,13 @@ void ModuleSelMan::updateAddPB() return; } - QStringList const & qsl = selectedModel->stringList(); + int const srows = selectedModel->rowCount(); + vector selModList; + for (int i = 0; i < srows; ++i) + selModList.push_back(getSelectedModel()->getIDString(i)); + + vector::const_iterator selModStart = selModList.begin(); + vector::const_iterator selModEnd = selModList.end(); //Check whether some required module is available if (!reqs.empty()) { @@ -224,7 +243,7 @@ void ModuleSelMan::updateAddPB() vector::const_iterator it = reqs.begin(); vector::const_iterator end = reqs.end(); for (; it != end; ++it) { - if (qsl.contains(toqstr(*it))) { + if (find(selModStart, selModEnd, *it) != selModEnd) { foundOne = true; break; } @@ -240,7 +259,7 @@ void ModuleSelMan::updateAddPB() vector::const_iterator it = excl.begin(); vector::const_iterator end = excl.end(); for (; it != end; ++it) { - if (qsl.contains(toqstr(*it))) { + if (find(selModStart, selModEnd, *it) != selModEnd) { addPB->setEnabled(false); return; } @@ -250,9 +269,10 @@ void ModuleSelMan::updateAddPB() addPB->setEnabled(true); } + void ModuleSelMan::updateDownPB() { - int const srows = selectedModel->stringList().size(); + int const srows = selectedModel->rowCount(); if (srows == 0) { downPB->setEnabled(false); return; @@ -265,15 +285,14 @@ void ModuleSelMan::updateDownPB() return; } //determine whether immediately succeding element requires this one - QString const curModName = - selectedLV->selectionModel()->currentIndex().data().toString(); - QStringList const & qsl = selectedModel->stringList(); - int const curIdx = qsl.indexOf(curModName); - if (curIdx < 0 || curIdx == srows - 1) { //this shouldn't happen... + QModelIndex const & curIdx = selectedLV->selectionModel()->currentIndex(); + int curRow = curIdx.row(); + if (curRow < 0 || curRow >= srows - 1) { //this shouldn't happen... downPB->setEnabled(false); return; } - string nextModName = fromqstr(qsl[curIdx + 1]); + string const curModName = getSelectedModel()->getIDString(curRow); + string const nextModName = getSelectedModel()->getIDString(curRow + 1); vector reqs = getRequiredList(nextModName); @@ -287,12 +306,12 @@ void ModuleSelMan::updateDownPB() //if this one is required, there is also an earlier one that is required. //enable it if this module isn't required downPB->setEnabled( - find(reqs.begin(), reqs.end(), fromqstr(curModName)) == reqs.end()); + find(reqs.begin(), reqs.end(), curModName) == reqs.end()); } void ModuleSelMan::updateUpPB() { - int const srows = selectedModel->stringList().size(); + int const srows = selectedModel->rowCount(); if (srows == 0) { upPB->setEnabled(false); return; @@ -304,10 +323,16 @@ void ModuleSelMan::updateUpPB() upPB->setEnabled(false); return; } + //determine whether immediately preceding element is required by this one - QString const curModName = - selectedLV->selectionModel()->currentIndex().data().toString(); - vector reqs = getRequiredList(fromqstr(curModName)); + QModelIndex const & curIdx = selectedLV->selectionModel()->currentIndex(); + int curRow = curIdx.row(); + if (curRow <= -1 || curRow > srows - 1) { //sanity check + downPB->setEnabled(false); + return; + } + string const curModName = getSelectedModel()->getIDString(curRow); + vector reqs = getRequiredList(curModName); //if this one doesn't require anything.... if (reqs.empty()) { @@ -315,13 +340,7 @@ void ModuleSelMan::updateUpPB() return; } - QStringList const & qsl = selectedModel->stringList(); - int const curIdx = qsl.indexOf(curModName); - if (curIdx <= 0) { //this shouldn't happen... - upPB->setEnabled(false); - return; - } - string preModName = fromqstr(qsl[curIdx - 1]); + string preModName = getSelectedModel()->getIDString(curRow - 1); //NOTE This is less flexible than it might be. You could check whether, even //if this one is required, there is also an earlier one that is required. @@ -331,7 +350,7 @@ void ModuleSelMan::updateUpPB() void ModuleSelMan::updateDelPB() { - int const srows = selectedModel->stringList().size(); + int const srows = selectedModel->rowCount(); if (srows == 0) { deletePB->setEnabled(false); return; @@ -346,59 +365,49 @@ void ModuleSelMan::updateDelPB() //determine whether some LATER module requires this one //NOTE Things are arranged so that this is the only way there //can be a problem. At least, we hope so. - QString const curModName = - selectedLV->selectionModel()->currentIndex().data().toString(); - QStringList const & qsl = selectedModel->stringList(); + QModelIndex const & curIdx = + selectedLV->selectionModel()->currentIndex(); + int const curRow = curIdx.row(); + if (curRow < 0 || curRow >= srows) { //this shouldn't happen + deletePB->setEnabled(false); + return; + } + + QString const curModName = curIdx.data().toString(); //We're looking here for a reason NOT to enable the button. If we //find one, we disable it and return. If we don't, we'll end up at //the end of the function, and then we enable it. - QStringList::const_iterator it = qsl.begin(); - QStringList::const_iterator end = qsl.end(); - bool found = false; - for (; it != end; ++it) { - //skip over the ones preceding this one - if (!found) { - if (*it == curModName) { - found = true; - } - continue; - } - - string const mod = fromqstr(*it); - vector reqs = getRequiredList(mod); + for (int i = curRow + 1; i < srows; ++i) { + string const thisMod = getSelectedModel()->getIDString(i); + vector reqs = getRequiredList(thisMod); //does this one require us? if (find(reqs.begin(), reqs.end(), fromqstr(curModName)) == reqs.end()) //no... continue; - //OK, so there is a module that requires us - //is there an EARLIER module that satisfies the require? + //OK, so this module requires us + //is there an EARLIER module that also satisfies the require? //NOTE We demand that it be earlier to keep the list of modules //consistent with the rule that a module must be proceeded by a //required module. There would be more flexible ways to proceed, //but that would be a lot more complicated, and the logic here is //already complicated. (That's why I've left the debugging code.) - //lyxerr << "Testing " << mod << std::endl; - QStringList::const_iterator it2 = qsl.begin(); - QStringList::const_iterator end2 = qsl.end(); - for (; it2 != end2; ++it2) { - //lyxerr << "In loop: Testing " << fromqstr(*it2) << std::endl; - if (*it2 == curModName) { //EARLIER!! - //no other module was found before this one, so... - //lyxerr << "Reached the end of the loop." << std::endl; - deletePB->setEnabled(false); - return; - } + //lyxerr << "Testing " << thisMod << std::endl; + bool foundOne = false; + for (int j = 0; j < curRow; ++j) { + string const mod = getSelectedModel()->getIDString(j); + //lyxerr << "In loop: Testing " << mod << std::endl; //do we satisfy the require? - if (find(reqs.begin(), reqs.end(), fromqstr(*it2)) != reqs.end()) { - //lyxerr << fromqstr(*it2) << " does the trick." << std::endl; + if (find(reqs.begin(), reqs.end(), mod) != reqs.end()) { + //lyxerr << mod << " does the trick." << std::endl; + foundOne = true; break; } } - //did we reach the end of the list? - if (it2 == end2) { - //lyxerr << "Reached end of list." << std::endl; + //did we find a module to satisfy the require? + if (!foundOne) { + //lyxerr << "No matching module found." << std::endl; deletePB->setEnabled(false); return; } @@ -1221,54 +1230,75 @@ namespace { t = subst(t, _("and"), s); return bformat(t, retval, from_ascii(v[vSize - 2]), from_ascii(v[vSize - 1])); } + + vector idsToNames(vector const & idList) + { + vector retval; + vector::const_iterator it = idList.begin(); + vector::const_iterator end = idList.end(); + for (; it != end; ++it) { + LyXModule const * const mod = moduleList[*it]; + if (!mod) + retval.push_back(*it + " (Unavailable)"); + else + retval.push_back(mod->getName()); + } + return retval; + } } void GuiDocument::updateModuleInfo() { selectionManager->update(); + //Module description - QListView const * const lv = selectionManager->selectedFocused() ? - latexModule->selectedLV : - latexModule->availableLV; - if (lv->selectionModel()->selectedIndexes().isEmpty()) + bool const focusOnSelected = selectionManager->selectedFocused(); + QListView const * const lv = + focusOnSelected ? latexModule->selectedLV : latexModule->availableLV; + if (lv->selectionModel()->selectedIndexes().isEmpty()) { latexModule->infoML->document()->clear(); - else { - QModelIndex const & idx = lv->selectionModel()->currentIndex(); - string const modName = fromqstr(idx.data().toString()); - docstring desc = getModuleDescription(modName); - - vector pkgList = getPackageList(modName); - docstring pkgdesc = formatStrVec(pkgList, _("and")); - if (!pkgdesc.empty()) { - if (!desc.empty()) - desc += "\n"; - desc += bformat(_("Package(s) required: %1$s."), pkgdesc); - } - - pkgList = getRequiredList(modName); - pkgdesc = formatStrVec(pkgList, _("or")); - if (!pkgdesc.empty()) { - if (!desc.empty()) - desc += "\n"; - desc += bformat(_("Module required: %1$s."), pkgdesc); - } - - pkgList = getExcludedList(modName); - pkgdesc = formatStrVec(pkgList, _( "and")); - if (!pkgdesc.empty()) { - if (!desc.empty()) - desc += "\n"; - desc += bformat(_("Modules excluded: %1$s."), pkgdesc); - } - - if (!isModuleAvailable(modName)) { - if (!desc.empty()) - desc += "\n"; - desc += _("WARNING: Some packages are unavailable!"); - } - latexModule->infoML->document()->setPlainText(toqstr(desc)); + return; } + QModelIndex const & idx = lv->selectionModel()->currentIndex(); + GuiIdListModel const & idModel = + focusOnSelected ? selected_model_ : available_model_; + string const modName = idModel.getIDString(idx.row()); + docstring desc = getModuleDescription(modName); + + vector pkgList = getPackageList(modName); + docstring pkgdesc = formatStrVec(pkgList, _("and")); + if (!pkgdesc.empty()) { + if (!desc.empty()) + desc += "\n"; + desc += bformat(_("Package(s) required: %1$s."), pkgdesc); + } + + pkgList = getRequiredList(modName); + if (!pkgList.empty()) { + vector const reqDescs = idsToNames(pkgList); + pkgdesc = formatStrVec(reqDescs, _("or")); + if (!desc.empty()) + desc += "\n"; + desc += bformat(_("Module required: %1$s."), pkgdesc); + } + + pkgList = getExcludedList(modName); + if (!pkgList.empty()) { + vector const reqDescs = idsToNames(pkgList); + pkgdesc = formatStrVec(reqDescs, _( "and")); + if (!desc.empty()) + desc += "\n"; + desc += bformat(_("Modules excluded: %1$s."), pkgdesc); + } + + if (!isModuleAvailable(modName)) { + if (!desc.empty()) + desc += "\n"; + desc += _("WARNING: Some packages are unavailable!"); + } + + latexModule->infoML->document()->setPlainText(toqstr(desc)); } @@ -1408,9 +1438,10 @@ void GuiDocument::apply(BufferParams & params) // Modules params.clearLayoutModules(); - QStringList const selMods = selectedModel()->stringList(); - for (int i = 0; i != selMods.size(); ++i) - params.addLayoutModule(lyx::fromqstr(selMods[i])); + int const srows = selected_model_.rowCount(); + vector selModList; + for (int i = 0; i < srows; ++i) + params.addLayoutModule(selected_model_.getIDString(i)); if (mathsModule->amsautoCB->isChecked()) { params.use_amsmath = BufferParams::package_auto; @@ -1922,27 +1953,40 @@ void GuiDocument::saveDocDefault() } +void GuiDocument::updateAvailableModules() +{ + available_model_.clear(); + vector const modInfoList = getModuleInfo(); + int const mSize = modInfoList.size(); + for (int i = 0; i < mSize; ++i) { + modInfoStruct const & modInfo = modInfoList[i]; + available_model_.insertRow(i, modInfo.name, modInfo.id); + } +} + + +void GuiDocument::updateSelectedModules() +{ + //and selected ones, too + selected_model_.clear(); + vector const selModList = getSelectedModules(); + int const sSize = selModList.size(); + for (int i = 0; i < sSize; ++i) { + modInfoStruct const & modInfo = selModList[i]; + selected_model_.insertRow(i, modInfo.name, modInfo.id); + } +} + + void GuiDocument::updateContents() { - //update list of available modules - QStringList strlist; - vector const modNames = getModuleNames(); - vector::const_iterator it = modNames.begin(); - for (; it != modNames.end(); ++it) - strlist.push_back(toqstr(*it)); - available_model_.setStringList(strlist); - //and selected ones, too - QStringList strlist2; - vector const & selMods = getSelectedModules(); - it = selMods.begin(); - for (; it != selMods.end(); ++it) - strlist2.push_back(toqstr(*it)); + updateAvailableModules(); + updateSelectedModules(); + //FIXME It'd be nice to make sure here that the selected //modules are consistent: That required modules are actually //selected, and that we don't have conflicts. If so, we could //at least pop up a warning. - selected_model_.setStringList(strlist2); - updateParams(bp_); } @@ -1973,7 +2017,7 @@ char const * GuiDocument::fontfamilies_gui[5] = { bool GuiDocument::initialiseParams(string const &) { bp_ = buffer().params(); - loadModuleNames(); + loadModuleInfo(); return true; } @@ -1990,15 +2034,29 @@ BufferId GuiDocument::id() const } -vector const & GuiDocument::getModuleNames() +vector const & GuiDocument::getModuleInfo() { return moduleNames_; } -vector const & GuiDocument::getSelectedModules() +vector const GuiDocument::getSelectedModules() { - return params().getModules(); + vector const & mods = params().getModules(); + vector::const_iterator it = mods.begin(); + vector::const_iterator end = mods.end(); + vector mInfo; + for (; it != end; ++it) { + modInfoStruct m; + m.id = *it; + LyXModule * mod = moduleList[*it]; + if (mod) + m.name = mod->getName(); + else + m.name = *it + " (Not Found)"; + mInfo.push_back(m); + } + return mInfo; } @@ -2118,14 +2176,17 @@ bool GuiDocument::providesScale(string const & font) const } -void GuiDocument::loadModuleNames () +void GuiDocument::loadModuleInfo() { moduleNames_.clear(); - LyXModuleList::const_iterator it = moduleList.begin(); - for (; it != moduleList.end(); ++it) - moduleNames_.push_back(it->getName()); - if (!moduleNames_.empty()) - sort(moduleNames_.begin(), moduleNames_.end()); + LyXModuleList::const_iterator it = moduleList.begin(); + LyXModuleList::const_iterator end = moduleList.end(); + for (; it != end; ++it) { + modInfoStruct m; + m.id = it->getID(); + m.name = it->getName(); + moduleNames_.push_back(m); + } } diff --git a/src/frontends/qt4/GuiDocument.h b/src/frontends/qt4/GuiDocument.h index ac9dda04b0..fc136f2f2c 100644 --- a/src/frontends/qt4/GuiDocument.h +++ b/src/frontends/qt4/GuiDocument.h @@ -13,10 +13,13 @@ #ifndef GUIDOCUMENT_H #define GUIDOCUMENT_H -#include "GuiDialog.h" -#include "BulletsModule.h" -#include "GuiSelectionManager.h" +#include + #include "BufferParams.h" +#include "BulletsModule.h" +#include "GuiDialog.h" +#include "GuiIdListModel.h" +#include "GuiSelectionManager.h" #include "support/types.h" @@ -52,13 +55,6 @@ class PreambleModule; /// typedef void const * BufferId; -#include -#include -#include - -#include -#include - template class UiWidget : public QWidget, public UI { @@ -77,8 +73,8 @@ public: QPushButton * delPB, QPushButton * upPB, QPushButton * downPB, - QStringListModel * availableModel, - QStringListModel * selectedModel); + GuiIdListModel * availableModel, + GuiIdListModel * selectedModel); private: /// virtual void updateAddPB(); @@ -88,6 +84,16 @@ private: virtual void updateDownPB(); /// virtual void updateDelPB(); + /// returns availableModel as a GuiIdListModel + GuiIdListModel * getAvailableModel() + { + return dynamic_cast(availableModel); + }; + /// returns selectedModel as a GuiIdListModel + GuiIdListModel * getSelectedModel() + { + return dynamic_cast(selectedModel); + }; }; @@ -158,22 +164,26 @@ private: std::vector lang_; /// Available modules - QStringListModel * availableModel() { return &available_model_; } + GuiIdListModel * availableModel() { return &available_model_; } /// Selected modules - QStringListModel * selectedModel() { return &selected_model_; } + GuiIdListModel * selectedModel() { return &selected_model_; } private: /// Apply changes void applyView(); /// update void updateContents(); + /// + void updateAvailableModules(); + /// + void updateSelectedModules(); /// save as default template void saveDocDefault(); /// reset to default params void useClassDefaults(); /// available modules - QStringListModel available_model_; + GuiIdListModel available_model_; /// selected modules - QStringListModel selected_model_; + GuiIdListModel selected_model_; protected: /// return false if validate_listings_params returns error @@ -201,10 +211,15 @@ protected: BufferParams const & params() const { return bp_; } /// BufferId id() const; + /// + struct modInfoStruct { + std::string name; + std::string id; + }; /// List of available modules - std::vector const & getModuleNames(); + std::vector const & getModuleInfo(); /// Modules in use in current buffer - std::vector const & getSelectedModules(); + std::vector const getSelectedModules(); /// void setLanguage() const; /// @@ -219,11 +234,11 @@ protected: bool providesScale(std::string const & font) const; private: /// - void loadModuleNames(); + void loadModuleInfo(); /// BufferParams bp_; /// List of names of available modules - std::vector moduleNames_; + std::vector moduleNames_; }; @@ -256,4 +271,4 @@ private: } // namespace frontend } // namespace lyx -#endif // QDOCUMENT_H +#endif // GUIDOCUMENT_H diff --git a/src/frontends/qt4/GuiSelectionManager.cpp b/src/frontends/qt4/GuiSelectionManager.cpp index eea9d40edb..74e3cf9de4 100644 --- a/src/frontends/qt4/GuiSelectionManager.cpp +++ b/src/frontends/qt4/GuiSelectionManager.cpp @@ -15,10 +15,14 @@ #include #include "GuiSelectionManager.h" +#include "support/debug.h" + +using std::vector; namespace lyx { namespace frontend { + GuiSelectionManager::GuiSelectionManager( QListView * avail, QListView * sel, @@ -26,8 +30,8 @@ GuiSelectionManager::GuiSelectionManager( QPushButton * del, QPushButton * up, QPushButton * down, - QStringListModel * amod, - QStringListModel * smod) + QAbstractListModel * amod, + QAbstractListModel * smod) { availableLV = avail; selectedLV = sel; @@ -78,7 +82,7 @@ void GuiSelectionManager::update() void GuiSelectionManager::updateAddPB() { - int const arows = availableModel->stringList().size(); + int const arows = availableModel->rowCount(); QModelIndexList const availSels = availableLV->selectionModel()->selectedIndexes(); addPB->setEnabled(arows > 0 && @@ -89,7 +93,7 @@ void GuiSelectionManager::updateAddPB() void GuiSelectionManager::updateDelPB() { - int const srows = selectedModel->stringList().size(); + int const srows = selectedModel->rowCount(); if (srows == 0) { deletePB->setEnabled(false); return; @@ -103,7 +107,7 @@ void GuiSelectionManager::updateDelPB() void GuiSelectionManager::updateUpPB() { - int const srows = selectedModel->stringList().size(); + int const srows = selectedModel->rowCount(); if (srows == 0) { upPB->setEnabled(false); return; @@ -117,7 +121,7 @@ void GuiSelectionManager::updateUpPB() void GuiSelectionManager::updateDownPB() { - int const srows = selectedModel->stringList().size(); + int const srows = selectedModel->rowCount(); if (srows == 0) { downPB->setEnabled(false); return; @@ -128,10 +132,17 @@ void GuiSelectionManager::updateDownPB() downPB->setEnabled(sel_nr >= 0 && sel_nr < srows - 1); } + bool GuiSelectionManager::isSelected(const QModelIndex & idx) { - QString const str = idx.data().toString(); - return selectedModel->stringList().contains(str); + if (selectedModel->rowCount() == 0) + return false; + QVariant const & str = availableModel->data(idx, Qt::DisplayRole); + QModelIndexList qmil = + selectedModel->match(selectedModel->index(0), + Qt::DisplayRole, str, + Qt::MatchExactly | Qt::MatchWrap); + return !qmil.empty(); } @@ -155,7 +166,8 @@ void GuiSelectionManager::selectedChanged(const QModelIndex & idx, const QModelI } -static QModelIndex getSelectedIndex(QListView * lv) +namespace { +QModelIndex getSelectedIndex(QListView * lv) { QModelIndex retval = QModelIndex(); QModelIndexList selIdx = @@ -164,6 +176,18 @@ static QModelIndex getSelectedIndex(QListView * lv) retval = selIdx.first(); return retval; } +} + + +bool GuiSelectionManager::insertRowToSelected(int i, + QMap const & itemData) +{ + if (i <= -1 || i > selectedModel->rowCount()) + return false; + if (!selectedModel->insertRow(i)) + return false; + return selectedModel->setItemData(selectedModel->index(i), itemData); +} void GuiSelectionManager::addPB_clicked() @@ -171,15 +195,17 @@ void GuiSelectionManager::addPB_clicked() QModelIndex const idxToAdd = getSelectedIndex(availableLV); if (!idxToAdd.isValid()) return; - QModelIndex idx = selectedLV->currentIndex(); + QModelIndex const idx = selectedLV->currentIndex(); + int const srows = selectedModel->rowCount(); + + QMap qm = availableModel->itemData(idxToAdd); + insertRowToSelected(srows, qm); - QStringList keys = selectedModel->stringList(); - keys.append(idxToAdd.data().toString()); - selectedModel->setStringList(keys); selectionChanged(); //signal if (idx.isValid()) selectedLV->setCurrentIndex(idx); + updateHook(); } @@ -190,9 +216,7 @@ void GuiSelectionManager::deletePB_clicked() if (!idx.isValid()) return; - QStringList keys = selectedModel->stringList(); - keys.removeAt(idx.row()); - selectedModel->setStringList(keys); + selectedModel->removeRow(idx.row()); selectionChanged(); //signal int nrows = selectedLV->model()->rowCount(); @@ -211,13 +235,18 @@ void GuiSelectionManager::deletePB_clicked() void GuiSelectionManager::upPB_clicked() { QModelIndex idx = selectedLV->currentIndex(); - + int const pos = idx.row(); - QStringList keys = selectedModel->stringList(); - keys.swap(pos, pos - 1); - selectedModel->setStringList(keys); - selectionChanged(); //signal + if (pos <= 0) + return; + QMap qm = selectedModel->itemData(idx); + + selectedModel->removeRow(pos); + insertRowToSelected(pos - 1, qm); + + selectionChanged(); //signal + selectedLV->setCurrentIndex(idx.sibling(idx.row() - 1, idx.column())); selectedHasFocus_ = true; updateHook(); @@ -227,11 +256,16 @@ void GuiSelectionManager::upPB_clicked() void GuiSelectionManager::downPB_clicked() { QModelIndex idx = selectedLV->currentIndex(); - + int const pos = idx.row(); - QStringList keys = selectedModel->stringList(); - keys.swap(pos, pos + 1); - selectedModel->setStringList(keys); + if (pos >= selectedModel->rowCount() - 1) + return; + + QMap qm = selectedModel->itemData(idx); + + selectedModel->removeRow(pos); + insertRowToSelected(pos + 1, qm); + selectionChanged(); //signal selectedLV->setCurrentIndex(idx.sibling(idx.row() + 1, idx.column())); @@ -311,9 +345,7 @@ bool GuiSelectionManager::eventFilter(QObject * obj, QEvent * event) if (keyModifiers == Qt::NoModifier && deletePB->isEnabled()) deletePB_clicked(); else if (keyModifiers == Qt::ControlModifier) { - QStringList list = selectedModel->stringList(); - list.clear(); - selectedModel->setStringList(list); + selectedModel->removeRows(0, selectedModel->rowCount()); updateHook(); } else //ignore it otherwise diff --git a/src/frontends/qt4/GuiSelectionManager.h b/src/frontends/qt4/GuiSelectionManager.h index fa176327e7..43ceea7b50 100644 --- a/src/frontends/qt4/GuiSelectionManager.h +++ b/src/frontends/qt4/GuiSelectionManager.h @@ -17,10 +17,14 @@ #include #include #include -#include +#include #include #include +#include "support/qstring_helpers.h" + +#include + namespace lyx { namespace frontend { @@ -45,8 +49,8 @@ public: QPushButton * delPB, QPushButton * upPB, QPushButton * downPB, - QStringListModel * availableModel, - QStringListModel * selectedModel); + QAbstractListModel * availableModel, + QAbstractListModel * selectedModel); /// Sets the state of the various push buttons, depending upon the /// state of the widgets. (E.g., "delete" is enabled only if the /// selection is non-empty.) @@ -82,6 +86,8 @@ protected: ///been selected (i.e., is also in selectedLV). bool isSelected(const QModelIndex & idx); /// + bool insertRowToSelected(int i, QMap const & itemData); + /// QListView * availableLV; /// QListView * selectedLV; @@ -94,9 +100,9 @@ protected: /// QPushButton * downPB; /// - QStringListModel * availableModel; + QAbstractListModel * availableModel; /// - QStringListModel * selectedModel; + QAbstractListModel * selectedModel; protected Q_SLOTS: /// @@ -104,13 +110,13 @@ protected Q_SLOTS: /// void selectedChanged(const QModelIndex & idx, const QModelIndex &); /// - void addPB_clicked(); + virtual void addPB_clicked(); /// - void deletePB_clicked(); + virtual void deletePB_clicked(); /// - void upPB_clicked(); + virtual void upPB_clicked(); /// - void downPB_clicked(); + virtual void downPB_clicked(); /// void availableLV_clicked(const QModelIndex &); /// @@ -129,7 +135,7 @@ private: virtual void updateDownPB(); /// virtual void updateUpPB(); - + /// bool selectedHasFocus_; }; diff --git a/src/frontends/qt4/Makefile.am b/src/frontends/qt4/Makefile.am index 4aae59b510..aa7a80737c 100644 --- a/src/frontends/qt4/Makefile.am +++ b/src/frontends/qt4/Makefile.am @@ -86,6 +86,7 @@ SOURCEFILES = \ GuiFontMetrics.cpp \ GuiGraphics.cpp \ GuiHyperlink.cpp \ + GuiIdListModel.cpp \ GuiImage.cpp \ GuiInclude.cpp \ GuiIndex.cpp \ @@ -175,6 +176,7 @@ MOCHEADER = \ GuiFontExample.h \ GuiGraphics.h \ GuiHyperlink.h \ + GuiIdListModel.h \ GuiInclude.h \ GuiIndex.h \ GuiKeySymbol.h \