QGCParamWidget.cc 25.7 KB
Newer Older
1 2 3 4
/*=====================================================================

QGroundControl Open Source Ground Control Station

pixhawk's avatar
pixhawk committed
5
(c) 2009, 2010 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

This file is part of the QGROUNDCONTROL project

    QGROUNDCONTROL is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    QGROUNDCONTROL is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.

======================================================================*/
/**
 * @file
 *   @brief Implementation of class QGCParamWidget
 *   @author Lorenz Meier <mail@qgroundcontrol.org>
 */
Lorenz Meier's avatar
Lorenz Meier committed
28 29
#include <cmath>
#include <float.h>
tstellanova's avatar
tstellanova committed
30 31
#include <QApplication>
#include <QDebug>
32
#include <QFile>
tstellanova's avatar
tstellanova committed
33 34 35
#include <QFileDialog>
#include <QGridLayout>

36
#include <QList>
37
#include <QMessageBox>
tstellanova's avatar
tstellanova committed
38 39 40
#include <QPushButton>
#include <QSettings>
#include <QTime>
pixhawk's avatar
pixhawk committed
41

Lorenz Meier's avatar
Lorenz Meier committed
42
#include "MainWindow.h"
43
#include "QGC.h"
tstellanova's avatar
tstellanova committed
44 45 46
#include "QGCParamWidget.h"
#include "UASInterface.h"
#include "UASParameterCommsMgr.h"
pixhawk's avatar
pixhawk committed
47

48 49 50 51
/**
 * @param uas MAV to set the parameters on
 * @param parent Parent widget
 */
pixhawk's avatar
pixhawk committed
52
QGCParamWidget::QGCParamWidget(UASInterface* uas, QWidget *parent) :
53
    QGCUASParamManager(uas, parent),
54
    componentItems(new QMap<int, QTreeWidgetItem*>())
