mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-11 05:33:33 +00:00
d5d665482e
The changes that accomplish this part are in ModuleList.{h,cpp}, configure.py, and the *.module files themselves. This is a format change, and the lyx2lyx is in those files. By itself, that change would not be major, except for the fact that we do not want the module to be represented in the UI by its filename---e.g., theorems-std---but rather by a descriptive name, such as "Theorems". But that change turns out to be wholly non-trivial. The mechanism for choosing modules was the same as---indeed, was borrowed from---that in GuiCitation: You get a list of modules, and choosing them involves moving strings from one QListView to another. The models underlying these views are just QStringListModels, which means that, when you want to know what modules have been selected, you see what strings are in the "selected" QListView. But these are just the descriptive names, and we can't look up a module by its descriptive name if it's been translated. That, indeed, was the whole point of the change to the new representation. So, we need a more complicated model underlying the QListView, one that will pair an identifying string---the filename minus the extension, in this case---with each item. This turns out not to be terribly difficult, though it took rather a while for me to understand why it's not difficult. There are two parts: (i) GuiSelectionManger gets re-written to use any QAbstractListModel, not just a QStringListModel. This actually seems to improve the code, independently. (ii) We then subclass QAbstractListModel to get the associated ID string, using the Qt::UserRole slot associated with each item to store its ID. This would be almost completely trivial if QAbstractListItem::itemData() included the QVariant associated with this role, but it doesn't, so there are some additional hoops through which to jump. The new model, a GuiIdListModel, is defined in the files by that name. The changes in GuiSelectionManger.{h,cpp} make it more abstract; the changes in GuiDocument.{h,cpp} adapt it to the new framework. I've also updated the module documenation to accord with this change. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@22501 a592a061-630c-0410-9148-cb99ea01b6c8
232 lines
5.1 KiB
C++
232 lines
5.1 KiB
C++
// -*- C++ -*-
|
|
/**
|
|
* \file ModuleList.cpp
|
|
* This file is part of LyX, the document processor.
|
|
* Licence details can be found in the file COPYING.
|
|
*
|
|
* \author Richard Heck
|
|
*
|
|
* Full author contact details are available in file CREDITS.
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include "ModuleList.h"
|
|
|
|
#include "support/debug.h"
|
|
#include "LaTeXFeatures.h"
|
|
#include "Lexer.h"
|
|
|
|
#include "support/FileName.h"
|
|
#include "support/filetools.h"
|
|
#include "support/lstrings.h"
|
|
|
|
#include <algorithm>
|
|
#include <ostream>
|
|
|
|
using namespace std;
|
|
using namespace lyx::support;
|
|
|
|
namespace lyx {
|
|
|
|
|
|
//global variable: module list
|
|
ModuleList moduleList;
|
|
|
|
|
|
LyXModule::LyXModule(string const & n, string const & i,
|
|
string const & d, vector<string> const & p,
|
|
vector<string> const & r, vector<string> const & e):
|
|
name(n), id(i), description(d),
|
|
packageList(p), requiredModules(r), excludedModules(e),
|
|
checked(false)
|
|
{
|
|
filename = id + ".module";
|
|
}
|
|
|
|
|
|
bool LyXModule::isAvailable() {
|
|
if (packageList.empty())
|
|
return true;
|
|
if (checked)
|
|
return available;
|
|
checked = true;
|
|
//check whether all of the required packages are available
|
|
vector<string>::const_iterator it = packageList.begin();
|
|
vector<string>::const_iterator end = packageList.end();
|
|
for (; it != end; ++it) {
|
|
if (!LaTeXFeatures::isAvailable(*it)) {
|
|
available = false;
|
|
return available;
|
|
}
|
|
}
|
|
available = true;
|
|
return available;
|
|
}
|
|
|
|
|
|
// used when sorting the module list.
|
|
class ModuleSorter
|
|
{
|
|
public:
|
|
int operator()(LyXModule const & lm1, LyXModule const & lm2) const
|
|
{
|
|
return lm1.getName() < lm2.getName();
|
|
}
|
|
};
|
|
|
|
|
|
//Much of this is borrowed from TextClassList::read()
|
|
bool ModuleList::load()
|
|
{
|
|
FileName const real_file = libFileSearch("", "lyxmodules.lst");
|
|
LYXERR(Debug::TCLASS, "Reading modules from `" << real_file << '\'');
|
|
|
|
if (real_file.empty()) {
|
|
lyxerr << "ModuleList::load(): unable to find "
|
|
"modules file `"
|
|
<< to_utf8(makeDisplayPath(real_file.absFilename(), 1000))
|
|
<< "'.\nNo modules will be available." << endl;
|
|
return false;
|
|
}
|
|
|
|
Lexer lex(0, 0);
|
|
if (!lex.setFile(real_file)) {
|
|
lyxerr << "ModuleList::load():"
|
|
"lyxlex was not able to set file: "
|
|
<< real_file << ".\nNo modules will be available." << endl;
|
|
return false;
|
|
}
|
|
|
|
if (!lex.isOK()) {
|
|
lyxerr << "ModuleList::load():" <<
|
|
"unable to open modules file `"
|
|
<< to_utf8(makeDisplayPath(real_file.absFilename(), 1000))
|
|
<< "'\nNo modules will be available."
|
|
<< endl;
|
|
return false;
|
|
}
|
|
|
|
bool finished = false;
|
|
// Parse modules files
|
|
LYXERR(Debug::TCLASS, "Starting parsing of lyxmodules.lst");
|
|
while (lex.isOK() && !finished) {
|
|
LYXERR(Debug::TCLASS, "\tline by line");
|
|
switch (lex.lex()) {
|
|
case Lexer::LEX_FEOF:
|
|
finished = true;
|
|
break;
|
|
default:
|
|
string const modName = lex.getString();
|
|
LYXERR(Debug::TCLASS, "Module name: " << modName);
|
|
if (!lex.next())
|
|
break;
|
|
string const fname = lex.getString();
|
|
LYXERR(Debug::TCLASS, "Filename: " << fname);
|
|
if (!lex.next())
|
|
break;
|
|
string const desc = lex.getString();
|
|
LYXERR(Debug::TCLASS, "Description: " << desc);
|
|
//FIXME Add packages
|
|
if (!lex.next())
|
|
break;
|
|
string str = lex.getString();
|
|
LYXERR(Debug::TCLASS, "Packages: " << str);
|
|
vector<string> pkgs;
|
|
while (!str.empty()) {
|
|
string p;
|
|
str = split(str, p, ',');
|
|
pkgs.push_back(p);
|
|
}
|
|
if (!lex.next())
|
|
break;
|
|
str = lex.getString();
|
|
LYXERR(Debug::TCLASS, "Required: " << str);
|
|
vector<string> req;
|
|
while (!str.empty()) {
|
|
string p;
|
|
str = split(str, p, '|');
|
|
req.push_back(p);
|
|
}
|
|
if (!lex.next())
|
|
break;
|
|
str = lex.getString();
|
|
LYXERR(Debug::TCLASS, "Excluded: " << str);
|
|
vector<string> exc;
|
|
while (!str.empty()) {
|
|
string p;
|
|
str = split(str, p, '|');
|
|
exc.push_back(p);
|
|
}
|
|
// This code is run when we have
|
|
// modName, fname, desc, pkgs, req, and exc
|
|
addLayoutModule(modName, fname, desc, pkgs, req, exc);
|
|
} // end switch
|
|
} //end while
|
|
|
|
LYXERR(Debug::TCLASS, "End of parsing of lyxmodules.lst");
|
|
|
|
if (!moduleList.empty())
|
|
sort(moduleList.begin(), moduleList.end(), ModuleSorter());
|
|
return true;
|
|
}
|
|
|
|
|
|
void ModuleList::addLayoutModule(string const & moduleName,
|
|
string const & filename, string const & description,
|
|
vector<string> const & pkgs, vector<string> const & req,
|
|
vector<string> const & exc)
|
|
{
|
|
LyXModule lm(moduleName, filename, description, pkgs, req, exc);
|
|
modlist_.push_back(lm);
|
|
}
|
|
|
|
|
|
LyXModuleList::const_iterator ModuleList::begin() const
|
|
{
|
|
return modlist_.begin();
|
|
}
|
|
|
|
|
|
LyXModuleList::iterator ModuleList::begin()
|
|
{
|
|
return modlist_.begin();
|
|
}
|
|
|
|
|
|
LyXModuleList::const_iterator ModuleList::end() const
|
|
{
|
|
return modlist_.end();
|
|
}
|
|
|
|
|
|
LyXModuleList::iterator ModuleList::end()
|
|
{
|
|
return modlist_.end();
|
|
}
|
|
|
|
|
|
LyXModule * ModuleList::getModuleByName(string const & str)
|
|
{
|
|
LyXModuleList::iterator it = modlist_.begin();
|
|
for (; it != modlist_.end(); ++it)
|
|
if (it->getName() == str) {
|
|
LyXModule & mod = *it;
|
|
return &mod;
|
|
}
|
|
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
|