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 334
//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));
//    }
//}


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

341

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

348

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

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

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

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

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


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

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

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

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

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

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

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

pixhawk's avatar
pixhawk committed
470 471
}

lm's avatar
lm committed
472

473

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

484 485 486 487 488 489 490 491 492
        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
493

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

496 497 498 499 500 501
        // 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
502
            //paramDataModel->setOnboardParameterWithType(componentId,key,value);
503
        }
504

505 506 507
    }
}

508 509


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

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

524 525

void QGCParamWidget::loadParametersFromFile()
526
{
527
    if (!mav) return;
528 529 530 531 532 533
    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);
534
    paramDataModel->readUpdateParametersFromStream(in);
535
    file.close();
lm's avatar
lm committed
536 537
}

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

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

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

    requestParameterList();
553 554
}

lm's avatar
lm committed
555

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

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

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

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

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

tstellanova's avatar
tstellanova committed
582
    if (changedParamCount > 0) {
tstellanova's avatar
tstellanova committed
583 584 585 586
        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
587 588
    else {
        paramCommsMgr->writeParamsToPersistentStorage();
tstellanova's avatar
tstellanova committed
589 590
    }
}
591

592 593 594 595 596
/**
 * @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
597 598
//void QGCParamWidget::setParameter(int component, QString parameterName, QVariant value)
//{
599

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

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

tstellanova's avatar
tstellanova committed
606 607 608 609 610 611 612 613 614 615 616 617 618 619
//    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;
//    }
620

tstellanova's avatar
tstellanova committed
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 656
//    //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
657

tstellanova's avatar
tstellanova committed
658 659 660 661 662 663
//    // 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
664

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

tstellanova's avatar
tstellanova committed
668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685
//    // 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
//}
686

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

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

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);

}