1 #include "DefaultAircraftLocator.hxx"
2 
3 #include <simgear/props/props_io.hxx>
4 #include <simgear/debug/logstream.hxx>
5 #include <simgear/structure/exception.hxx>
6 
7 #include <Main/globals.hxx>
8 #include <Main/locale.hxx>
9 
loadXMLDefaults()10 static SGPropertyNode_ptr loadXMLDefaults()
11 {
12     SGPropertyNode_ptr root(new SGPropertyNode);
13     const SGPath defaultsXML = globals->get_fg_root() / "defaults.xml";
14     if (!defaultsXML.exists()) {
15         SG_LOG(SG_GUI, SG_POPUP, "Failed to find required data file (defaults.xml)");
16         return {};
17     }
18 
19     try {
20        readProperties(defaultsXML, root);
21     } catch (sg_exception& e) {
22         SG_LOG(SG_GUI, SG_POPUP, "Failed to read required data file (defaults.xml)");
23         return {};
24     }
25 
26     if (!root->hasChild("sim")) {
27         SG_LOG(SG_GUI, SG_POPUP, "Failed to find /sim node in defaults.xml, broken");
28         return {};
29     }
30 
31     return root;
32 }
33 
34 
35 namespace flightgear
36 {
37 
defaultAirportICAO()38 std::string defaultAirportICAO()
39 {
40     SGPropertyNode_ptr root = loadXMLDefaults();
41     if (!root) {
42         return {};
43     }
44 
45     std::string airportCode = root->getStringValue("/sim/presets/airport-id");
46     return airportCode;
47 }
48 
defaultSplashScreenPaths()49 string_list defaultSplashScreenPaths()
50 {
51     string_list result;
52     SGPath tpath = globals->get_fg_root() / "Textures";
53     auto paths = simgear::Dir(tpath).children(simgear::Dir::TYPE_FILE);
54     paths.erase(std::remove_if(paths.begin(), paths.end(), [](const SGPath& p) {
55         const auto f = p.file();
56         if (f.find("Splash") != 0) return true;
57         const auto ext = p.extension();
58         return ext != "png" && ext != "jpg";
59     }), paths.end());
60 
61     for (auto c : paths) {
62         result.push_back(c.utf8Str());
63     }
64 
65     return result;
66 }
67 
DefaultAircraftLocator()68 DefaultAircraftLocator::DefaultAircraftLocator()
69 {
70     SGPropertyNode_ptr root = loadXMLDefaults();
71     if (root) {
72         _aircraftId = root->getStringValue("/sim/aircraft");
73     } else {
74         SG_LOG(SG_GUI, SG_WARN, "failed to load default aircraft identifier");
75         _aircraftId = "ufo"; // last ditch fallback
76     }
77 
78     _aircraftId += "-set.xml";
79     const SGPath rootAircraft = globals->get_fg_root() / "Aircraft";
80     visitDir(rootAircraft, 0);
81 }
82 
foundPath() const83 SGPath DefaultAircraftLocator::foundPath() const
84 {
85     return _foundPath;
86 }
87 
88 AircraftDirVistorBase::VisitResult
visit(const SGPath & p)89 DefaultAircraftLocator::visit(const SGPath& p)
90 {
91     if (p.file() == _aircraftId) {
92         _foundPath = p;
93         return VISIT_DONE;
94     }
95 
96     return VISIT_CONTINUE;
97 }
98 
WeatherScenariosModel(QObject * pr)99 WeatherScenariosModel::WeatherScenariosModel(QObject *pr) :
100     QAbstractListModel(pr)
101 {
102     SGPropertyNode_ptr root = loadXMLDefaults();
103     if (root) {
104         SGPropertyNode_ptr scenarios = root->getNode("environment/weather-scenarios");
105         Q_ASSERT(scenarios);
106         int nChildren = scenarios->nChildren();
107         for (int i = 0; i < nChildren; i++) {
108             SGPropertyNode_ptr scenario = scenarios->getChild(i);
109             if (strcmp(scenario->getName(), "scenario") != 0) {
110                 continue;
111             }
112 
113             // omit the 'live data' option, we have a distinct UI for that, we'll
114             // pass --real-wxr option on launch
115             if (scenario->getStringValue("local-weather/tile-type") == std::string("live")) {
116                 continue;
117             }
118 
119             WeatherScenario ws;
120             const string wsId = scenario->getStringValue("id");
121             if (!wsId.empty()) {
122                 // translated
123                 auto locale = globals->get_locale();
124                 ws.name = QString::fromStdString(locale->getLocalizedString(wsId + "-name", "weather-scenarios"));
125                 ws.description = QString::fromStdString(locale->getLocalizedString(wsId + "-desc", "weather-scenarios"));
126             } else {
127                 ws.name = QString::fromStdString(scenario->getStringValue("name"));
128                 ws.description = QString::fromStdString(scenario->getStringValue("description")).simplified();
129             }
130 
131             ws.metar = QString::fromStdString(scenario->getStringValue("metar"));
132             if (scenario->hasChild("local-weather")) {
133                 ws.localWeatherTileManagement = QString::fromStdString(scenario->getStringValue("local-weather/tile-management"));
134                 ws.localWeatherTileType = QString::fromStdString(scenario->getStringValue("local-weather/tile-type"));
135             }
136             m_scenarios.push_back(ws);
137         }
138     }
139 }
140 
rowCount(const QModelIndex &) const141 int WeatherScenariosModel::rowCount(const QModelIndex&) const
142 {
143     return static_cast<int>(m_scenarios.size());
144 }
145 
data(const QModelIndex & index,int role) const146 QVariant WeatherScenariosModel::data(const QModelIndex &index, int role) const
147 {
148     const int row = index.row();
149     if ((row < 0) || (row >= m_scenarios.size())) {
150            return QVariant();
151     }
152 
153     const WeatherScenario& scenario(m_scenarios.at(row));
154     if ((role == Qt::DisplayRole) || (role == NameRole)) {
155         return scenario.name;
156     } else if (role == DescriptionRole) {
157         return scenario.description;
158     } else if (role == MetarRole) {
159         return scenario.metar;
160     }
161 
162     return QVariant();
163 }
164 
roleNames() const165 QHash<int, QByteArray> WeatherScenariosModel::roleNames() const
166 {
167     QHash<int, QByteArray> result;
168     result[NameRole] = "name";
169     result[DescriptionRole] = "description";
170     result[MetarRole] = "metar";
171     return result;
172 }
173 
metarForItem(quint32 index) const174 QString WeatherScenariosModel::metarForItem(quint32 index) const
175 {
176     if (index >= m_scenarios.size()) {
177         return {};
178     }
179 
180     return m_scenarios.at(index).metar;
181 }
182 
descriptionForItem(quint32 index) const183 QString WeatherScenariosModel::descriptionForItem(quint32 index) const
184 {
185     if (index >= m_scenarios.size()) {
186         return {};
187     }
188 
189     return m_scenarios.at(index).description;
190 }
191 
localWeatherData(quint32 index) const192 QStringList WeatherScenariosModel::localWeatherData(quint32 index) const
193 {
194     if (index >= m_scenarios.size()) {
195         return {};
196     }
197 
198     const auto& s = m_scenarios.at(index);
199     if (s.localWeatherTileManagement.isEmpty() || s.localWeatherTileType.isEmpty()) {
200         return {};
201     }
202 
203     return QStringList() << s.localWeatherTileManagement << s.localWeatherTileType;
204 }
205 
nameForItem(quint32 index) const206 QString WeatherScenariosModel::nameForItem(quint32 index) const
207 {
208     if (index >= m_scenarios.size()) {
209         return {};
210     }
211 
212     return m_scenarios.at(index).name;
213 }
214 
215 } // of namespace flightgear
216