pixhawk's avatar
pixhawk committed
55
{
lm's avatar
lm committed
56

pixhawk's avatar
pixhawk committed
57 58
    // Create tree widget
    tree = new QTreeWidget(this);
lm's avatar
lm committed
59
    statusLabel = new QLabel();
lm's avatar
lm committed
60
    statusLabel->setAutoFillBackground(true);
61
    tree->setColumnWidth(70, 30);
pixhawk's avatar
pixhawk committed
62 63

    // Set tree widget as widget onto this component
64
    QGridLayout* horizontalLayout;
pixhawk's avatar
pixhawk committed
65
    //form->setAutoFillBackground(false);
66
    horizontalLayout = new QGridLayout(this);
67 68
    horizontalLayout->setHorizontalSpacing(6);
    horizontalLayout->setVerticalSpacing(6);
pixhawk's avatar
pixhawk committed
69
    horizontalLayout->setMargin(0);
70 71
    horizontalLayout->setSizeConstraint(QLayout::SetMinimumSize);
    //horizontalLayout->setSizeConstraint( QLayout::SetFixedSize );
pixhawk's avatar
pixhawk committed
72

lm's avatar
lm committed
73
    // Parameter tree
74
    horizontalLayout->addWidget(tree, 0, 0, 1, 3);
lm's avatar
lm committed
75 76

    // Status line
lm's avatar
lm committed
77
    statusLabel->setText(tr("Click refresh to download parameters"));
lm's avatar
lm committed
78 79 80 81
    horizontalLayout->addWidget(statusLabel, 1, 0, 1, 3);


    // BUTTONS
Jessica's avatar
Jessica committed
82
    QPushButton* refreshButton = new QPushButton(tr("Get"));
83 84
    refreshButton->setToolTip(tr("Load parameters currently in non-permanent memory of aircraft."));
    refreshButton->setWhatsThis(tr("Load parameters currently in non-permanent memory of aircraft."));
85
    connect(refreshButton, SIGNAL(clicked()), this, SLOT(requestAllParamsUpdate()));
lm's avatar
lm committed
86
    horizontalLayout->addWidget(refreshButton, 2, 0);
87

Jessica's avatar
Jessica committed
88
    QPushButton* setButton = new QPushButton(tr("Set"));
89 90
    setButton->setToolTip(tr("Set current parameters in non-permanent onboard memory"));
    setButton->setWhatsThis(tr("Set current parameters in non-permanent onboard memory"));
91
    connect(setButton, SIGNAL(clicked()), this, SLOT(setParameters()));
lm's avatar
lm committed
92
    horizontalLayout->addWidget(setButton, 2, 1);
93

94
    QPushButton* writeButton = new QPushButton(tr("Write (ROM)"));
95 96
    writeButton->setToolTip(tr("Copy current parameters in non-permanent memory of the aircraft to permanent memory. Transmit your parameters first to write these."));
    writeButton->setWhatsThis(tr("Copy current parameters in non-permanent memory of the aircraft to permanent memory. Transmit your parameters first to write these."));
97
    connect(writeButton, SIGNAL(clicked()), this, SLOT(writeParameters()));
lm's avatar
lm committed
98
    horizontalLayout->addWidget(writeButton, 2, 2);
99

100
    QPushButton* loadFileButton = new QPushButton(tr("Load File"));
101 102
    loadFileButton->setToolTip(tr("Load parameters from a file on this computer in the view. To write them to the aircraft, use transmit after loading them."));
    loadFileButton->setWhatsThis(tr("Load parameters from a file on this computer in the view. To write them to the aircraft, use transmit after loading them."));
103
    connect(loadFileButton, SIGNAL(clicked()), this, SLOT(loadParametersFromFile()));
lm's avatar
lm committed
104
    horizontalLayout->addWidget(loadFileButton, 3, 0);
105 106

    QPushButton* saveFileButton = new QPushButton(tr("Save File"));
107 108
    saveFileButton->setToolTip(tr("Save parameters in this view to a file on this computer."));
    saveFileButton->setWhatsThis(tr("Save parameters in this view to a file on this computer."));
109
    connect(saveFileButton, SIGNAL(clicked()), this, SLOT(saveParametersToFile()));
lm's avatar
lm committed
110 111 112 113 114 115 116
    horizontalLayout->addWidget(saveFileButton, 3, 1);

    QPushButton* readButton = new QPushButton(tr("Read (ROM)"));
    readButton->setToolTip(tr("Copy parameters from permanent memory to non-permanent current memory of aircraft. DOES NOT update the parameters in this view, click refresh after copying them to get them."));
    readButton->setWhatsThis(tr("Copy parameters from permanent memory to non-permanent current memory of aircraft. DOES NOT update the parameters in this view, click refresh after copying them to get them."));
    connect(readButton, SIGNAL(clicked()), this, SLOT(readParameters()));
    horizontalLayout->addWidget(readButton, 3, 2);
117

118 119 120 121 122 123
    // Set correct vertical scaling
    horizontalLayout->setRowStretch(0, 100);
    horizontalLayout->setRowStretch(1, 10);
    horizontalLayout->setRowStretch(2, 10);
    horizontalLayout->setRowStretch(3, 10);

124
    // Set layout
pixhawk's avatar
pixhawk committed
125 126 127 128 129 130 131 132
    this->setLayout(horizontalLayout);

    // Set header
    QStringList headerItems;
    headerItems.append("Parameter");
    headerItems.append("Value");
    tree->setHeaderLabels(headerItems);
    tree->setColumnCount(2);
133
    tree->setExpandsOnDoubleClick(true);
134 135

    // Connect signals/slots
136
    connect(this, SIGNAL(parameterChanged(int,QString,QVariant)), mav, SLOT(setParameter(int,QString,QVariant)));
137
    connect(tree, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, SLOT(parameterItemChanged(QTreeWidgetItem*,int)));
lm's avatar
lm committed
138

139
    // New parameters from UAS
140
    connect(uas, SIGNAL(parameterChanged(int,int,int,int,QString,QVariant)), this, SLOT(receivedParameterUpdate(int,int,int,int,QString,QVariant)));
141

tstellanova's avatar
tstellanova committed
142

tstellanova's avatar
tstellanova committed
143
//    connect(&retransmissionTimer, SIGNAL(timeout()), this, SLOT(retransmissionGuardTick()));
tstellanova's avatar
tstellanova committed
144 145 146
//    connect(this, SIGNAL(requestParameter(int,QString)), uas, SLOT(requestParameter(int,QString)));
//    connect(this, SIGNAL(requestParameter(int,int)), uas, SLOT(requestParameter(int,int)));

147
    // Get parameters
tstellanova's avatar
tstellanova committed
148
    if (uas) {
149
        requestAllParamsUpdate();
tstellanova's avatar
tstellanova committed
150
    }
pixhawk's avatar
pixhawk committed
151 152
}

