2 ******************************************************************************
4 * @file flightdatamodel.cpp
5 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
6 * @addtogroup GCSPlugins GCS Plugins
8 * @addtogroup OPMapPlugin OpenPilot Map Plugin
10 * @brief The OpenPilot Map plugin
11 *****************************************************************************/
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 * You should have received a copy of the GNU General Public License along
24 * with this program; if not, write to the Free Software Foundation, Inc.,
25 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "flightdatamodel.h"
29 #include <QMessageBox>
30 #include <QDomDocument>
32 flightDataModel::flightDataModel(QObject
*parent
) : QAbstractTableModel(parent
)
35 int flightDataModel::rowCount(const QModelIndex
& /*parent*/) const
37 return dataStorage
.length();
40 int flightDataModel::columnCount(const QModelIndex
&parent
) const
42 if (parent
.isValid()) {
48 QVariant
flightDataModel::data(const QModelIndex
&index
, int role
) const
50 if (role
== Qt::DisplayRole
|| role
== Qt::EditRole
) {
51 int rowNumber
= index
.row();
52 int columnNumber
= index
.column();
53 if (rowNumber
> dataStorage
.length() - 1 || rowNumber
< 0) {
54 return QVariant::Invalid
;
56 pathPlanData
*myRow
= dataStorage
.at(rowNumber
);
57 QVariant ret
= getColumnByIndex(myRow
, columnNumber
);
61 else if (role == Qt::BackgroundRole) {
62 // WaypointActive::DataFields waypointActive = waypointActiveObj->getData();
64 if(index.row() == waypointActive.Index) {
65 return QBrush(Qt::lightGray);
67 return QVariant::Invalid;
70 return QVariant::Invalid
;
74 bool flightDataModel::setColumnByIndex(pathPlanData
*row
, const int index
, const QVariant value
)
80 row
->wpDescritption
= value
.toString();
84 row
->latPosition
= value
.toDouble();
88 row
->lngPosition
= value
.toDouble();
92 row
->disRelative
= value
.toDouble();
96 row
->beaRelative
= value
.toDouble();
99 case ALTITUDERELATIVE
:
100 row
->altitudeRelative
= value
.toFloat();
104 row
->isRelative
= value
.toBool();
108 row
->altitude
= value
.toDouble();
112 row
->velocity
= value
.toFloat();
116 row
->mode
= value
.toInt();
120 row
->mode_params
[0] = value
.toFloat();
124 row
->mode_params
[1] = value
.toFloat();
128 row
->mode_params
[2] = value
.toFloat();
132 row
->mode_params
[3] = value
.toFloat();
136 row
->condition
= value
.toInt();
139 case CONDITION_PARAMS0
:
140 row
->condition_params
[0] = value
.toFloat();
143 case CONDITION_PARAMS1
:
144 row
->condition_params
[1] = value
.toFloat();
147 case CONDITION_PARAMS2
:
148 row
->condition_params
[2] = value
.toFloat();
151 case CONDITION_PARAMS3
:
152 row
->condition_params
[3] = value
.toFloat();
156 row
->command
= value
.toInt();
159 case JUMPDESTINATION
:
160 row
->jumpdestination
= value
.toInt();
163 case ERRORDESTINATION
:
164 row
->errordestination
= value
.toInt();
168 row
->locked
= value
.toBool();
178 QVariant
flightDataModel::getColumnByIndex(const pathPlanData
*row
, const int index
) const
184 value
= row
->wpDescritption
;
187 value
= row
->latPosition
;
190 value
= row
->lngPosition
;
193 value
= row
->disRelative
;
196 value
= row
->beaRelative
;
198 case ALTITUDERELATIVE
:
199 value
= row
->altitudeRelative
;
202 value
= row
->isRelative
;
205 value
= row
->altitude
;
208 value
= row
->velocity
;
214 value
= row
->mode_params
[0];
217 value
= row
->mode_params
[1];
220 value
= row
->mode_params
[2];
223 value
= row
->mode_params
[3];
226 value
= row
->condition
;
228 case CONDITION_PARAMS0
:
229 value
= row
->condition_params
[0];
231 case CONDITION_PARAMS1
:
232 value
= row
->condition_params
[1];
234 case CONDITION_PARAMS2
:
235 value
= row
->condition_params
[2];
237 case CONDITION_PARAMS3
:
238 value
= row
->condition_params
[3];
241 value
= row
->command
;
243 case JUMPDESTINATION
:
244 value
= row
->jumpdestination
;
246 case ERRORDESTINATION
:
247 value
= row
->errordestination
;
256 QVariant
flightDataModel::headerData(int section
, Qt::Orientation orientation
, int role
) const
260 if (role
== Qt::DisplayRole
) {
261 if (orientation
== Qt::Vertical
) {
262 value
= QString::number(section
+ 1);
263 } else if (orientation
== Qt::Horizontal
) {
266 value
= QString("Description");
269 value
= QString("Latitude");
272 value
= QString("Longitude");
275 value
= QString("Distance to home");
278 value
= QString("Bearing from home");
280 case ALTITUDERELATIVE
:
281 value
= QString("Altitude above home");
284 value
= QString("Relative to home");
287 value
= QString("Altitude");
290 value
= QString("Velocity");
293 value
= QString("Mode");
296 value
= QString("Mode parameter 0");
299 value
= QString("Mode parameter 1");
302 value
= QString("Mode parameter 2");
305 value
= QString("Mode parameter 3");
308 value
= QString("Condition");
310 case CONDITION_PARAMS0
:
311 value
= QString("Condition parameter 0");
313 case CONDITION_PARAMS1
:
314 value
= QString("Condition parameter 1");
316 case CONDITION_PARAMS2
:
317 value
= QString("Condition parameter 2");
319 case CONDITION_PARAMS3
:
320 value
= QString("Condition parameter 3");
323 value
= QString("Command");
325 case JUMPDESTINATION
:
326 value
= QString("Jump Destination");
328 case ERRORDESTINATION
:
329 value
= QString("Error Destination");
332 value
= QString("Locked");
340 value
= QAbstractTableModel::headerData(section
, orientation
, role
);
345 bool flightDataModel::setData(const QModelIndex
&index
, const QVariant
&value
, int role
)
347 if (role
== Qt::EditRole
) {
348 int columnIndex
= index
.column();
349 int rowIndex
= index
.row();
350 if (rowIndex
> dataStorage
.length() - 1) {
353 pathPlanData
*myRow
= dataStorage
.at(rowIndex
);
354 setColumnByIndex(myRow
, columnIndex
, value
);
355 emit
dataChanged(index
, index
);
360 Qt::ItemFlags
flightDataModel::flags(const QModelIndex
& /*index*/) const
362 return Qt::ItemIsSelectable
| Qt::ItemIsEditable
| Qt::ItemIsEnabled
;
365 bool flightDataModel::insertRows(int row
, int count
, const QModelIndex
& /*parent*/)
369 beginInsertRows(QModelIndex(), row
, row
+ count
- 1);
370 for (int x
= 0; x
< count
; ++x
) {
371 data
= new pathPlanData
;
372 data
->latPosition
= 0;
373 data
->lngPosition
= 0;
374 data
->disRelative
= 0;
375 data
->beaRelative
= 0;
376 data
->altitudeRelative
= 0;
377 data
->isRelative
= true;
381 data
->mode_params
[0] = 0;
382 data
->mode_params
[1] = 0;
383 data
->mode_params
[2] = 0;
384 data
->mode_params
[3] = 0;
386 data
->condition_params
[0] = 0;
387 data
->condition_params
[1] = 0;
388 data
->condition_params
[2] = 0;
389 data
->condition_params
[3] = 0;
391 data
->jumpdestination
= 0;
392 data
->errordestination
= 0;
393 data
->locked
= false;
394 if (rowCount() > 0) {
395 data
->altitude
= this->data(this->index(rowCount() - 1, ALTITUDE
)).toDouble();
396 data
->altitudeRelative
= this->data(this->index(rowCount() - 1, ALTITUDERELATIVE
)).toDouble();
397 data
->isRelative
= this->data(this->index(rowCount() - 1, ISRELATIVE
)).toBool();
398 data
->velocity
= this->data(this->index(rowCount() - 1, VELOCITY
)).toFloat();
399 data
->mode
= this->data(this->index(rowCount() - 1, MODE
)).toInt();
400 data
->mode_params
[0] = this->data(this->index(rowCount() - 1, MODE_PARAMS0
)).toFloat();
401 data
->mode_params
[1] = this->data(this->index(rowCount() - 1, MODE_PARAMS1
)).toFloat();
402 data
->mode_params
[2] = this->data(this->index(rowCount() - 1, MODE_PARAMS2
)).toFloat();
403 data
->mode_params
[3] = this->data(this->index(rowCount() - 1, MODE_PARAMS3
)).toFloat();
404 data
->condition
= this->data(this->index(rowCount() - 1, CONDITION
)).toInt();
405 data
->condition_params
[0] = this->data(this->index(rowCount() - 1, CONDITION_PARAMS0
)).toFloat();
406 data
->condition_params
[1] = this->data(this->index(rowCount() - 1, CONDITION_PARAMS1
)).toFloat();
407 data
->condition_params
[2] = this->data(this->index(rowCount() - 1, CONDITION_PARAMS2
)).toFloat();
408 data
->condition_params
[3] = this->data(this->index(rowCount() - 1, CONDITION_PARAMS3
)).toFloat();
409 data
->command
= this->data(this->index(rowCount() - 1, COMMAND
)).toInt();
410 data
->errordestination
= this->data(this->index(rowCount() - 1, ERRORDESTINATION
)).toInt();
412 dataStorage
.insert(row
, data
);
418 bool flightDataModel::removeRows(int row
, int count
, const QModelIndex
& /*parent*/)
420 if (row
< 0 || count
<= 0) {
423 beginRemoveRows(QModelIndex(), row
, row
+ count
- 1);
424 for (int x
= 0; x
< count
; ++x
) {
425 delete dataStorage
.at(row
);
426 dataStorage
.removeAt(row
);
432 bool flightDataModel::writeToFile(QString fileName
)
434 QFile
file(fileName
);
436 if (!file
.open(QIODevice::WriteOnly
)) {
437 QMessageBox::information(NULL
, tr("Unable to open file"), file
.errorString());
440 QDataStream
out(&file
);
441 QDomDocument
doc("PathPlan");
442 QDomElement root
= doc
.createElement("waypoints");
443 doc
.appendChild(root
);
445 foreach(pathPlanData
* obj
, dataStorage
) {
446 QDomElement waypoint
= doc
.createElement("waypoint");
448 waypoint
.setAttribute("number", dataStorage
.indexOf(obj
));
449 root
.appendChild(waypoint
);
450 QDomElement field
= doc
.createElement("field");
451 field
.setAttribute("value", obj
->wpDescritption
);
452 field
.setAttribute("name", "description");
453 waypoint
.appendChild(field
);
455 field
= doc
.createElement("field");
456 field
.setAttribute("value", obj
->latPosition
);
457 field
.setAttribute("name", "latitude");
458 waypoint
.appendChild(field
);
460 field
= doc
.createElement("field");
461 field
.setAttribute("value", obj
->lngPosition
);
462 field
.setAttribute("name", "longitude");
463 waypoint
.appendChild(field
);
465 field
= doc
.createElement("field");
466 field
.setAttribute("value", obj
->disRelative
);
467 field
.setAttribute("name", "distance_to_home");
468 waypoint
.appendChild(field
);
470 field
= doc
.createElement("field");
471 field
.setAttribute("value", obj
->beaRelative
);
472 field
.setAttribute("name", "bearing_from_home");
473 waypoint
.appendChild(field
);
475 field
= doc
.createElement("field");
476 field
.setAttribute("value", obj
->altitudeRelative
);
477 field
.setAttribute("name", "altitude_above_home");
478 waypoint
.appendChild(field
);
480 field
= doc
.createElement("field");
481 field
.setAttribute("value", obj
->isRelative
);
482 field
.setAttribute("name", "is_relative_to_home");
483 waypoint
.appendChild(field
);
485 field
= doc
.createElement("field");
486 field
.setAttribute("value", obj
->altitude
);
487 field
.setAttribute("name", "altitude");
488 waypoint
.appendChild(field
);
490 field
= doc
.createElement("field");
491 field
.setAttribute("value", obj
->velocity
);
492 field
.setAttribute("name", "velocity");
493 waypoint
.appendChild(field
);
495 field
= doc
.createElement("field");
496 field
.setAttribute("value", obj
->mode
);
497 field
.setAttribute("name", "mode");
498 waypoint
.appendChild(field
);
500 field
= doc
.createElement("field");
501 field
.setAttribute("value", obj
->mode_params
[0]);
502 field
.setAttribute("name", "mode_param0");
503 waypoint
.appendChild(field
);
505 field
= doc
.createElement("field");
506 field
.setAttribute("value", obj
->mode_params
[1]);
507 field
.setAttribute("name", "mode_param1");
508 waypoint
.appendChild(field
);
510 field
= doc
.createElement("field");
511 field
.setAttribute("value", obj
->mode_params
[2]);
512 field
.setAttribute("name", "mode_param2");
513 waypoint
.appendChild(field
);
515 field
= doc
.createElement("field");
516 field
.setAttribute("value", obj
->mode_params
[3]);
517 field
.setAttribute("name", "mode_param3");
518 waypoint
.appendChild(field
);
520 field
= doc
.createElement("field");
521 field
.setAttribute("value", obj
->condition
);
522 field
.setAttribute("name", "condition");
523 waypoint
.appendChild(field
);
525 field
= doc
.createElement("field");
526 field
.setAttribute("value", obj
->condition_params
[0]);
527 field
.setAttribute("name", "condition_param0");
528 waypoint
.appendChild(field
);
530 field
= doc
.createElement("field");
531 field
.setAttribute("value", obj
->condition_params
[1]);
532 field
.setAttribute("name", "condition_param1");
533 waypoint
.appendChild(field
);
535 field
= doc
.createElement("field");
536 field
.setAttribute("value", obj
->condition_params
[2]);
537 field
.setAttribute("name", "condition_param2");
538 waypoint
.appendChild(field
);
540 field
= doc
.createElement("field");
541 field
.setAttribute("value", obj
->condition_params
[3]);
542 field
.setAttribute("name", "condition_param3");
543 waypoint
.appendChild(field
);
545 field
= doc
.createElement("field");
546 field
.setAttribute("value", obj
->command
);
547 field
.setAttribute("name", "command");
548 waypoint
.appendChild(field
);
550 field
= doc
.createElement("field");
551 field
.setAttribute("value", obj
->jumpdestination
);
552 field
.setAttribute("name", "jumpdestination");
553 waypoint
.appendChild(field
);
555 field
= doc
.createElement("field");
556 field
.setAttribute("value", obj
->errordestination
);
557 field
.setAttribute("name", "errordestination");
558 waypoint
.appendChild(field
);
560 field
= doc
.createElement("field");
561 field
.setAttribute("value", obj
->locked
);
562 field
.setAttribute("name", "is_locked");
563 waypoint
.appendChild(field
);
565 file
.write(doc
.toString().toLatin1());
570 void flightDataModel::readFromFile(QString fileName
)
572 // TODO warning message
573 removeRows(0, rowCount());
574 QFile
file(fileName
);
575 file
.open(QIODevice::ReadOnly
);
576 QDomDocument
doc("PathPlan");
577 QByteArray array
= file
.readAll();
579 if (!doc
.setContent(array
, &error
)) {
581 msgBox
.setText(tr("File Parsing Failed."));
582 msgBox
.setInformativeText(QString(tr("This file is not a correct XML file:%0")).arg(error
));
583 msgBox
.setStandardButtons(QMessageBox::Ok
);
589 QDomElement root
= doc
.documentElement();
591 if (root
.isNull() || (root
.tagName() != "waypoints")) {
593 msgBox
.setText(tr("Wrong file contents"));
594 msgBox
.setInformativeText(tr("This file does not contain correct UAVSettings"));
595 msgBox
.setStandardButtons(QMessageBox::Ok
);
600 pathPlanData
*data
= NULL
;
601 QDomNode node
= root
.firstChild();
602 while (!node
.isNull()) {
603 QDomElement e
= node
.toElement();
604 if (e
.tagName() == "waypoint") {
605 QDomNode fieldNode
= e
.firstChild();
606 data
= new pathPlanData
;
607 while (!fieldNode
.isNull()) {
608 QDomElement field
= fieldNode
.toElement();
609 if (field
.tagName() == "field") {
610 QString name
= field
.attribute("name");
611 QString value
= field
.attribute("value");
612 if (name
== "altitude") {
613 data
->altitude
= value
.toDouble();
614 } else if (name
== "description") {
615 data
->wpDescritption
= value
;
616 } else if (name
== "latitude") {
617 data
->latPosition
= value
.toDouble();
618 } else if (name
== "longitude") {
619 data
->lngPosition
= value
.toDouble();
620 } else if (name
== "distance_to_home") {
621 data
->disRelative
= value
.toDouble();
622 } else if (name
== "bearing_from_home") {
623 data
->beaRelative
= value
.toDouble();
624 } else if (name
== "altitude_above_home") {
625 data
->altitudeRelative
= value
.toFloat();
626 } else if (name
== "is_relative_to_home") {
627 data
->isRelative
= value
.toInt();
628 } else if (name
== "altitude") {
629 data
->altitude
= value
.toDouble();
630 } else if (name
== "velocity") {
631 data
->velocity
= value
.toFloat();
632 } else if (name
== "mode") {
633 data
->mode
= value
.toInt();
634 } else if (name
== "mode_param0") {
635 data
->mode_params
[0] = value
.toFloat();
636 } else if (name
== "mode_param1") {
637 data
->mode_params
[1] = value
.toFloat();
638 } else if (name
== "mode_param2") {
639 data
->mode_params
[2] = value
.toFloat();
640 } else if (name
== "mode_param3") {
641 data
->mode_params
[3] = value
.toFloat();
642 } else if (name
== "condition") {
643 data
->condition
= value
.toDouble();
644 } else if (name
== "condition_param0") {
645 data
->condition_params
[0] = value
.toFloat();
646 } else if (name
== "condition_param1") {
647 data
->condition_params
[1] = value
.toFloat();
648 } else if (name
== "condition_param2") {
649 data
->condition_params
[2] = value
.toFloat();
650 } else if (name
== "condition_param3") {
651 data
->condition_params
[3] = value
.toFloat();
652 } else if (name
== "command") {
653 data
->command
= value
.toInt();
654 } else if (name
== "jumpdestination") {
655 data
->jumpdestination
= value
.toInt();
656 } else if (name
== "errordestination") {
657 data
->errordestination
= value
.toInt();
658 } else if (name
== "is_locked") {
659 data
->locked
= value
.toInt();
662 fieldNode
= fieldNode
.nextSibling();
664 beginInsertRows(QModelIndex(), dataStorage
.length(), dataStorage
.length());
665 dataStorage
.append(data
);
668 node
= node
.nextSibling();