QGCParamWidget.cc 26 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
tstellanova's avatar
tstellanova committed
136 137 138 139
//    connect(this, SIGNAL(parameterChanged(int,QString,QVariant)),
//            mav, SLOT(setParameter(int,QString,QVariant)));
    connect(tree, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
            this, SLOT(parameterItemChanged(QTreeWidgetItem*,int)));
lm's avatar
lm committed
140

tstellanova's avatar
tstellanova committed
141 142
//    // New parameters from UAS
//    connect(uas, SIGNAL(parameterChanged(int,int,int,int,QString,QVariant)), this, SLOT(receivedParameterUpdate(int,int,int,int,QString,QVariant)));
143

tstellanova's avatar
tstellanova committed
144

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

tstellanova's avatar
tstellanova committed
149 150 151 152 153 154 155 156

    connect(paramDataModel, SIGNAL(parameterUpdated(int, QString , QVariant )),
            this, SLOT(handleParameterUpdate(int,QString,QVariant)));

    // Listen for param list reload finished
    connect(paramCommsMgr, SIGNAL(parameterListUpToDate()),
            this, SLOT(handleParameterListUpToDate()));

157
    // Get parameters
tstellanova's avatar
tstellanova committed
158
    if (uas) {
159
        requestAllParamsUpdate();
tstellanova's avatar
tstellanova committed
160
    }
pixhawk's avatar
pixhawk committed
161 162
}

tstellanova's avatar
tstellanova committed
163

164 165


166 167


lm's avatar
lm committed
168

tstellanova's avatar
tstellanova committed
169
void QGCParamWidget::addComponentItem( int compId, QString compName)
pixhawk's avatar
pixhawk committed
170
{
tstellanova's avatar
tstellanova committed
171
    if (componentItems->contains(compId)) {
pixhawk's avatar
pixhawk committed
172
        // Update existing
tstellanova's avatar
tstellanova committed
173
        componentItems->value(compId)->setData(0, Qt::DisplayRole, QString("%1 (#%2)").arg(compName).arg(compId));
174
        //components->value(component)->setData(1, Qt::DisplayRole, QString::number(component));
tstellanova's avatar
tstellanova committed
175
        componentItems->value(compId)->setFirstColumnSpanned(true);
176
    } else {
pixhawk's avatar
pixhawk committed
177
        // Add new
tstellanova's avatar
tstellanova committed
178
        QStringList list(QString("%1 (#%2)").arg(compName).arg(compId));
pixhawk's avatar
pixhawk committed
179
        QTreeWidgetItem* comp = new QTreeWidgetItem(list);
lm's avatar
lm committed
180
        comp->setFirstColumnSpanned(true);
tstellanova's avatar
tstellanova committed
181
        componentItems->insert(compId, comp);
pixhawk's avatar
pixhawk committed
182
        // Create grouping and update maps
tstellanova's avatar
tstellanova committed
183
        paramGroups.insert(compId, new QMap<QString, QTreeWidgetItem*>());
pixhawk's avatar
pixhawk committed
184 185 186
        tree->addTopLevelItem(comp);
        tree->update();
    }
187

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

pixhawk's avatar
pixhawk committed
191 192
}

tstellanova's avatar
tstellanova committed
193 194