tstellanova's avatar
tstellanova committed
153

154 155


156 157


lm's avatar
lm committed
158

tstellanova's avatar
tstellanova committed
159
void QGCParamWidget::addComponentItem( int compId, QString compName)
pixhawk's avatar
pixhawk committed
160
{
tstellanova's avatar
tstellanova committed
161
    if (componentItems->contains(compId)) {
pixhawk's avatar
pixhawk committed
162
        // Update existing
tstellanova's avatar
tstellanova committed
163
        componentItems->value(compId)->setData(0, Qt::DisplayRole, QString("%1 (#%2)").arg(compName).arg(compId));
164
        //components->value(component)->setData(1, Qt::DisplayRole, QString::number(component));
tstellanova's avatar
tstellanova committed
165
        componentItems->value(compId)->setFirstColumnSpanned(true);
166
    } else {
pixhawk's avatar
pixhawk committed
167
        // Add new
tstellanova's avatar
tstellanova committed
168
        QStringList list(QString("%1 (#%2)").arg(compName).arg(compId));
pixhawk's avatar
pixhawk committed
169
        QTreeWidgetItem* comp = new QTreeWidgetItem(list);
lm's avatar
lm committed
170
        comp->setFirstColumnSpanned(true);
tstellanova's avatar
tstellanova committed
171
        componentItems->insert(compId, comp);
pixhawk's avatar
pixhawk committed
172
        // Create grouping and update maps
tstellanova's avatar
tstellanova committed
173
        paramGroups.insert(compId, new QMap<QString, QTreeWidgetItem*>());
pixhawk's avatar
pixhawk committed
174 175 176
        tree->addTopLevelItem(comp);
        tree->update();
    }
177

tstellanova's avatar
tstellanova committed
178 179
    //TODO it seems unlikely that the UI would know about a component before the data model...
    paramDataModel->addComponent(compId);
180

pixhawk's avatar
pixhawk committed
181 182
}

tstellanova's avatar
tstellanova committed
183 184


lm's avatar
lm committed
185 186 187 188 189
/**
 * @param uas System which has the component
 * @param component id of the component
 * @param parameterName human friendly name of the parameter
 */
tstellanova's avatar
tstellanova committed
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333
//void QGCParamWidget::receivedParameterUpdate(int uas, int component, int paramCount, int paramId, QString parameterName, QVariant value)
//{

//    updateParameterDisplay(component, parameterName, value);

//    // Missing packets list has to be instantiated for all components
//    if (!transmissionMissingPackets.contains(component)) {
//        transmissionMissingPackets.insert(component, new QList<int>());
//    }

//    // List mode is different from single parameter transfers
//    if (transmissionListMode) {
//        // Only accept the list size once on the first packet from
//        // each component
//        if (!transmissionListSizeKnown.contains(component))
//        {
//            // Mark list size as known
//            transmissionListSizeKnown.insert(component, true);

//            // Mark all parameters as missing
//            for (int i = 0; i < paramCount; ++i)
//            {
//                if (!transmissionMissingPackets.value(component)->contains(i))
//                {
//                    transmissionMissingPackets.value(component)->append(i);
//                }
//            }

//            // There is only one transmission timeout for all components
//            // since components do not manage their transmission,
//            // the longest timeout is safe for all components.
//            quint64 thisTransmissionTimeout = QGC::groundTimeMilliseconds() + ((paramCount)*retransmissionTimeout);
//            if (thisTransmissionTimeout > transmissionTimeout)
//            {
//                transmissionTimeout = thisTransmissionTimeout;
//            }
//        }

//        // Start retransmission guard
//        // or reset timer
//        paramCommsMgr->setRetransmissionGuardEnabled(true); //TODO
//    }

//    // Mark this parameter as received in read list
//    int index = transmissionMissingPackets.value(component)->indexOf(paramId);
//    // If the MAV sent the parameter without request, it wont be in missing list
//    if (index != -1) transmissionMissingPackets.value(component)->removeAt(index);

