QGCParamWidget.cc 26.1 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 158 159
    connect(paramCommsMgr, SIGNAL(parameterStatusMsgUpdated(QString,int)),
            this, SLOT(handleParamStatusMsgUpdate(QString , int )));

160
    // Get parameters
tstellanova's avatar
tstellanova committed
161
    if (uas) {
162
        requestAllParamsUpdate();
tstellanova's avatar
tstellanova committed
163
    }
pixhawk's avatar
pixhawk committed
164 165
}

tstellanova's avatar
tstellanova committed
166

167 168


169 170


lm's avatar
lm committed
171

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

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

pixhawk's avatar
pixhawk committed
194 195
}

tstellanova's avatar
tstellanova committed
196 197


lm's avatar
lm committed
198 199 200 201 202
/**
 * @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
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 344 345 346
//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
347
void QGCParamWidget::handleParameterUpdate(int componentId, const QString& paramName, QVariant value)
lm's avatar
lm committed
348
{
tstellanova's avatar
tstellanova committed
349 350
    updateParameterDisplay(componentId, paramName, value);
}
351

352

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

359

tstellanova's avatar
tstellanova committed
360 361
void QGCParamWidget::updateParameterDisplay(int componentId, QString parameterName, QVariant value)
{
362

363 364 365
//    QString ptrStr;
//    ptrStr.sprintf("%8p", this);
//    qDebug() <<  "QGCParamWidget " << ptrStr << " got param" <<  parameterName;
366

367
    // Reference to item in tree
368
    QTreeWidgetItem* parameterItem = NULL;
pixhawk's avatar
pixhawk committed
369 370

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

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


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

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

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

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

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

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

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

pixhawk's avatar
pixhawk committed
481 482
}

lm's avatar
lm committed
483

484

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

495 496 497 498 499 500 501 502 503
        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
504

505
        bool changed = paramDataModel->addPendingIfParameterChanged(componentId,key,value);
506

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

516 517 518
    }
}

519 520


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

530 531
    QTextStream outstream(&file);
    paramDataModel->writeOnboardParametersToStream(outstream,mav->getUASName());
532 533 534
    file.close();
}

535 536

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

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

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

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

    requestParameterList();
564 565
}

lm's avatar
lm committed
566

tstellanova's avatar
tstellanova committed
567 568 569 570 571 572

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

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

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

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

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

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

tstellanova's avatar
tstellanova committed
611 612 613
//    if (parameterName.isEmpty()) {
//        return;
//    }
614

tstellanova's avatar
tstellanova committed
615
//    double dblValue = value.toDouble();
616

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

tstellanova's avatar
tstellanova committed
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 665 666 667
//    //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
668

tstellanova's avatar
tstellanova committed
669 670 671 672 673 674
//    // 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
675

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

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

698 699
void QGCParamWidget::readParameters()
{
700
    if (!mav) return;
701
    mav->readParametersFromStorage();
702 703
}

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

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

}