1 | /* |
2 | * Copyright (C) 2012 Cutehacks AS. All rights reserved. |
3 | * info@cutehacks.com |
4 | * http://cutehacks.com |
5 | * |
6 | * This file is part of Fly. |
7 | * |
8 | * Fly is free software: you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by |
10 | * the Free Software Foundation, either version 3 of the License, or |
11 | * (at your option) any later version. |
12 | * |
13 | * Fly is distributed in the hope that it will be useful, |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | * GNU General Public License for more details. |
17 | * |
18 | * You should have received a copy of the GNU General Public License |
19 | * along with Fly. If not, see <http://www.gnu.org/licenses/>. |
20 | */ |
21 | |
22 | #include "flightsmodel.h" |
23 | |
24 | #include "settings.h" |
25 | #include "airportnames.h" |
26 | #include "flightstatuses.h" |
27 | #include "node.h" |
28 | |
29 | FlightsModel::FlightsModel(Settings *settings, |
30 | AirportNames *airports, |
31 | FlightStatuses *statuses, |
32 | FlightTimes *times, |
33 | QObject *parent) |
34 | : QAbstractListModel(parent), |
35 | m_settings(settings), |
36 | m_airports(airports), |
37 | m_statuses(statuses), |
38 | m_times(times) |
39 | { |
40 | QHash<int,QByteArray> names; |
41 | names.insert(0, "uniqueID" ); |
42 | names.insert(1, "airline" ); |
43 | names.insert(2, "flightID" ); |
44 | names.insert(3, "domesticOrInternational" ); |
45 | names.insert(4, "scheduleTime" ); |
46 | names.insert(5, "arrivalOrDeparture" ); |
47 | names.insert(6, "airportCode" ); |
48 | names.insert(7, "airportName" ); |
49 | names.insert(8, "viaAirportCodes" ); |
50 | names.insert(9, "viaAirportNames" ); |
51 | names.insert(10, "routeAirportNames" ); |
52 | names.insert(11, "checkinArea" ); |
53 | names.insert(12, "gate" ); |
54 | names.insert(13, "statusCode" ); |
55 | names.insert(14, "statusText" ); |
56 | names.insert(15, "statusTime" ); |
57 | names.insert(16, "beltNumber" ); |
58 | names.insert(17, "roundtrip" ); |
59 | names.insert(18, "scheduleText" ); |
60 | setRoleNames(names); |
61 | |
62 | m_times->setAirportCode(m_settings->airportCode()); |
63 | QObject::connect(m_times, SIGNAL(dataUpdated(Node*)), this, SLOT(updateContents(Node*))); |
64 | QObject::connect(m_times, SIGNAL(airportCodeChanged()), this, SIGNAL(airportCodeChanged())); |
65 | QObject::connect(m_settings, SIGNAL(airportCodeChanged()), this, SLOT(reloadContents())); |
66 | } |
67 | |
68 | FlightsModel::~FlightsModel() |
69 | { |
70 | } |
71 | |
72 | int FlightsModel::rowCount(const QModelIndex &parent) const |
73 | { |
74 | return parent.isValid() ? 0 : m_flights.count(); |
75 | } |
76 | |
77 | bool FlightsModel::isLoading() const |
78 | { |
79 | return m_flights.isEmpty();// && m_times && m_times->isWaiting(); |
80 | } |
81 | |
82 | QString FlightsModel::airportCode() const |
83 | { |
84 | return m_times ? m_times->airportCode() : QString(); |
85 | } |
86 | |
87 | QVariant FlightsModel::data(const QModelIndex &index, int role) const |
88 | { |
89 | if (index.isValid()) { |
90 | switch (role) { |
91 | case 0: return m_flights.value(index.row()).m_uniqueID; |
92 | case 1: return m_flights.value(index.row()).m_airline; |
93 | case 2: return m_flights.value(index.row()).m_flightID; |
94 | case 3: return m_flights.value(index.row()).m_domesticOrInternational; |
95 | case 4: return m_flights.value(index.row()).m_scheduleTime; |
96 | case 5: return m_flights.value(index.row()).m_arrivalOrDeparture; |
97 | case 6: return m_flights.value(index.row()).m_airportCode; |
98 | case 7: return m_flights.value(index.row()).m_airportName; |
99 | case 8: return m_flights.value(index.row()).m_viaAirportCodes; |
100 | case 9: return m_flights.value(index.row()).m_viaAirportNames; |
101 | case 10: return m_flights.value(index.row()).m_routeAirportNames; |
102 | case 11: return m_flights.value(index.row()).m_checkinArea; |
103 | case 12: return m_flights.value(index.row()).m_gate; |
104 | case 13: return m_flights.value(index.row()).m_statusCode; |
105 | case 14: return m_flights.value(index.row()).m_statusText; |
106 | case 15: return m_flights.value(index.row()).m_statusTime; |
107 | case 16: return m_flights.value(index.row()).m_beltNumber; |
108 | case 17: return m_flights.value(index.row()).m_roundtrip; |
109 | case 18: return m_flights.value(index.row()).m_scheduleText; |
110 | default: break; |
111 | } |
112 | } |
113 | return QVariant(); |
114 | } |
115 | |
116 | void FlightsModel::reloadContents() |
117 | { |
118 | if (m_times) { |
119 | m_times->setAirportCode(m_settings->airportCode()); |
120 | m_times->start(); |
121 | } |
122 | beginResetModel(); |
123 | m_flights.clear(); |
124 | endResetModel(); |
125 | emit loadingChanged(); |
126 | } |
127 | |
128 | void FlightsModel::updateContents(Node *root) |
129 | { |
130 | beginResetModel(); |
131 | m_flights.clear(); |
132 | |
133 | QStack<Node*> pending; |
134 | pending.push(root); |
135 | while (!pending.isEmpty()) { |
136 | Node *node = pending.pop(); |
137 | for (int i = 0; i < node->childCount(); ++i) { |
138 | Node *child = node->child(i); |
139 | if (child->type() == "flight" ) { |
140 | appendFlightData(child); |
141 | } else { |
142 | pending.push(child); |
143 | } |
144 | } |
145 | } |
146 | |
147 | endResetModel(); |
148 | emit loadingChanged(); |
149 | } |
150 | |
151 | void FlightsModel::appendFlightData(Node *flight) |
152 | { |
153 | const QString airportCode = m_times->airportCode(); |
154 | FlightData data; |
155 | if (flight && flight->type() == "flight" ) { |
156 | data.m_uniqueID = flight->attribute("uniqueID" ).toLong(); |
157 | if (Node *airline = flight->firstChildOfType("airline" )) |
158 | data.m_airline = airline->text(); |
159 | if (Node *flight_id = flight->firstChildOfType("flight_id" )) |
160 | data.m_flightID = flight_id->text(); |
161 | if (Node *dom_int = flight->firstChildOfType("dom_int" )) |
162 | data.m_domesticOrInternational = dom_int->text(); // "D" = domestic, "I" = international |
163 | if (Node *schedule_time = flight->firstChildOfType("schedule_time" )) { |
164 | QDateTime scheduleTime = QDateTime::fromString(schedule_time->text(), Qt::ISODate); |
165 | scheduleTime.setTimeSpec(Qt::UTC); |
166 | data.m_scheduleTime = scheduleTime.toLocalTime(); |
167 | data.m_scheduleText = data.m_scheduleTime.toString("hhmm" ); |
168 | } |
169 | if (Node *arr_dep = flight->firstChildOfType("arr_dep" )) |
170 | data.m_arrivalOrDeparture = arr_dep->text(); // "D" = departure, "A" = arrival |
171 | if (Node *airport = flight->firstChildOfType("airport" )) { |
172 | data.m_airportCode = airport->text(); |
173 | data.m_airportName = m_airports ? m_airports->airportName(data.m_airportCode) : QString(); |
174 | data.m_roundtrip = (data.m_airportCode == airportCode); // if destination and origin are the same |
175 | } |
176 | if (Node *via_airport = flight->firstChildOfType("via_airport" )) { |
177 | data.m_viaAirportCodes = via_airport->text().split(','); |
178 | foreach(QString code, data.m_viaAirportCodes) |
179 | data.m_viaAirportNames.append(m_airports->airportName(code)); |
180 | if (!data.m_roundtrip && data.m_arrivalOrDeparture == "D" ) |
181 | data.m_viaAirportNames.append(data.m_airportName); |
182 | data.m_routeAirportNames = data.m_viaAirportNames.join(", " ); |
183 | } |
184 | if (Node *check_in = flight->firstChildOfType("check_in" )) |
185 | data.m_checkinArea = check_in->text(); // "A" "B" "C" "D" checking area |
186 | if (Node *gate = flight->firstChildOfType("gate" )) |
187 | data.m_gate = gate->text(); |
188 | if (Node *status = flight->firstChildOfType("status" )) { |
189 | data.m_statusCode = status->attribute("code" ); |
190 | data.m_statusText = m_statuses ? m_statuses->statusTextNorwegian(data.m_statusCode) : QString(); // ### support norwegian |
191 | QDateTime statusTime = QDateTime::fromString(status->attribute("time" ), Qt::ISODate); |
192 | statusTime.setTimeSpec(Qt::UTC); |
193 | data.m_statusText += statusTime.toLocalTime().toString(" hh:mm" ); |
194 | } |
195 | if (Node *belt_number = flight->firstChildOfType("belt_number" )) |
196 | data.m_beltNumber = belt_number->text(); |
197 | } |
198 | m_flights.append(data); |
199 | } |
200 | |