//    bool justWritten = false;
//    bool writeMismatch = false;
//    //bool lastWritten = false;
//    // Mark this parameter as received in write ACK list
//    QMap<QString, QVariant>* map = transmissionMissingWriteAckPackets.value(component);
//    if (map && map->contains(parameterName))
//    {
//        justWritten = true;
//        QVariant newval = map->value(parameterName);
//        if (map->value(parameterName) != value)
//        {
//            writeMismatch = true;
//        }
//        map->remove(parameterName);
//    }

//    int missCount = 0;
//    foreach (int key, transmissionMissingPackets.keys())
//    {
//        missCount +=  transmissionMissingPackets.value(key)->count();
//    }

//    int missWriteCount = 0;
//    foreach (int key, transmissionMissingWriteAckPackets.keys())
//    {
//        missWriteCount += transmissionMissingWriteAckPackets.value(key)->count();
//    }

//    if (justWritten && !writeMismatch && missWriteCount == 0)
//    {
//        // Just wrote one and count went to 0 - this was the last missing write parameter
//        statusLabel->setText(tr("SUCCESS: WROTE ALL PARAMETERS"));
//        QPalette pal = statusLabel->palette();
//        pal.setColor(backgroundRole(), QGC::colorGreen);
//        statusLabel->setPalette(pal);
//    } else if (justWritten && !writeMismatch)
//    {
//        statusLabel->setText(tr("SUCCESS: Wrote %2 (#%1/%4): %3").arg(paramId+1).arg(parameterName).arg(value.toDouble()).arg(paramCount));
//        QPalette pal = statusLabel->palette();
//        pal.setColor(backgroundRole(), QGC::colorGreen);
//        statusLabel->setPalette(pal);
//    } else if (justWritten && writeMismatch)
//    {
//        // Mismatch, tell user
//        QPalette pal = statusLabel->palette();
//        pal.setColor(backgroundRole(), QGC::colorRed);
//        statusLabel->setPalette(pal);
//        statusLabel->setText(tr("FAILURE: Wrote %1: sent %2 != onboard %3").arg(parameterName).arg(map->value(parameterName).toDouble()).arg(value.toDouble()));
//    }
//    else
//    {
//        if (missCount > 0)
//        {
//            QPalette pal = statusLabel->palette();
//            pal.setColor(backgroundRole(), QGC::colorOrange);
//            statusLabel->setPalette(pal);
//        }
//        else
//        {
//            QPalette pal = statusLabel->palette();
//            pal.setColor(backgroundRole(), QGC::colorGreen);
//            statusLabel->setPalette(pal);
//        }
//        QString val = QString("%1").arg(value.toFloat(), 5, 'f', 1, QChar(' '));
//        //statusLabel->setText(tr("OK: %1 %2 #%3/%4, %5 miss").arg(parameterName).arg(val).arg(paramId+1).arg(paramCount).arg(missCount));
//        if (missCount == 0)
//        {
//            // Transmission done
//            QTime time = QTime::currentTime();
//            QString timeString = time.toString();
//            statusLabel->setText(tr("All received. (updated at %1)").arg(timeString));
//        }
//        else
//        {
//            // Transmission in progress
//            statusLabel->setText(tr("OK: %1 %2 (%3/%4)").arg(parameterName).arg(val).arg(paramCount-missCount).arg(paramCount));
//        }
//    }

//    // Check if last parameter was received
//    if (missCount == 0 && missWriteCount == 0)
//    {
//        this->transmissionActive = false;
//        this->transmissionListMode = false;
//        transmissionListSizeKnown.clear();
//        foreach (int key, transmissionMissingPackets.keys())
//        {
//            transmissionMissingPackets.value(key)->clear();
//        }

//        // Expand visual tree
//        tree->expandItem(tree->topLevelItem(0));
//    }
//}


tstellanova's avatar
tstellanova committed
334
void QGCParamWidget::handleParameterUpdate(int componentId, int paramId, const QString& paramName, QVariant value)
lm's avatar
lm committed
335
{
tstellanova's avatar
tstellanova committed
336 337 338
    Q_UNUSED(paramId);
    updateParameterDisplay(componentId, paramName, value);
}
339

340

