Skip to content
Snippets Groups Projects
QGCParamWidget.cc 26.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • /*=====================================================================
    
    QGroundControl Open Source Ground Control Station
    
    
    pixhawk's avatar
    pixhawk committed
    (c) 2009, 2010 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
    
    
    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
    #include <cmath>
    #include <float.h>
    
    tstellanova's avatar
    tstellanova committed
    #include <QApplication>
    #include <QDebug>
    
    #include <QFile>
    
    tstellanova's avatar
    tstellanova committed
    #include <QFileDialog>
    #include <QGridLayout>
    
    
    #include <QMessageBox>
    
    tstellanova's avatar
    tstellanova committed
    #include <QPushButton>
    #include <QSettings>
    #include <QTime>
    
    pixhawk's avatar
    pixhawk committed
    
    
    Lorenz Meier's avatar
    Lorenz Meier committed
    #include "MainWindow.h"
    
    #include "QGC.h"
    
    tstellanova's avatar
    tstellanova committed
    #include "QGCParamWidget.h"
    #include "UASInterface.h"
    #include "UASParameterCommsMgr.h"
    
    pixhawk's avatar
    pixhawk committed
    
    
    /**
     * @param uas MAV to set the parameters on
     * @param parent Parent widget
     */
    
    pixhawk's avatar
    pixhawk committed
    QGCParamWidget::QGCParamWidget(UASInterface* uas, QWidget *parent) :
    
        QGCUASParamManager(uas, parent),
    
        componentItems(new QMap<int, QTreeWidgetItem*>())
    
    pixhawk's avatar
    pixhawk committed
    {
    
    lm's avatar
    lm committed
    
    
    pixhawk's avatar
    pixhawk committed
        // Create tree widget
        tree = new QTreeWidget(this);
    
    lm's avatar
    lm committed
        statusLabel = new QLabel();
    
    lm's avatar
    lm committed
        statusLabel->setAutoFillBackground(true);
    
        tree->setColumnWidth(70, 30);
    
    pixhawk's avatar
    pixhawk committed
    
        // Set tree widget as widget onto this component
    
    pixhawk's avatar
    pixhawk committed
        //form->setAutoFillBackground(false);
    
        horizontalLayout = new QGridLayout(this);
    
        horizontalLayout->setHorizontalSpacing(6);
        horizontalLayout->setVerticalSpacing(6);
    
    pixhawk's avatar
    pixhawk committed
        horizontalLayout->setMargin(0);
    
        horizontalLayout->setSizeConstraint(QLayout::SetMinimumSize);
        //horizontalLayout->setSizeConstraint( QLayout::SetFixedSize );
    
    pixhawk's avatar
    pixhawk committed
    
    
    lm's avatar
    lm committed
        // Parameter tree
    
        horizontalLayout->addWidget(tree, 0, 0, 1, 3);
    
    lm's avatar
    lm committed
    
        // Status line
    
    lm's avatar
    lm committed
        statusLabel->setText(tr("Click refresh to download parameters"));
    
    lm's avatar
    lm committed
        horizontalLayout->addWidget(statusLabel, 1, 0, 1, 3);
    
    
        // BUTTONS
    
    Jessica's avatar
    Jessica committed
        QPushButton* refreshButton = new QPushButton(tr("Get"));
    
    lm's avatar
    lm committed
        refreshButton->setToolTip(tr("Load parameters currently in non-permanent memory of aircraft."));
        refreshButton->setWhatsThis(tr("Load parameters currently in non-permanent memory of aircraft."));
    
        connect(refreshButton, SIGNAL(clicked()), this, SLOT(requestAllParamsUpdate()));
    
    lm's avatar
    lm committed
        horizontalLayout->addWidget(refreshButton, 2, 0);
    
    Jessica's avatar
    Jessica committed
        QPushButton* setButton = new QPushButton(tr("Set"));
    
    lm's avatar
    lm committed
        setButton->setToolTip(tr("Set current parameters in non-permanent onboard memory"));
        setButton->setWhatsThis(tr("Set current parameters in non-permanent onboard memory"));
    
        connect(setButton, SIGNAL(clicked()), this, SLOT(setParameters()));
    
    lm's avatar
    lm committed
        horizontalLayout->addWidget(setButton, 2, 1);
    
        QPushButton* writeButton = new QPushButton(tr("Write (ROM)"));
    
    lm's avatar
    lm committed
        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."));
    
        connect(writeButton, SIGNAL(clicked()), this, SLOT(writeParameters()));
    
    lm's avatar
    lm committed
        horizontalLayout->addWidget(writeButton, 2, 2);
    
        QPushButton* loadFileButton = new QPushButton(tr("Load File"));
    
    lm's avatar
    lm committed
        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."));
    
        connect(loadFileButton, SIGNAL(clicked()), this, SLOT(loadParametersFromFile()));
    
    lm's avatar
    lm committed
        horizontalLayout->addWidget(loadFileButton, 3, 0);
    
    
        QPushButton* saveFileButton = new QPushButton(tr("Save File"));
    
    lm's avatar
    lm committed
        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."));
    
        connect(saveFileButton, SIGNAL(clicked()), this, SLOT(saveParametersToFile()));
    
    lm's avatar
    lm committed
        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);
    
        // Set correct vertical scaling
        horizontalLayout->setRowStretch(0, 100);
        horizontalLayout->setRowStretch(1, 10);
        horizontalLayout->setRowStretch(2, 10);
        horizontalLayout->setRowStretch(3, 10);
    
    
    pixhawk's avatar
    pixhawk committed
        this->setLayout(horizontalLayout);
    
        // Set header
        QStringList headerItems;
        headerItems.append("Parameter");
        headerItems.append("Value");
        tree->setHeaderLabels(headerItems);
        tree->setColumnCount(2);
    
        tree->setExpandsOnDoubleClick(true);
    
    tstellanova's avatar
    tstellanova committed
    //    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
    
    
    tstellanova's avatar
    tstellanova committed
    //    // New parameters from UAS
    //    connect(uas, SIGNAL(parameterChanged(int,int,int,int,QString,QVariant)), this, SLOT(receivedParameterUpdate(int,int,int,int,QString,QVariant)));
    
    tstellanova's avatar
    tstellanova committed
    //    connect(&retransmissionTimer, SIGNAL(timeout()), this, SLOT(retransmissionGuardTick()));
    
    tstellanova's avatar
    tstellanova committed
    //    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
    
        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()));
    
    
        connect(paramCommsMgr, SIGNAL(parameterStatusMsgUpdated(QString,int)),
                this, SLOT(handleParamStatusMsgUpdate(QString , int )));
    
    
    tstellanova's avatar
    tstellanova committed
        if (uas) {
    
            requestAllParamsUpdate();
    
    tstellanova's avatar
    tstellanova committed
        }
    
    lm's avatar
    lm committed
    
    
    tstellanova's avatar
    tstellanova committed
    void QGCParamWidget::addComponentItem( int compId, QString compName)
    
    pixhawk's avatar
    pixhawk committed
    {
    
    tstellanova's avatar
    tstellanova committed
        if (componentItems->contains(compId)) {
    
    pixhawk's avatar
    pixhawk committed
            // Update existing
    
    tstellanova's avatar
    tstellanova committed
            componentItems->value(compId)->setData(0, Qt::DisplayRole, QString("%1 (#%2)").arg(compName).arg(compId));
    
            //components->value(component)->setData(1, Qt::DisplayRole, QString::number(component));
    
    tstellanova's avatar
    tstellanova committed
            componentItems->value(compId)->setFirstColumnSpanned(true);
    
    pixhawk's avatar
    pixhawk committed
            // Add new
    
    tstellanova's avatar
    tstellanova committed
            QStringList list(QString("%1 (#%2)").arg(compName).arg(compId));
    
    pixhawk's avatar
    pixhawk committed
            QTreeWidgetItem* comp = new QTreeWidgetItem(list);
    
    lm's avatar
    lm committed
            comp->setFirstColumnSpanned(true);
    
    tstellanova's avatar
    tstellanova committed
            componentItems->insert(compId, comp);
    
    pixhawk's avatar
    pixhawk committed
            // Create grouping and update maps
    
    tstellanova's avatar
    tstellanova committed
            paramGroups.insert(compId, new QMap<QString, QTreeWidgetItem*>());
    
    pixhawk's avatar
    pixhawk committed
            tree->addTopLevelItem(comp);
            tree->update();
        }
    
    tstellanova's avatar
    tstellanova committed
        //TODO it seems unlikely that the UI would know about a component before the data model...
        paramDataModel->addComponent(compId);
    
    lm's avatar
    lm committed
    /**
     * @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
    //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
    void QGCParamWidget::handleParameterUpdate(int componentId, const QString& paramName, QVariant value)
    
    lm's avatar
    lm committed
    {
    
    tstellanova's avatar
    tstellanova committed
        updateParameterDisplay(componentId, paramName, value);
    }
    
    tstellanova's avatar
    tstellanova committed
    void QGCParamWidget::handleParameterListUpToDate()
    
    tstellanova's avatar
    tstellanova committed
    {
        // Expand visual tree
        tree->expandItem(tree->topLevelItem(0));
    
    lm's avatar
    lm committed
    }
    
    
    tstellanova's avatar
    tstellanova committed
    void QGCParamWidget::updateParameterDisplay(int componentId, QString parameterName, QVariant value)
    {
    
    //    QString ptrStr;
    //    ptrStr.sprintf("%8p", this);
    //    qDebug() <<  "QGCParamWidget " << ptrStr << " got param" <<  parameterName;
    
        // Reference to item in tree
    
        QTreeWidgetItem* parameterItem = NULL;
    
    pixhawk's avatar
    pixhawk committed
    
        // Get component
    
        if (!componentItems->contains(componentId)) {
            QString componentName = tr("Component #%1").arg(componentId);
    
    tstellanova's avatar
    tstellanova committed
            addComponentItem(componentId, componentName);
    
    pixhawk's avatar
    pixhawk committed
        }
    
    tstellanova's avatar
    tstellanova committed
        //TODO this should be bubbling up from the model, not vice-versa, right?
    //    // Replace value in data model
    //    paramDataModel->handleParameterUpdate(componentId,parameterName,value);
    
    pixhawk's avatar
    pixhawk committed
        QString splitToken = "_";
        // Check if auto-grouping can work
    
    lm's avatar
    lm committed
        if (parameterName.contains(splitToken))
        {
    
    pixhawk's avatar
    pixhawk committed
            QString parent = parameterName.section(splitToken, 0, 0, QString::SectionSkipEmpty);
    
            QMap<QString, QTreeWidgetItem*>* compParamGroups = paramGroups.value(componentId);
    
            if (!compParamGroups->contains(parent))
            {
    
    pixhawk's avatar
    pixhawk committed
                // Insert group item
                QStringList glist;
                glist.append(parent);
                QTreeWidgetItem* item = new QTreeWidgetItem(glist);
                compParamGroups->insert(parent, item);
    
                componentItems->value(componentId)->addChild(item);
    
    
            // Append child to group
            bool found = false;
            QTreeWidgetItem* parentItem = compParamGroups->value(parent);
    
            for (int i = 0; i < parentItem->childCount(); i++) {
    
                QTreeWidgetItem* child = parentItem->child(i);
                QString key = child->data(0, Qt::DisplayRole).toString();
    
    tstellanova's avatar
    tstellanova committed
                if (key == parameterName)  {
    
                    //qDebug() << "UPDATED CHILD";
                    parameterItem = child;
    
    tstellanova's avatar
    tstellanova committed
                    if (value.type() == QVariant::Char) {
    
                        parameterItem->setData(1, Qt::DisplayRole, value.toUInt());
                    }
    
    tstellanova's avatar
    tstellanova committed
                    else {
    
                        parameterItem->setData(1, Qt::DisplayRole, value);
                    }
    
    tstellanova's avatar
    tstellanova committed
            if (!found) {
    
                // Insert parameter into map
                QStringList plist;
                plist.append(parameterName);
    
                // CREATE PARAMETER ITEM
    
                parameterItem = new QTreeWidgetItem(plist);
    
                // CONFIGURE PARAMETER ITEM
    
    tstellanova's avatar
    tstellanova committed
                if (value.type() == QVariant::Char) {
    
                    parameterItem->setData(1, Qt::DisplayRole, value.toUInt());
                }
    
    tstellanova's avatar
    tstellanova committed
                else {
    
                    parameterItem->setData(1, Qt::DisplayRole, value);
                }
    
    
                compParamGroups->value(parent)->addChild(parameterItem);
    
    lm's avatar
    lm committed
                parameterItem->setFlags(parameterItem->flags() | Qt::ItemIsEditable);
    
    lm's avatar
    lm committed
        }
    
    tstellanova's avatar
    tstellanova committed
        else  {
    
    pixhawk's avatar
    pixhawk committed
            bool found = false;
    
            QTreeWidgetItem* parent = componentItems->value(componentId);
    
    tstellanova's avatar
    tstellanova committed
            for (int i = 0; i < parent->childCount(); i++) {
    
    pixhawk's avatar
    pixhawk committed
                QTreeWidgetItem* child = parent->child(i);
                QString key = child->data(0, Qt::DisplayRole).toString();
    
    tstellanova's avatar
    tstellanova committed
                if (key == parameterName) {
    
    pixhawk's avatar
    pixhawk committed
                    //qDebug() << "UPDATED CHILD";
    
                    parameterItem = child;
                    parameterItem->setData(1, Qt::DisplayRole, value);
    
    pixhawk's avatar
    pixhawk committed
                    found = true;
                }
            }
    
    
    tstellanova's avatar
    tstellanova committed
            if (!found) {
    
                // Insert parameter into map
                QStringList plist;
                plist.append(parameterName);
    
                // CREATE PARAMETER ITEM
    
                parameterItem = new QTreeWidgetItem(plist);
    
                // CONFIGURE PARAMETER ITEM
    
                parameterItem->setData(1, Qt::DisplayRole, value);
    
                componentItems->value(componentId)->addChild(parameterItem);
    
    lm's avatar
    lm committed
                parameterItem->setFlags(parameterItem->flags() | Qt::ItemIsEditable);
    
    pixhawk's avatar
    pixhawk committed
            }
    
            //tree->expandAll();
    
        // Reset background color
    
        parameterItem->setBackground(1, Qt::NoBrush);
    
    lm's avatar
    lm committed
        // Add tooltip
    
        QString paramDesc = paramDataModel->getParamDescription(parameterName);
    
        QString tooltipFormat;
    
        if (paramDataModel->isParamDefaultKnown(parameterName)) {
    
            tooltipFormat = tr("Default: %1, %2");
    
            double paramDefValue = paramDataModel->getParamDefault(parameterName);
            tooltipFormat = tooltipFormat.arg(paramDefValue).arg(paramDesc);
    
        else {
            tooltipFormat = paramDesc;
    
        }
        parameterItem->setToolTip(0, tooltipFormat);
        parameterItem->setToolTip(1, tooltipFormat);
    
    lm's avatar
    lm committed
    
    
    tstellanova's avatar
    tstellanova committed
        //paramDataModel->handleParameterUpdate(componentId,parameterName,value);
    
    lm's avatar
    lm committed
    
    
    void QGCParamWidget::parameterItemChanged(QTreeWidgetItem* current, int column)
    
    lm's avatar
    lm committed
    {
    
        if (current && column > 0) {
    
            QTreeWidgetItem* parent = current->parent();
    
            while (parent->parent() != NULL) {
    
                parent = parent->parent();
            }
            // Parent is now top-level component
    
            int componentId = componentItems->key(parent);
    
            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
    
            bool changed = paramDataModel->addPendingIfParameterChanged(componentId,key,value);
    
            // 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
    
                //paramDataModel->setOnboardParameterWithType(componentId,key,value);
    
    void QGCParamWidget::saveParametersToFile()
    
        if (!mav) return;
    
        QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), "./parameters.txt", tr("Parameter File (*.txt)"));
        QFile file(fileName);
    
        if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
    
        QTextStream outstream(&file);
        paramDataModel->writeOnboardParametersToStream(outstream,mav->getUASName());
    
    
    void QGCParamWidget::loadParametersFromFile()
    
        if (!mav) return;
    
        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);
    
        paramDataModel->readUpdateParametersFromStream(in);
    
    lm's avatar
    lm committed
    }
    
    
    tstellanova's avatar
    tstellanova committed
    void QGCParamWidget::setParameterStatusMsg(const QString& msg)
    
    tstellanova's avatar
    tstellanova committed
        statusLabel->setText(msg);
    }
    
    
    void QGCParamWidget::requestAllParamsUpdate()
    
    tstellanova's avatar
    tstellanova committed
    {
        if (!mav) {
            return;
    
    tstellanova's avatar
    tstellanova committed
    
        // Clear view and request param list
        clear();
    
        requestParameterList();
    
    lm's avatar
    lm committed
    
    
    tstellanova's avatar
    tstellanova committed
    
    /**
     * Set all parameter in the parameter tree on the MAV
     */
    void QGCParamWidget::setParameters()
    {
    
    tstellanova's avatar
    tstellanova committed
        paramCommsMgr->sendPendingParameters();
    
    tstellanova's avatar
    tstellanova committed
     * Write the current onboard parameters from RAM into
     * permanent storage, e.g. EEPROM or harddisk
    
    tstellanova's avatar
    tstellanova committed
    void QGCParamWidget::writeParameters()
    
    tstellanova's avatar
    tstellanova committed
        int changedParamCount = 0;
    
        QMap<int, QMap<QString, QVariant>*>::iterator i;
        QMap<int, QMap<QString, QVariant>*> changedValues = paramDataModel->getPendingParameters();
    
    
    tstellanova's avatar
    tstellanova committed
        for (i = changedValues.begin(); i != changedValues.end() , (0 == changedParamCount);  ++i) {
    
    tstellanova's avatar
    tstellanova committed
            // Iterate through the parameters of the component
    
    tstellanova's avatar
    tstellanova committed
            QMap<QString, QVariant>* compPending = i.value();
            changedParamCount += compPending->count();
    
    tstellanova's avatar
    tstellanova committed
        }
    
    tstellanova's avatar
    tstellanova committed
        if (changedParamCount > 0) {
    
    tstellanova's avatar
    tstellanova committed
            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
        else {
            paramCommsMgr->writeParamsToPersistentStorage();
    
    /**
     * @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
    //void QGCParamWidget::setParameter(int component, QString parameterName, QVariant value)
    //{
    
    tstellanova's avatar
    tstellanova committed
    //    if (parameterName.isEmpty()) {
    //        return;
    //    }
    
    tstellanova's avatar
    tstellanova committed
    //    double dblValue = value.toDouble();
    
    tstellanova's avatar
    tstellanova committed
    //    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;
    //    }
    
    tstellanova's avatar
    tstellanova committed
    //    //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
    
    
    tstellanova's avatar
    tstellanova committed
    //    // 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
    
    
    tstellanova's avatar
    tstellanova committed
    //    // Insert it in missing write ACK list
    //    transmissionMissingWriteAckPackets.value(component)->insert(parameterName, value);
    
    Lorenz Meier's avatar
    Lorenz Meier committed
    
    
    tstellanova's avatar
    tstellanova committed
    //    // 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
    //}
    
    void QGCParamWidget::readParameters()
    {
    
        if (!mav) return;
    
        mav->readParametersFromStorage();
    
    /**
     * Clear all data in the parameter widget
     */
    
    pixhawk's avatar
    pixhawk committed
    void QGCParamWidget::clear()
    {
        tree->clear();
    
        componentItems->clear();
    
    pixhawk's avatar
    pixhawk committed
    }
    
    tstellanova's avatar
    tstellanova committed
    
    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);
    
    }