Rewrite --show-aircraft and --aircraft handling to share directory search code.
As a bonus, sort the --show-aircraft list case-insensitively.
This commit is contained in:
parent
af3f072c21
commit
c95a5db23d
4 changed files with 276 additions and 240 deletions
|
@ -57,6 +57,7 @@
|
||||||
#include <simgear/structure/exception.hxx>
|
#include <simgear/structure/exception.hxx>
|
||||||
#include <simgear/structure/event_mgr.hxx>
|
#include <simgear/structure/event_mgr.hxx>
|
||||||
#include <simgear/misc/sg_path.hxx>
|
#include <simgear/misc/sg_path.hxx>
|
||||||
|
#include <simgear/misc/sg_dir.hxx>
|
||||||
#include <simgear/misc/interpolator.hxx>
|
#include <simgear/misc/interpolator.hxx>
|
||||||
#include <simgear/scene/material/matlib.hxx>
|
#include <simgear/scene/material/matlib.hxx>
|
||||||
#include <simgear/scene/model/particles.hxx>
|
#include <simgear/scene/model/particles.hxx>
|
||||||
|
@ -499,68 +500,153 @@ do_options (int argc, char ** argv)
|
||||||
fgParseArgs(argc, argv);
|
fgParseArgs(argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
static string fgFindAircraftPath( const SGPath &path, const string &aircraft,
|
void fgFindAircraftInDir(const SGPath& dirPath, T* obj, bool (T::*pred)(const SGPath& p))
|
||||||
SGPropertyNode *cache, int depth = 0 )
|
|
||||||
{
|
{
|
||||||
const int MAXDEPTH = 1;
|
if (!dirPath.exists()) {
|
||||||
|
SG_LOG(SG_GENERAL, SG_WARN, "fgFindAircraftInDir: no such path:" << dirPath.str());
|
||||||
ulDirEnt* dire;
|
return;
|
||||||
ulDir *dirp = ulOpenDir(path.str().c_str());
|
|
||||||
if (dirp == NULL) {
|
|
||||||
cerr << "Unable to open aircraft directory '" << path.str() << '\'' << endl;
|
|
||||||
exit(-1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string result;
|
bool recurse = true;
|
||||||
while ((dire = ulReadDir(dirp)) != NULL) {
|
simgear::Dir dir(dirPath);
|
||||||
if (dire->d_isdir) {
|
simgear::PathList setFiles(dir.children(simgear::Dir::TYPE_FILE, "-set.xml"));
|
||||||
if (depth > MAXDEPTH)
|
simgear::PathList::iterator p;
|
||||||
|
for (p = setFiles.begin(); p != setFiles.end(); ++p) {
|
||||||
|
// check file name ends with -set.xml
|
||||||
|
|
||||||
|
// if we found a -set.xml at this level, don't recurse any deeper
|
||||||
|
recurse = false;
|
||||||
|
|
||||||
|
bool done = (obj->*pred)(*p);
|
||||||
|
if (done) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} // of -set.xml iteration
|
||||||
|
|
||||||
|
if (recurse) {
|
||||||
|
simgear::PathList subdirs(dir.children(simgear::Dir::TYPE_DIR | simgear::Dir::NO_DOT_OR_DOTDOT));
|
||||||
|
for (p = subdirs.begin(); p != subdirs.end(); ++p) {
|
||||||
|
if (p->file() == "CVS") {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!strcmp("CVS", dire->d_name) || !strcmp(".", dire->d_name)
|
fgFindAircraftInDir(*p, obj, pred);
|
||||||
|| !strcmp("..", dire->d_name) || !strcmp("AI", dire->d_name))
|
}
|
||||||
|
} // of recursive case
|
||||||
|
}
|
||||||
|
|
||||||
|
class FindAndCacheAircraft
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FindAndCacheAircraft(SGPropertyNode* autoSave)
|
||||||
|
{
|
||||||
|
_cache = autoSave->getNode("sim/startup/path-cache", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool loadAircraft()
|
||||||
|
{
|
||||||
|
std::string aircraft = fgGetString( "/sim/aircraft", "");
|
||||||
|
if (aircraft.empty()) {
|
||||||
|
SG_LOG(SG_GENERAL, SG_ALERT, "no aircraft specified");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_searchAircraft = aircraft + "-set.xml";
|
||||||
|
if (!checkCache()) {
|
||||||
|
// prepare cache for re-scan
|
||||||
|
SGPropertyNode *n = _cache->getNode("fg-root", true);
|
||||||
|
n->setStringValue(globals->get_fg_root().c_str());
|
||||||
|
n->setAttribute(SGPropertyNode::USERARCHIVE, true);
|
||||||
|
_cache->removeChildren("aircraft");
|
||||||
|
|
||||||
|
SGPath aircraftDir(globals->get_fg_root());
|
||||||
|
aircraftDir.append("Aircraft");
|
||||||
|
|
||||||
|
fgFindAircraftInDir(aircraftDir, this, &FindAndCacheAircraft::checkAircraft);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_foundPath.str().empty()) {
|
||||||
|
SG_LOG(SG_GENERAL, SG_ALERT, "Cannot find specified aircraft: " << aircraft );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SG_LOG(SG_GENERAL, SG_INFO, "Loading aircraft -set file from:" << _foundPath.str());
|
||||||
|
fgSetString( "/sim/aircraft-dir", _foundPath.dir().c_str());
|
||||||
|
if (!_foundPath.exists()) {
|
||||||
|
SG_LOG(SG_GENERAL, SG_ALERT, "Unable to find -set file:" << _foundPath.str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
readProperties(_foundPath.str(), globals->get_props());
|
||||||
|
} catch ( const sg_exception &e ) {
|
||||||
|
SG_LOG(SG_INPUT, SG_ALERT, "Error reading aircraft: " << e.getFormattedMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool checkCache()
|
||||||
|
{
|
||||||
|
if (globals->get_fg_root() != _cache->getStringValue("fg-root", "")) {
|
||||||
|
return false; // cache mismatch
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<SGPropertyNode_ptr> cache = _cache->getChildren("aircraft");
|
||||||
|
for (unsigned int i = 0; i < cache.size(); i++) {
|
||||||
|
const char *name = cache[i]->getStringValue("file", "");
|
||||||
|
if (!boost::equals(_searchAircraft, name, is_iequal())) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
SGPath next = path;
|
SGPath xml(cache[i]->getStringValue("path", ""));
|
||||||
next.append(dire->d_name);
|
xml.append(name);
|
||||||
|
if (xml.exists()) {
|
||||||
|
_foundPath = xml;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
result = fgFindAircraftPath( next, aircraft, cache, depth + 1 );
|
return false;
|
||||||
if ( ! result.empty() )
|
} // of aircraft in cache iteration
|
||||||
break;
|
|
||||||
|
|
||||||
} else {
|
return false;
|
||||||
int len = strlen(dire->d_name);
|
}
|
||||||
if (len < 9 || strcmp(dire->d_name + len - 8, "-set.xml"))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
|
bool checkAircraft(const SGPath& p)
|
||||||
|
{
|
||||||
// create cache node
|
// create cache node
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (1)
|
while (1) {
|
||||||
if (!cache->getChild("aircraft", i++, false))
|
if (!_cache->getChild("aircraft", i++, false))
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
SGPropertyNode *n, *entry = cache->getChild("aircraft", --i, true);
|
SGPropertyNode *n, *entry = _cache->getChild("aircraft", --i, true);
|
||||||
|
|
||||||
|
std::string fileName(p.file());
|
||||||
n = entry->getNode("file", true);
|
n = entry->getNode("file", true);
|
||||||
n->setStringValue(dire->d_name);
|
n->setStringValue(fileName);
|
||||||
n->setAttribute(SGPropertyNode::USERARCHIVE, true);
|
n->setAttribute(SGPropertyNode::USERARCHIVE, true);
|
||||||
|
|
||||||
n = entry->getNode("path", true);
|
n = entry->getNode("path", true);
|
||||||
n->setStringValue(path.str().c_str());
|
n->setStringValue(p.dir());
|
||||||
n->setAttribute(SGPropertyNode::USERARCHIVE, true);
|
n->setAttribute(SGPropertyNode::USERARCHIVE, true);
|
||||||
|
|
||||||
if ( boost::equals(dire->d_name, aircraft.c_str(), is_iequal()) ) {
|
if ( boost::equals(fileName, _searchAircraft.c_str(), is_iequal()) ) {
|
||||||
result = path.str();
|
_foundPath = p;
|
||||||
break;
|
return true;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ulCloseDir(dirp);
|
return false;
|
||||||
return result;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
std::string _searchAircraft;
|
||||||
|
SGPath _foundPath;
|
||||||
|
SGPropertyNode* _cache;
|
||||||
|
};
|
||||||
|
|
||||||
// Read in configuration (file and command line)
|
// Read in configuration (file and command line)
|
||||||
bool fgInitConfig ( int argc, char **argv ) {
|
bool fgInitConfig ( int argc, char **argv ) {
|
||||||
|
@ -606,79 +692,24 @@ bool fgInitConfig ( int argc, char **argv ) {
|
||||||
home->setAttribute(SGPropertyNode::WRITE, false);
|
home->setAttribute(SGPropertyNode::WRITE, false);
|
||||||
|
|
||||||
config.append( "autosave.xml" );
|
config.append( "autosave.xml" );
|
||||||
|
if (config.exists()) {
|
||||||
SG_LOG(SG_INPUT, SG_INFO, "Reading user settings from " << config.str());
|
SG_LOG(SG_INPUT, SG_INFO, "Reading user settings from " << config.str());
|
||||||
try {
|
try {
|
||||||
readProperties(config.str(), &autosave, SGPropertyNode::USERARCHIVE);
|
readProperties(config.str(), &autosave, SGPropertyNode::USERARCHIVE);
|
||||||
} catch (...) {
|
} catch (sg_exception& e) {
|
||||||
SG_LOG(SG_INPUT, SG_DEBUG, "First time reading user settings");
|
SG_LOG(SG_INPUT, SG_WARN, "failed to read user settings:" << e.getMessage()
|
||||||
|
<< "(from " << e.getOrigin() << ")");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
SG_LOG(SG_INPUT, SG_DEBUG, "Finished Reading user settings");
|
|
||||||
}
|
}
|
||||||
SGPropertyNode *cache_root = autosave.getNode("sim/startup/path-cache", true);
|
|
||||||
|
|
||||||
|
|
||||||
// Scan user config files and command line for a specified aircraft.
|
// Scan user config files and command line for a specified aircraft.
|
||||||
fgInitFGAircraft(argc, argv);
|
fgInitFGAircraft(argc, argv);
|
||||||
|
FindAndCacheAircraft f(&autosave);
|
||||||
string aircraft = fgGetString( "/sim/aircraft", "" );
|
if (!f.loadAircraft()) {
|
||||||
if ( aircraft.size() > 0 ) {
|
|
||||||
SGPath aircraft_search( globals->get_fg_root() );
|
|
||||||
aircraft_search.append( "Aircraft" );
|
|
||||||
|
|
||||||
string aircraft_set = aircraft + "-set.xml";
|
|
||||||
string result;
|
|
||||||
|
|
||||||
// check if the *-set.xml file is already in the cache
|
|
||||||
if (globals->get_fg_root() == cache_root->getStringValue("fg-root", "")) {
|
|
||||||
vector<SGPropertyNode_ptr> cache = cache_root->getChildren("aircraft");
|
|
||||||
for (unsigned int i = 0; i < cache.size(); i++) {
|
|
||||||
const char *name = cache[i]->getStringValue("file", "");
|
|
||||||
if (boost::equals(aircraft_set, name, is_iequal())) {
|
|
||||||
const char *path = cache[i]->getStringValue("path", "");
|
|
||||||
SGPath xml(path);
|
|
||||||
xml.append(name);
|
|
||||||
if (xml.exists())
|
|
||||||
result = path;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.empty()) {
|
|
||||||
// prepare cache for rescan
|
|
||||||
SGPropertyNode *n = cache_root->getNode("fg-root", true);
|
|
||||||
n->setStringValue(globals->get_fg_root().c_str());
|
|
||||||
n->setAttribute(SGPropertyNode::USERARCHIVE, true);
|
|
||||||
cache_root->removeChildren("aircraft");
|
|
||||||
|
|
||||||
result = fgFindAircraftPath( aircraft_search, aircraft_set, cache_root );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !result.empty() ) {
|
|
||||||
fgSetString( "/sim/aircraft-dir", result.c_str() );
|
|
||||||
SGPath full_name( result );
|
|
||||||
full_name.append( aircraft_set );
|
|
||||||
|
|
||||||
SG_LOG(SG_INPUT, SG_INFO, "Reading default aircraft: " << aircraft
|
|
||||||
<< " from " << full_name.str());
|
|
||||||
try {
|
|
||||||
readProperties( full_name.str(), globals->get_props() );
|
|
||||||
} catch ( const sg_exception &e ) {
|
|
||||||
string message = "Error reading default aircraft: ";
|
|
||||||
message += e.getFormattedMessage();
|
|
||||||
SG_LOG(SG_INPUT, SG_ALERT, message);
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
SG_LOG( SG_INPUT, SG_ALERT, "Cannot find specified aircraft: "
|
|
||||||
<< aircraft );
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
|
||||||
SG_LOG( SG_INPUT, SG_ALERT, "No default aircraft specified" );
|
|
||||||
}
|
|
||||||
|
|
||||||
copyProperties(&autosave, globals->get_props());
|
copyProperties(&autosave, globals->get_props());
|
||||||
|
|
||||||
// parse options after loading aircraft to ensure any user
|
// parse options after loading aircraft to ensure any user
|
||||||
|
@ -1707,3 +1738,114 @@ void doSimulatorReset(void) // from gui_local.cxx -- TODO merge with fgReInitSu
|
||||||
master_freeze->setBoolValue(false);
|
master_freeze->setBoolValue(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// helper object to implement the --show-aircraft command.
|
||||||
|
// resides here so we can share the fgFindAircraftInDir template above,
|
||||||
|
// and hence ensure this command lists exectly the same aircraft as the normal
|
||||||
|
// loading path.
|
||||||
|
class ShowAircraft
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ShowAircraft()
|
||||||
|
{
|
||||||
|
_minStatus = getNumMaturity(fgGetString("/sim/aircraft-min-status", "all"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void show(const SGPath& path)
|
||||||
|
{
|
||||||
|
fgFindAircraftInDir(path, this, &ShowAircraft::processAircraft);
|
||||||
|
|
||||||
|
std::sort(_aircraft.begin(), _aircraft.end(), ciLessLibC());
|
||||||
|
SG_LOG( SG_GENERAL, SG_ALERT, "" ); // To popup the console on Windows
|
||||||
|
cout << "Available aircraft:" << endl;
|
||||||
|
for ( unsigned int i = 0; i < _aircraft.size(); i++ ) {
|
||||||
|
cout << _aircraft[i] << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool processAircraft(const SGPath& path)
|
||||||
|
{
|
||||||
|
SGPropertyNode root;
|
||||||
|
try {
|
||||||
|
readProperties(path.str(), &root);
|
||||||
|
} catch (sg_exception& e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int maturity = 0;
|
||||||
|
string descStr(" ");
|
||||||
|
descStr += path.file();
|
||||||
|
|
||||||
|
SGPropertyNode *node = root.getNode("sim");
|
||||||
|
if (node) {
|
||||||
|
SGPropertyNode* desc = node->getNode("description");
|
||||||
|
// if a status tag is found, read it in
|
||||||
|
if (node->hasValue("status")) {
|
||||||
|
maturity = getNumMaturity(node->getStringValue("status"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (desc) {
|
||||||
|
if (descStr.size() <= 27+3) {
|
||||||
|
descStr.append(29+3-descStr.size(), ' ');
|
||||||
|
} else {
|
||||||
|
descStr += '\n';
|
||||||
|
descStr.append( 32, ' ');
|
||||||
|
}
|
||||||
|
descStr += desc->getStringValue();
|
||||||
|
}
|
||||||
|
} // of have 'sim' node
|
||||||
|
|
||||||
|
if (maturity < _minStatus) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_aircraft.push_back(descStr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int getNumMaturity(const char * str)
|
||||||
|
{
|
||||||
|
// changes should also be reflected in $FG_ROOT/data/options.xml &
|
||||||
|
// $FG_ROOT/data/Translations/string-default.xml
|
||||||
|
const char* levels[] = {"alpha","beta","early-production","production"};
|
||||||
|
|
||||||
|
if (!strcmp(str, "all")) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i=0; i<(sizeof(levels)/sizeof(levels[0]));i++)
|
||||||
|
if (strcmp(str,levels[i])==0)
|
||||||
|
return i;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// recommended in Meyers, Effective STL when internationalization and embedded
|
||||||
|
// NULLs aren't an issue. Much faster than the STL or Boost lex versions.
|
||||||
|
struct ciLessLibC : public std::binary_function<string, string, bool>
|
||||||
|
{
|
||||||
|
bool operator()(const std::string &lhs, const std::string &rhs) const
|
||||||
|
{
|
||||||
|
return strcasecmp(lhs.c_str(), rhs.c_str()) < 0 ? 1 : 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int _minStatus;
|
||||||
|
string_list _aircraft;
|
||||||
|
};
|
||||||
|
|
||||||
|
void fgShowAircraft(const SGPath &path)
|
||||||
|
{
|
||||||
|
ShowAircraft s;
|
||||||
|
s.show(path);
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
cout << "Hit a key to continue..." << endl;
|
||||||
|
cin.get();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
// forward decls
|
// forward decls
|
||||||
class SGPropertyNode;
|
class SGPropertyNode;
|
||||||
class SGTime;
|
class SGTime;
|
||||||
|
class SGPath;
|
||||||
|
|
||||||
// Read in configuration (files and command line optoins) but only set
|
// Read in configuration (files and command line optoins) but only set
|
||||||
// fg_root
|
// fg_root
|
||||||
|
@ -86,6 +87,14 @@ SGTime *fgInitTime();
|
||||||
// set up a time offset (aka warp) if one is specified
|
// set up a time offset (aka warp) if one is specified
|
||||||
void fgInitTimeOffset();
|
void fgInitTimeOffset();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Search in the current directory, and in on directory deeper
|
||||||
|
* for <aircraft>-set.xml configuration files and show the aircaft name
|
||||||
|
* and the contents of the<description> tag in a sorted manner.
|
||||||
|
*
|
||||||
|
* @parampath the directory to search for configuration files
|
||||||
|
*/
|
||||||
|
void fgShowAircraft(const SGPath &path);
|
||||||
|
|
||||||
#endif // _FG_INIT_HXX
|
#endif // _FG_INIT_HXX
|
||||||
|
|
||||||
|
|
|
@ -1642,7 +1642,7 @@ fgParseArgs (int argc, char **argv)
|
||||||
fgOptLogLevel( "alert" );
|
fgOptLogLevel( "alert" );
|
||||||
SGPath path( globals->get_fg_root() );
|
SGPath path( globals->get_fg_root() );
|
||||||
path.append("Aircraft");
|
path.append("Aircraft");
|
||||||
fgShowAircraft(path, true);
|
fgShowAircraft(path);
|
||||||
exit(0);
|
exit(0);
|
||||||
|
|
||||||
} else if (result == FG_OPTIONS_SHOW_SOUND_DEVICES) {
|
} else if (result == FG_OPTIONS_SHOW_SOUND_DEVICES) {
|
||||||
|
@ -1847,117 +1847,3 @@ fgUsage (bool verbose)
|
||||||
cin.get();
|
cin.get();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// A simple function to return an integer depending on the position
|
|
||||||
// of the status string within the array in order to determine the hierarchy.
|
|
||||||
unsigned int getNumMaturity(const char * str)
|
|
||||||
{
|
|
||||||
// changes should also be reflected in $FG_ROOT/data/options.xml &
|
|
||||||
// $FG_ROOT/data/Translations/string-default.xml
|
|
||||||
const char* levels[] = {"alpha","beta","early-production","production"};
|
|
||||||
|
|
||||||
if (!strcmp(str, "all")) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i=0; i<(sizeof(levels)/sizeof(levels[0]));i++)
|
|
||||||
if (strcmp(str,levels[i])==0)
|
|
||||||
return i;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static void fgSearchAircraft(const SGPath &path, string_list &aircraft,
|
|
||||||
bool recursive)
|
|
||||||
{
|
|
||||||
if (!path.exists()) {
|
|
||||||
SG_LOG(SG_GENERAL, SG_WARN, "fgSearchAircraft: no such path:" << path.str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int requiredStatus = getNumMaturity(fgGetString("/sim/aircraft-min-status", "all"));
|
|
||||||
|
|
||||||
simgear::Dir dir(path);
|
|
||||||
simgear::PathList setFiles(dir.children(simgear::Dir::TYPE_FILE, "-set.xml"));
|
|
||||||
simgear::PathList::iterator p;
|
|
||||||
for (p = setFiles.begin(); p != setFiles.end(); ++p) {
|
|
||||||
// check file name ends with -set.xml
|
|
||||||
|
|
||||||
SGPropertyNode root;
|
|
||||||
try {
|
|
||||||
readProperties(p->str(), &root);
|
|
||||||
} catch (sg_exception& e) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int maturity = 0;
|
|
||||||
string descStr(" ");
|
|
||||||
descStr += path.file();
|
|
||||||
|
|
||||||
SGPropertyNode *node = root.getNode("sim");
|
|
||||||
if (node) {
|
|
||||||
SGPropertyNode* desc = node->getNode("description");
|
|
||||||
// if a status tag is found, read it in
|
|
||||||
if (node->hasValue("status")) {
|
|
||||||
maturity = getNumMaturity(node->getStringValue("status"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desc) {
|
|
||||||
if (descStr.size() <= 27+3) {
|
|
||||||
descStr.append(29+3-descStr.size(), ' ');
|
|
||||||
} else {
|
|
||||||
descStr += '\n';
|
|
||||||
descStr.append( 32, ' ');
|
|
||||||
}
|
|
||||||
descStr += desc->getStringValue();
|
|
||||||
}
|
|
||||||
} // of have 'sim' node
|
|
||||||
|
|
||||||
if (maturity < requiredStatus) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we found a -set.xml at this level, don't recurse any deeper
|
|
||||||
recursive = false;
|
|
||||||
|
|
||||||
aircraft.push_back(descStr);
|
|
||||||
} // of -set.xml iteration
|
|
||||||
|
|
||||||
// recurse down if requested
|
|
||||||
if (recursive) {
|
|
||||||
simgear::PathList subdirs(dir.children(simgear::Dir::TYPE_DIR | simgear::Dir::NO_DOT_OR_DOTDOT));
|
|
||||||
for (p = subdirs.begin(); p != subdirs.end(); ++p) {
|
|
||||||
if (p->file() == "CVS") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
fgSearchAircraft(*p, aircraft, recursive);
|
|
||||||
}
|
|
||||||
} // of recursive case
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Search in the current directory, and in on directory deeper
|
|
||||||
* for <aircraft>-set.xml configuration files and show the aircaft name
|
|
||||||
* and the contents of the<description> tag in a sorted manner.
|
|
||||||
*
|
|
||||||
* @parampath the directory to search for configuration files
|
|
||||||
* @param recursive defines whether the directory should be searched recursively
|
|
||||||
*/
|
|
||||||
void fgShowAircraft(const SGPath &path, bool recursive) {
|
|
||||||
string_list aircraft;
|
|
||||||
|
|
||||||
fgSearchAircraft( path, aircraft, recursive );
|
|
||||||
|
|
||||||
sort(aircraft.begin(), aircraft.end());
|
|
||||||
SG_LOG( SG_GENERAL, SG_ALERT, "" ); // To popup the console on Windows
|
|
||||||
cout << "Available aircraft:" << endl;
|
|
||||||
for ( unsigned int i = 0; i < aircraft.size(); i++ ) {
|
|
||||||
cout << aircraft[i] << endl;
|
|
||||||
}
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
cout << "Hit a key to continue..." << endl;
|
|
||||||
cin.get();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
|
@ -33,6 +33,5 @@ extern void fgSetDefaults ();
|
||||||
extern void fgParseArgs (int argc, char ** argv);
|
extern void fgParseArgs (int argc, char ** argv);
|
||||||
extern void fgParseOptions (const string &file_path);
|
extern void fgParseOptions (const string &file_path);
|
||||||
extern void fgUsage (bool verbose = false);
|
extern void fgUsage (bool verbose = false);
|
||||||
extern void fgShowAircraft(const SGPath &path, bool recursive);
|
|
||||||
|
|
||||||
#endif /* _OPTIONS_HXX */
|
#endif /* _OPTIONS_HXX */
|
||||||
|
|
Loading…
Add table
Reference in a new issue