tstellanova's avatar
tstellanova committed
341
void QGCParamWidget::handleParameterListUpToDate()
tstellanova's avatar
tstellanova committed
342 343 344
{
    // Expand visual tree
    tree->expandItem(tree->topLevelItem(0));
lm's avatar
lm committed
345 346
}

347

tstellanova's avatar
tstellanova committed
348 349
void QGCParamWidget::updateParameterDisplay(int componentId, QString parameterName, QVariant value)
{
350

351 352 353
//    QString ptrStr;
//    ptrStr.sprintf("%8p", this);
//    qDebug() <<  "QGCParamWidget " << ptrStr << " got param" <<  parameterName;
354

355
    // Reference to item in tree
356
    QTreeWidgetItem* parameterItem = NULL;
pixhawk's avatar
pixhawk committed
357 358

    // Get component
359 360
    if (!componentItems->contains(componentId)) {
        QString componentName = tr("Component #%1").arg(componentId);
tstellanova's avatar
tstellanova committed
361
        addComponentItem(componentId, componentName);
pixhawk's avatar
pixhawk committed
362
    }
363

tstellanova's avatar
tstellanova committed
364 365 366
    //TODO this should be bubbling up from the model, not vice-versa, right?
//    // Replace value in data model
//    paramDataModel->handleParameterUpdate(componentId,parameterName,value);
367 368


pixhawk's avatar
pixhawk committed
369 370
    QString splitToken = "_";
    // Check if auto-grouping can work
lm's avatar
lm committed
371 372
    if (parameterName.contains(splitToken))
    {
pixhawk's avatar
pixhawk committed
373
        QString parent = parameterName.section(splitToken, 0, 0, QString::SectionSkipEmpty);
374
        QMap<QString, QTreeWidgetItem*>* compParamGroups = paramGroups.value(componentId);
375 376
        if (!compParamGroups->contains(parent))
        {
pixhawk's avatar
pixhawk committed
377 378 379 380 381
            // Insert group item
            QStringList glist;
            glist.append(parent);
            QTreeWidgetItem* item = new QTreeWidgetItem(glist);
            compParamGroups->insert(parent, item);
382
            componentItems->value(componentId)->addChild(item);
383
        }
384 385 386 387

        // Append child to group
        bool found = false;
        QTreeWidgetItem* parentItem = compParamGroups->value(parent);
388
        for (int i = 0; i < parentItem->childCount(); i++) {
389 390
            QTreeWidgetItem* child = parentItem->child(i);
            QString key = child->data(0, Qt::DisplayRole).toString();
tstellanova's avatar
tstellanova committed
391
            if (key == parameterName)  {
392 393
                //qDebug() << "UPDATED CHILD";
                parameterItem = child;
tstellanova's avatar
tstellanova committed
394
                if (value.type() == QVariant::Char) {
395 396
                    parameterItem->setData(1, Qt::DisplayRole, value.toUInt());
                }
tstellanova's avatar
tstellanova committed
397
                else {
398 399
                    parameterItem->setData(1, Qt::DisplayRole, value);
                }
400 401 402 403
                found = true;
            }
        }

tstellanova's avatar
tstellanova committed
404
        if (!found) {
405 406 407
            // Insert parameter into map
            QStringList plist;
            plist.append(parameterName);
408
            // CREATE PARAMETER ITEM
409
            parameterItem = new QTreeWidgetItem(plist);
410
            // CONFIGURE PARAMETER ITEM
tstellanova's avatar
tstellanova committed
411
            if (value.type() == QVariant::Char) {
412 413
                parameterItem->setData(1, Qt::DisplayRole, value.toUInt());
            }
tstellanova's avatar
tstellanova committed
414
            else {
415 416
                parameterItem->setData(1, Qt::DisplayRole, value);
            }
417 418

            compParamGroups->value(parent)->addChild(parameterItem);
lm's avatar
lm committed
419
            parameterItem->setFlags(parameterItem->flags() | Qt::ItemIsEditable);
420
        }
lm's avatar
lm committed
421
    }
tstellanova's avatar
tstellanova committed
422
    else  {
pixhawk's avatar
pixhawk committed
423
        bool found = false;
424
        QTreeWidgetItem* parent = componentItems->value(componentId);
tstellanova's avatar
tstellanova committed
425
        for (int i = 0; i < parent->childCount(); i++) {
pixhawk's avatar
pixhawk committed
426 427
            QTreeWidgetItem* child = parent->child(i);
            QString key = child->data(0, Qt::DisplayRole).toString();
tstellanova's avatar
tstellanova committed
428
            if (key == parameterName) {
pixhawk's avatar
pixhawk committed
429
                //qDebug() << "UPDATED CHILD";
430 431
                parameterItem = child;
                parameterItem->setData(1, Qt::DisplayRole, value);
pixhawk's avatar
pixhawk committed
432 433 434 435
                found = true;
            }
        }

tstellanova's avatar
tstellanova committed
436
        if (!found) {
437 438 439
            // Insert parameter into map
            QStringList plist;
            plist.append(parameterName);
440
            // CREATE PARAMETER ITEM
441
            parameterItem = new QTreeWidgetItem(plist);
442
            // CONFIGURE PARAMETER ITEM
443
            parameterItem->setData(1, Qt::DisplayRole, value);
444

445
            componentItems->value(componentId)->addChild(parameterItem);
lm's avatar
lm committed
446
            parameterItem->setFlags(parameterItem->flags() | Qt::ItemIsEditable);
pixhawk's avatar
pixhawk committed
447
        }
448
        //tree->expandAll();
449
    }
450
    // Reset background color
451
    parameterItem->setBackground(0, Qt::NoBrush);
452
    parameterItem->setBackground(1, Qt::NoBrush);
lm's avatar
lm committed
453
    // Add tooltip
454
    QString paramDesc = paramDataModel->getParamDescription(parameterName);
455
    QString tooltipFormat;
456
    if (paramDataModel->isParamDefaultKnown(parameterName)) {
457
        tooltipFormat = tr("Default: %1, %2");
458 459
        double paramDefValue = paramDataModel->getParamDefault(parameterName);
        tooltipFormat = tooltipFormat.arg(paramDefValue).arg(paramDesc);
460
    }
461 462
    else {
        tooltipFormat = paramDesc;
463 464 465
    }
    parameterItem->setToolTip(0, tooltipFormat);
    parameterItem->setToolTip(1, tooltipFormat);
lm's avatar
lm committed
466

tstellanova's avatar
tstellanova committed
467
    //paramDataModel->handleParameterUpdate(componentId,parameterName,value);
468

pixhawk's avatar
pixhawk committed
469 470
}