lm's avatar
lm committed
195 196 197 198 199
/**
 * @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
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 335 336 337 338 339 340 341 342 343
//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
344
void QGCParamWidget::handleParameterUpdate(int componentId, const QString& paramName, QVariant value)
lm's avatar
lm committed
345
{
tstellanova's avatar
tstellanova committed
346 347
    updateParameterDisplay(componentId, paramName, value);
}
348

349

tstellanova's avatar
tstellanova committed
350
void QGCParamWidget::handleParameterListUpToDate()
tstellanova's avatar
tstellanova committed
351 352 353
{
    // Expand visual tree
    tree->expandItem(tree->topLevelItem(0));
lm's avatar
lm committed
354 355
}

356

tstellanova's avatar
tstellanova committed
357 358
void QGCParamWidget::updateParameterDisplay(int componentId, QString parameterName, QVariant value)
{
359

360 361 362
//    QString ptrStr;
//    ptrStr.sprintf("%8p", this);
//    qDebug() <<  "QGCParamWidget " << ptrStr << " got param" <<  parameterName;
363

364
    // Reference to item in tree
365
    QTreeWidgetItem* parameterItem = NULL;
pixhawk's avatar
pixhawk committed
366 367

    // Get component
368 369
    if (!componentItems->contains(componentId)) {
        QString componentName = tr("Component #%1").arg(componentId);
tstellanova's avatar
tstellanova committed
370
        addComponentItem(componentId, componentName);
pixhawk's avatar
pixhawk committed
371
    }
372

tstellanova's avatar
tstellanova committed
373 374 375
    //TODO this should be bubbling up from the model, not vice-versa, right?
//    // Replace value in data model
//    paramDataModel->handleParameterUpdate(componentId,parameterName,value);
376 377


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

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

tstellanova's avatar
tstellanova committed
413
        if (!found) {
414 415 416
            // Insert parameter into map
            QStringList plist;
            plist.append(parameterName);
417
            // CREATE PARAMETER ITEM
418
            parameterItem = new QTreeWidgetItem(plist);
419
            // CONFIGURE PARAMETER ITEM
tstellanova's avatar
tstellanova committed
420
            if (value.type() == QVariant::Char) {
421 422
                parameterItem->setData(1, Qt::DisplayRole, value.toUInt());
            }
tstellanova's avatar
tstellanova committed
423
            else {
424 425
                parameterItem->setData(1, Qt::DisplayRole, value);
            }
426 427

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

tstellanova's avatar
tstellanova committed
445
        if (!found) {
446 447 448
            // Insert parameter into map
            QStringList plist;
            plist.append(parameterName);
449
            // CREATE PARAMETER ITEM
450
            parameterItem = new QTreeWidgetItem(plist);
451
            // CONFIGURE PARAMETER ITEM
452
            parameterItem->setData(1, Qt::DisplayRole, value);
453

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

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

pixhawk's avatar
pixhawk committed
478 479
}

lm's avatar
lm committed
480

481

482
void QGCParamWidget::parameterItemChanged(QTreeWidgetItem* current, int column)
lm's avatar
lm committed
483
{
484
    if (current && column > 0) {
485
        QTreeWidgetItem* parent = current->parent();
486
        while (parent->parent() != NULL) {
487 488 489
            parent = parent->parent();
        }
        // Parent is now top-level component
490
        int componentId = componentItems->key(parent);
491

492 493 494 495 496 497 498 499 500
        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
501

502
        bool changed = paramDataModel->addPendingIfParameterChanged(componentId,key,value);
503

504 505 506 507 508 509
        // 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
510
            //paramDataModel->setOnboardParameterWithType(componentId,key,value);
511
        }
512

513 514 515
    }
}

516 517


518
void QGCParamWidget::saveParametersToFile()
519
{
520
    if (!mav) return;
521 522
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), "./parameters.txt", tr("Parameter File (*.txt)"));
    QFile file(fileName);
523
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
524 525 526
        return;
    }

527 528
    QTextStream outstream(&file);
    paramDataModel->writeOnboardParametersToStream(outstream,mav->getUASName());
529 530 531
    file.close();
}

532 533

void QGCParamWidget::loadParametersFromFile()
534
{
535
    if (!mav) return;
536 537 538 539 540 541
    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);
542
    paramDataModel->readUpdateParametersFromStream(in);
543
    file.close();
lm's avatar
lm committed
544 545
}

tstellanova's avatar
tstellanova committed
546
void QGCParamWidget::setParameterStatusMsg(const QString& msg)
547
{
tstellanova's avatar
tstellanova committed
548 549 550
    statusLabel->setText(msg);
}

551
void QGCParamWidget::requestAllParamsUpdate()
tstellanova's avatar
tstellanova committed
552 553 554
{
    if (!mav) {
        return;
555
    }
tstellanova's avatar
tstellanova committed
556 557 558 559 560

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

    requestParameterList();
561 562
}

lm's avatar
lm committed
563

tstellanova's avatar
tstellanova committed
564 565 566 567 568 569

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

573
/**
tstellanova's avatar
tstellanova committed
574 575
 * Write the current onboard parameters from RAM into
 * permanent storage, e.g. EEPROM or harddisk
576
 */
tstellanova's avatar
tstellanova committed
577
void QGCParamWidget::writeParameters()
578
{
tstellanova's avatar
tstellanova committed
579 580 581 582 583
    int changedParamCount = 0;

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

tstellanova's avatar
tstellanova committed
584
    for (i = changedValues.begin(); i != changedValues.end() , (0 == changedParamCount);  ++i) {
tstellanova's avatar
tstellanova committed
585
        // Iterate through the parameters of the component
tstellanova's avatar
tstellanova committed
586 587
        QMap<QString, QVariant>* compPending = i.value();
        changedParamCount += compPending->count();
tstellanova's avatar
tstellanova committed
588
    }
589

tstellanova's avatar
tstellanova committed
590
    if (changedParamCount > 0) {
tstellanova's avatar
tstellanova committed
591 592 593 594
        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
595 596
    else {
        paramCommsMgr->writeParamsToPersistentStorage();
tstellanova's avatar
tstellanova committed
597 598
    }
}
599

600 601 602 603 604
/**
 * @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
605 606
//void QGCParamWidget::setParameter(int component, QString parameterName, QVariant value)
//{
607

tstellanova's avatar
tstellanova committed
608 609 610
//    if (parameterName.isEmpty()) {
//        return;
//    }
611

tstellanova's avatar
tstellanova committed
612
//    double dblValue = value.toDouble();
613

tstellanova's avatar
tstellanova committed
614 615 616 617 618 619 620 621 622 623 624 625 626 627
//    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;
//    }
628

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

tstellanova's avatar
tstellanova committed
666 667 668 669 670 671
//    // 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
672

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

tstellanova's avatar
tstellanova committed
676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693
//    // 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
//}
694

695 696
void QGCParamWidget::readParameters()
{
697
    if (!mav) return;
698
    mav->readParametersFromStorage();
699 700
}

701 702 703
/**
 * Clear all data in the parameter widget
 */
pixhawk's avatar
pixhawk committed
704 705 706
void QGCParamWidget::clear()
{
    tree->clear();
707
    componentItems->clear();
pixhawk's avatar
pixhawk committed
708
}
tstellanova's avatar
tstellanova committed
709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725

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

}