lm's avatar
lm committed
471

472

473
void QGCParamWidget::parameterItemChanged(QTreeWidgetItem* current, int column)
lm's avatar
lm committed
474
{
475
    if (current && column > 0) {
476
        QTreeWidgetItem* parent = current->parent();
477
        while (parent->parent() != NULL) {
478 479 480
            parent = parent->parent();
        }
        // Parent is now top-level component
481
        int componentId = componentItems->key(parent);
482

483 484 485 486 487 488 489 490 491
        QString key = current->data(0, Qt::DisplayRole).toString();
        QVariant value = current->data(1, Qt::DisplayRole);
        // Set parameter on changed list to be transmitted to MAV
        QPalette pal = statusLabel->palette();
        pal.setColor(backgroundRole(), QGC::colorOrange);
        statusLabel->setPalette(pal);
        statusLabel->setText(tr("Transmit pend. %1:%2: %3").arg(componentId).arg(key).arg(value.toFloat(), 5, 'f', 1, QChar(' ')));
        //qDebug() << "PARAM CHANGED: COMP:" << key << "KEY:" << str << "VALUE:" << value;
        // Changed values list
492

493
        bool changed = paramDataModel->addPendingIfParameterChanged(componentId,key,value);
494

495 496 497 498 499 500
        // If the value was numerically changed, display it differently
        if (changed) {
            current->setBackground(0, QBrush(QColor(QGC::colorOrange)));
            current->setBackground(1, QBrush(QColor(QGC::colorOrange)));

            //TODO this seems incorrect-- we're pre-updating the onboard value before we've received confirmation
501
            //paramDataModel->setOnboardParameterWithType(componentId,key,value);
502
        }
503

504 505 506
    }
}

507 508


509
void QGCParamWidget::saveParametersToFile()
510
{
511
    if (!mav) return;
512 513
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), "./parameters.txt", tr("Parameter File (*.txt)"));
    QFile file(fileName);
514
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
515 516 517
        return;
    }

518 519
    QTextStream outstream(&file);
    paramDataModel->writeOnboardParametersToStream(outstream,mav->getUASName());
520 521 522
    file.close();
}

523 524

void QGCParamWidget::loadParametersFromFile()
525
{
526
    if (!mav) return;
527 528 529 530 531 532
    QString fileName = QFileDialog::getOpenFileName(this, tr("Load File"), ".", tr("Parameter file (*.txt)"));
    QFile file(fileName);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
        return;

    QTextStream in(&file);
533
    paramDataModel->readUpdateParametersFromStream(in);
534
    file.close();
lm's avatar
lm committed
535 536
}

tstellanova's avatar
tstellanova committed
537
void QGCParamWidget::setParameterStatusMsg(const QString& msg)
538
{
tstellanova's avatar
tstellanova committed
539 540 541
    statusLabel->setText(msg);
}

542
void QGCParamWidget::requestAllParamsUpdate()
tstellanova's avatar
tstellanova committed
543 544 545
{
    if (!mav) {
        return;
546
    }
tstellanova's avatar
tstellanova committed
547 548 549 550 551

    // Clear view and request param list
    clear();

    requestParameterList();
552 553
}

lm's avatar
lm committed
554

tstellanova's avatar
tstellanova committed
555 556 557 558 559 560

/**
 * Set all parameter in the parameter tree on the MAV
 */
void QGCParamWidget::setParameters()
{
tstellanova's avatar
tstellanova committed
561
    paramCommsMgr->sendPendingParameters();
562 563
}

564
/**
tstellanova's avatar
tstellanova committed
565 566
 * Write the current onboard parameters from RAM into
 * permanent storage, e.g. EEPROM or harddisk
567
 */
tstellanova's avatar
tstellanova committed
568
void QGCParamWidget::writeParameters()
569
{
tstellanova's avatar
tstellanova committed
570 571 572 573 574
    int changedParamCount = 0;

    QMap<int, QMap<QString, QVariant>*>::iterator i;
    QMap<int, QMap<QString, QVariant>*> changedValues = paramDataModel->getPendingParameters();

tstellanova's avatar
tstellanova committed
575
    for (i = changedValues.begin(); i != changedValues.end() , (0 == changedParamCount);  ++i) {
tstellanova's avatar
tstellanova committed
576
        // Iterate through the parameters of the component
tstellanova's avatar
tstellanova committed
577 578
        QMap<QString, QVariant>* compPending = i.value();
        changedParamCount += compPending->count();
tstellanova's avatar
tstellanova committed
579
    }
580

tstellanova's avatar
tstellanova committed
581
    if (changedParamCount > 0) {
tstellanova's avatar
tstellanova committed
582 583 584 585
        QMessageBox msgBox;
        msgBox.setText(tr("There are locally changed parameters. Please transmit them first (<TRANSMIT>) or update them with the onboard values (<REFRESH>) before storing onboard from RAM to ROM."));
        msgBox.exec();
    }
tstellanova's avatar
tstellanova committed
586 587
    else {
        paramCommsMgr->writeParamsToPersistentStorage();
tstellanova's avatar
tstellanova committed
588 589
    }
}
590

591 592 593 594 595
/**
 * @param component the subsystem which has the parameter
 * @param parameterName name of the parameter, as delivered by the system
 * @param value value of the parameter
 */
tstellanova's avatar
tstellanova committed
596 597
//void QGCParamWidget::setParameter(int component, QString parameterName, QVariant value)
//{
598

tstellanova's avatar
tstellanova committed
599 600 601
//    if (parameterName.isEmpty()) {
//        return;
//    }
602

tstellanova's avatar
tstellanova committed
603
//    double dblValue = value.toDouble();
604

tstellanova's avatar
tstellanova committed
605 606 607 608 609 610 611 612 613 614 615 616 617 618
//    if (paramDataModel->isValueLessThanParamMin(parameterName,dblValue)) {
//        statusLabel->setText(tr("REJ. %1, %2 < min").arg(parameterName).arg(dblValue));
//        return;
//    }
//    if (paramDataModel->isValueGreaterThanParamMax(parameterName,dblValue)) {
//        statusLabel->setText(tr("REJ. %1, %2 > max").arg(parameterName).arg(dblValue));
//        return;
//    }
//    QVariant onboardVal;
//    paramDataModel->getOnboardParameterValue(component,parameterName,onboardVal);
//    if (onboardVal == value) {
//        statusLabel->setText(tr("REJ. %1 already %2").arg(parameterName).arg(dblValue));
//        return;
//    }
619

tstellanova's avatar
tstellanova committed
620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655
//    //int paramType = (int)onboardParameters.value(component)->value(parameterName).type();
//    int paramType = (int)value.type();
//    switch (paramType)
//    {
//    case QVariant::Char:
//    {
//        QVariant fixedValue(QChar((unsigned char)value.toInt()));
//        emit parameterChanged(component, parameterName, fixedValue);
//        //qDebug() << "PARAM WIDGET SENT:" << fixedValue;
//    }
//        break;
//    case QVariant::Int:
//    {
//        QVariant fixedValue(value.toInt());
//        emit parameterChanged(component, parameterName, fixedValue);
//        //qDebug() << "PARAM WIDGET SENT:" << fixedValue;
//    }
//        break;
//    case QVariant::UInt:
//    {
//        QVariant fixedValue(value.toUInt());
//        emit parameterChanged(component, parameterName, fixedValue);
//        //qDebug() << "PARAM WIDGET SENT:" << fixedValue;
//    }
//        break;
//    case QMetaType::Float:
//    {
//        QVariant fixedValue(value.toFloat());
//        emit parameterChanged(component, parameterName, fixedValue);
//        //qDebug() << "PARAM WIDGET SENT:" << fixedValue;
//    }
//        break;
//    default:
//        qCritical() << "ABORTED PARAM SEND, NO VALID QVARIANT TYPE";
//        return;
//    }
lm's avatar
lm committed
656

tstellanova's avatar
tstellanova committed
657 658 659 660 661 662
//    // Wait for parameter to be written back
//    // mark it therefore as missing
//    if (!transmissionMissingWriteAckPackets.contains(component))
//    {
//        transmissionMissingWriteAckPackets.insert(component, new QMap<QString, QVariant>());
//    }
lm's avatar
lm committed
663

tstellanova's avatar
tstellanova committed
664 665
//    // Insert it in missing write ACK list
//    transmissionMissingWriteAckPackets.value(component)->insert(parameterName, value);
Lorenz Meier's avatar
Lorenz Meier committed
666

tstellanova's avatar
tstellanova committed
667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684
//    // Set timeouts
//    if (transmissionActive)
//    {
//        transmissionTimeout += rewriteTimeout;
//    }
//    else
//    {
//        quint64 newTransmissionTimeout = QGC::groundTimeMilliseconds() + rewriteTimeout;
//        if (newTransmissionTimeout > transmissionTimeout)
//        {
//            transmissionTimeout = newTransmissionTimeout;
//        }
//        transmissionActive = true;
//    }

//    // Enable guard / reset timeouts
//    paramCommsMgr->setRetransmissionGuardEnabled(true); //TODO
//}
685

686 687
void QGCParamWidget::readParameters()
{
688
    if (!mav) return;
689
    mav->readParametersFromStorage();
690 691
}

692 693 694
/**
 * Clear all data in the parameter widget
 */
pixhawk's avatar
pixhawk committed
695 696 697
void QGCParamWidget::clear()
{
    tree->clear();
698
    componentItems->clear();
pixhawk's avatar
pixhawk committed
699
}
tstellanova's avatar
tstellanova committed
700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716

void QGCParamWidget::handleParamStatusMsgUpdate(QString msg, int level)
{
    QColor bgColor = QGC::colorGreen;
    if ((int)UASParameterCommsMgr::ParamCommsStatusLevel_Warning == level) {
        bgColor = QGC::colorOrange;
    }
    else if ((int)UASParameterCommsMgr::ParamCommsStatusLevel_Error == level) {
        bgColor =  QGC::colorRed;
    }

    QPalette pal = statusLabel->palette();
    pal.setColor(backgroundRole(), bgColor);
    statusLabel->setPalette(pal);
    statusLabel->setText(msg);

}