diff --git a/libs/mavlink/include/mavlink/v1.0 b/libs/mavlink/include/mavlink/v1.0 index 7d0aa0205ef8bd13bf855b21d3ebe054dc9109ef..42f1a37397335b3c4c96b0a41c73d85e80d54a60 160000 --- a/libs/mavlink/include/mavlink/v1.0 +++ b/libs/mavlink/include/mavlink/v1.0 @@ -1 +1 @@ -Subproject commit 7d0aa0205ef8bd13bf855b21d3ebe054dc9109ef +Subproject commit 42f1a37397335b3c4c96b0a41c73d85e80d54a60 diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index 26d0dab76cfda77610c0ab2f90ce49e69438d144..cb4e270280bb11e9cda3724cba96d7f6ae467f5c 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -166,10 +166,10 @@ WindowsBuild { } # -# By default warnings as errors are turned off. Even so, in order for a pull request -# to be accepted you must compile cleanly with warnings as errors turned on the default -# set of OS builds. See http://www.qgroundcontrol.org/dev/contribute for more details. -# You can use the WarningsAsErrorsOn CONFIG switch to turn warnings as errors on for your +# By default warnings as errors are turned off. Even so, in order for a pull request +# to be accepted you must compile cleanly with warnings as errors turned on the default +# set of OS builds. See http://www.qgroundcontrol.org/dev/contribute for more details. +# You can use the WarningsAsErrorsOn CONFIG switch to turn warnings as errors on for your # own builds. # @@ -239,7 +239,7 @@ RESOURCES += qgroundcontrol.qrc TRANSLATIONS += \ es-MX.ts \ en-US.ts - + DEPENDPATH += \ . \ plugins @@ -343,6 +343,7 @@ FORMS += \ src/ui/px4_configuration/PX4FirmwareUpgrade.ui \ src/ui/QGCUASFileView.ui \ src/QGCQmlWidgetHolder.ui \ + src/ui/QGCMapRCToParamDialog.ui HEADERS += \ src/MG.h \ @@ -495,6 +496,8 @@ HEADERS += \ src/QGCQuickWidget.h \ src/QGCPalette.h \ src/QGCQmlWidgetHolder.h \ + src/ui/QGCParamTreeWidget.h \ + src/ui/QGCMapRCToParamDialog.h SOURCES += \ src/main.cc \ @@ -636,13 +639,15 @@ SOURCES += \ src/QGCQuickWidget.cc \ src/QGCPalette.cc \ src/QGCQmlWidgetHolder.cpp \ + src/ui/QGCParamTreeWidget.cpp \ + src/ui/QGCMapRCToParamDialog.cpp # # Unit Test specific configuration goes here # # We have to special case Windows debug_and_release builds because you can't have files -# which are only in the debug variant [QTBUG-40351]. So in this case we include unit tests -# even in the release variant. If you want a Windows release build with no unit tests run +# which are only in the debug variant [QTBUG-40351]. So in this case we include unit tests +# even in the release variant. If you want a Windows release build with no unit tests run # qmake with CONFIG-=debug_and_release CONFIG+=release. # diff --git a/src/qgcunittest/MockUAS.h b/src/qgcunittest/MockUAS.h index 6e7ee75509e468698fab7c7bcbbe8696835eae7b..e20ac200558d65d48c8711cca9d4de64b6b84036 100644 --- a/src/qgcunittest/MockUAS.h +++ b/src/qgcunittest/MockUAS.h @@ -1,24 +1,24 @@ /*===================================================================== - + QGroundControl Open Source Ground Control Station - + (c) 2009 - 2014 QGROUNDCONTROL PROJECT - + 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 . - + ======================================================================*/ #ifndef MOCKUAS_H @@ -39,43 +39,43 @@ class MockUAS : public UASInterface { Q_OBJECT - + signals: // The following UASInterface signals are supported // void parameterChanged(int uas, int component, QString parameterName, QVariant value); // void remoteControlChannelRawChanged(int channelId, float raw); - + public: // Implemented UASInterface overrides virtual int getSystemType(void) { return _systemType; } virtual int getUASID(void) const { return _systemId; } virtual QGCUASParamManagerInterface* getParamManager() { return &_paramManager; }; - + // sendMessage is only supported if a mavlink plugin is installed. virtual void sendMessage(mavlink_message_t message); - + public: // MockUAS methods MockUAS(void); - + // Use these methods to setup/control the mock UAS - + void setMockSystemType(int systemType) { _systemType = systemType; } void setMockSystemId(int systemId) { _systemId = systemId; } - + /// @return returns mock QGCUASParamManager associated with the UAS. This mock implementation /// allows you to simulate parameter input and validate parameter setting MockQGCUASParamManager* getMockQGCUASParamManager(void) { return &_paramManager; } - + /// @brief Sets the parameter map into the mock QGCUASParamManager and signals parameterChanged for /// each param void setMockParametersAndSignal(MockQGCUASParamManager::ParamMap_t& map); - + void emitRemoteControlChannelRawChanged(int channel, float raw) { emit remoteControlChannelRawChanged(channel, raw); } - + /// @brief Installs a mavlink plugin. Only a single mavlink plugin is supported at a time. void setMockMavlinkPlugin(MockMavlinkInterface* mavlinkPlugin) { _mavlinkPlugin = mavlinkPlugin; }; - + public: // Unimplemented UASInterface overrides virtual QString getUASName() const { Q_ASSERT(false); return _bogusString; }; @@ -168,16 +168,19 @@ public slots: virtual void sendHilOpticalFlow(quint64 time_us, qint16 flow_x, qint16 flow_y, float flow_comp_m_x, float flow_comp_m_y, quint8 quality, float ground_distance) { Q_UNUSED(time_us); Q_UNUSED(flow_x); Q_UNUSED(flow_y); Q_UNUSED(flow_comp_m_x); Q_UNUSED(flow_comp_m_y); Q_UNUSED(quality); Q_UNUSED(ground_distance); Q_ASSERT(false);}; - + virtual void sendMapRCToParam(QString param_id, float scale, float value0, quint8 param_rc_channel_index, float valueMin, float valueMax) + { Q_UNUSED(param_id); Q_UNUSED(scale); Q_UNUSED(value0); Q_UNUSED(param_rc_channel_index); Q_UNUSED(valueMin); Q_UNUSED(valueMax); } + virtual void unsetRCToParameterMap() {} + virtual bool isRotaryWing() { Q_ASSERT(false); return false; } virtual bool isFixedWing() { Q_ASSERT(false); return false; } private: int _systemType; int _systemId; - + MockQGCUASParamManager _paramManager; - + MockMavlinkInterface* _mavlinkPlugin; ///< Mock Mavlink plugin, NULL for none // Bogus variables used for return types of NYI methods diff --git a/src/uas/UAS.cc b/src/uas/UAS.cc index 26fbda4bf1812ce2b5c340397c7a0bb7a45df704..20312d9afe7ab491ec993d12a61eca3d01f233b9 100644 --- a/src/uas/UAS.cc +++ b/src/uas/UAS.cc @@ -2357,7 +2357,7 @@ void UAS::processParamValueMsg(mavlink_message_t& msg, const QString& paramName, // Insert with correct type // TODO: This is a hack for MAV_AUTOPILOT_ARDUPILOTMEGA until the new version of MAVLink and a fix for their param handling. - + switch (rawValue.param_type) { case MAV_PARAM_TYPE_REAL32: if (getAutopilotType() == MAV_AUTOPILOT_ARDUPILOTMEGA) { @@ -2366,7 +2366,7 @@ void UAS::processParamValueMsg(mavlink_message_t& msg, const QString& paramName, paramValue = QVariant(paramUnion.param_float); } break; - + case MAV_PARAM_TYPE_UINT8: if (getAutopilotType() == MAV_AUTOPILOT_ARDUPILOTMEGA) { paramValue = QVariant(QChar((unsigned char)paramUnion.param_float)); @@ -2374,7 +2374,7 @@ void UAS::processParamValueMsg(mavlink_message_t& msg, const QString& paramName, paramValue = QVariant(QChar((unsigned char)paramUnion.param_uint8)); } break; - + case MAV_PARAM_TYPE_INT8: if (getAutopilotType() == MAV_AUTOPILOT_ARDUPILOTMEGA) { paramValue = QVariant(QChar((char)paramUnion.param_float)); @@ -2382,7 +2382,7 @@ void UAS::processParamValueMsg(mavlink_message_t& msg, const QString& paramName, paramValue = QVariant(QChar((char)paramUnion.param_int8)); } break; - + case MAV_PARAM_TYPE_INT16: if (getAutopilotType() == MAV_AUTOPILOT_ARDUPILOTMEGA) { paramValue = QVariant((short)paramUnion.param_float); @@ -2390,7 +2390,7 @@ void UAS::processParamValueMsg(mavlink_message_t& msg, const QString& paramName, paramValue = QVariant(paramUnion.param_int16); } break; - + case MAV_PARAM_TYPE_UINT32: if (getAutopilotType() == MAV_AUTOPILOT_ARDUPILOTMEGA) { paramValue = QVariant((unsigned int)paramUnion.param_float); @@ -2405,13 +2405,13 @@ void UAS::processParamValueMsg(mavlink_message_t& msg, const QString& paramName, paramValue = QVariant(paramUnion.param_int32); } break; - + default: qCritical() << "INVALID DATA TYPE USED AS PARAMETER VALUE: " << rawValue.param_type; } qCDebug(UASLog) << "Received PARAM_VALUE" << paramName << paramValue << rawValue.param_type; - + parameters.value(compId)->insert(paramName, paramValue); emit parameterChanged(uasId, compId, paramName, paramValue); emit parameterChanged(uasId, compId, rawValue.param_count, rawValue.param_index, paramName, paramValue); @@ -3290,12 +3290,12 @@ void UAS::removeLink(QObject* object) { qCDebug(UASLog) << "removeLink:" << QString("%1").arg((ulong)object, 0, 16); qCDebug(UASLog) << "link count:" << links.count(); - + // Do not dynamic cast or de-reference QObject, since object is either in destructor or may have already // been destroyed. - + LinkInterface* link = (LinkInterface*)object; - + int index = links.indexOf(link); Q_ASSERT(index != -1); links.removeAt(index); @@ -3467,3 +3467,55 @@ void UAS::stopLowBattAlarm() lowBattAlarm = false; } } + +void UAS::sendMapRCToParam(QString param_id, float scale, float value0, quint8 param_rc_channel_index, float valueMin, float valueMax) +{ + mavlink_message_t message; + + char param_id_cstr[MAVLINK_MSG_PARAM_MAP_RC_FIELD_PARAM_ID_LEN] = {}; + // Copy string into buffer, ensuring not to exceed the buffer size + for (unsigned int i = 0; i < sizeof(param_id_cstr); i++) + { + if ((int)i < param_id.length()) + { + param_id_cstr[i] = param_id.toLatin1()[i]; + } + } + + mavlink_msg_param_map_rc_pack(mavlink->getSystemId(), + mavlink->getComponentId(), + &message, + this->uasId, + 0, + param_id_cstr, + -1, + param_rc_channel_index, + value0, + scale, + valueMin, + valueMax); + sendMessage(message); + qDebug() << "Mavlink message sent"; +} + +void UAS::unsetRCToParameterMap() +{ + char param_id_cstr[MAVLINK_MSG_PARAM_MAP_RC_FIELD_PARAM_ID_LEN] = {}; + + for (int i = 0; i < 3; i++) { + mavlink_message_t message; + mavlink_msg_param_map_rc_pack(mavlink->getSystemId(), + mavlink->getComponentId(), + &message, + this->uasId, + 0, + param_id_cstr, + -2, + i, + 0.0f, + 0.0f, + 0.0f, + 0.0f); + sendMessage(message); + } +} diff --git a/src/uas/UAS.h b/src/uas/UAS.h index 86b037de5bc8c6cf55f3eafe6ef55bb50b86bf56..9762ce9856a6d9071313bf2ede87ec4906e6c7cb 100644 --- a/src/uas/UAS.h +++ b/src/uas/UAS.h @@ -883,6 +883,12 @@ public slots: /** @brief Triggers the action associated with the given ID. */ void triggerAction(int action); + + /** @brief Send command to map a RC channel to a parameter */ + void sendMapRCToParam(QString param_id, float scale, float value0, quint8 param_rc_channel_index, float valueMin, float valueMax); + + /** @brief Send command to disable all bindings/maps between RC and parameters */ + void unsetRCToParameterMap(); signals: /** @brief The main/battery voltage has changed/was updated */ //void voltageChanged(int uasId, double voltage); // Defined in UASInterface already diff --git a/src/uas/UASInterface.h b/src/uas/UASInterface.h index 17c7fc4f7007b84221d24dad38abbf6971ad654f..9aeca95253e818b42940f6a997ec8d12bdcbda92 100644 --- a/src/uas/UASInterface.h +++ b/src/uas/UASInterface.h @@ -199,32 +199,32 @@ public: */ static QColor getNextColor() { /* Create color map */ - static QList colors = QList() - << QColor(231,72,28) - << QColor(104,64,240) - << QColor(203,254,121) + static QList colors = QList() + << QColor(231,72,28) + << QColor(104,64,240) + << QColor(203,254,121) << QColor(161,252,116) - << QColor(232,33,47) - << QColor(116,251,110) - << QColor(234,38,107) + << QColor(232,33,47) + << QColor(116,251,110) + << QColor(234,38,107) << QColor(104,250,138) - << QColor(235,43,165) - << QColor(98,248,176) - << QColor(236,48,221) + << QColor(235,43,165) + << QColor(98,248,176) + << QColor(236,48,221) << QColor(92,247,217) - << QColor(200,54,238) - << QColor(87,231,246) - << QColor(151,59,239) + << QColor(200,54,238) + << QColor(87,231,246) + << QColor(151,59,239) << QColor(81,183,244) - << QColor(75,133,243) - << QColor(242,255,128) + << QColor(75,133,243) + << QColor(242,255,128) << QColor(230,126,23); - + static int nextColor = -1; if(nextColor == 18){//if at the end of the list nextColor = -1;//go back to the beginning } - nextColor++; + nextColor++; return colors[nextColor];//return the next color } @@ -391,6 +391,12 @@ public slots: virtual void sendHilOpticalFlow(quint64 time_us, qint16 flow_x, qint16 flow_y, float flow_comp_m_x, float flow_comp_m_y, quint8 quality, float ground_distance) = 0; + /** @brief Send command to map a RC channel to a parameter */ + virtual void sendMapRCToParam(QString param_id, float scale, float value0, quint8 param_rc_channel_index, float valueMin, float valueMax) = 0; + + /** @brief Send command to disable all bindings/maps between RC and parameters */ + virtual void unsetRCToParameterMap() = 0; + protected: QColor color; diff --git a/src/ui/QGCBaseParamWidget.cc b/src/ui/QGCBaseParamWidget.cc index 35e868518a6f5beb120a698da2dca0865a19a7b0..b6f86c90d2d7dbcfc6e61ba081585df9ddabf605 100644 --- a/src/ui/QGCBaseParamWidget.cc +++ b/src/ui/QGCBaseParamWidget.cc @@ -95,6 +95,11 @@ void QGCBaseParamWidget::requestOnboardParamsUpdate() paramMgr->requestParameterList(); } +void QGCBaseParamWidget::requestOnboardParamUpdate(QString parameterName) +{ + paramMgr->requestParameterUpdate(paramMgr->getDefaultComponentId(), parameterName); +} + void QGCBaseParamWidget::saveParametersToFile() { diff --git a/src/ui/QGCBaseParamWidget.h b/src/ui/QGCBaseParamWidget.h index ffb0e912574b146f1f13110c1ab4db5a79fbd690..8ec34711dc9b93688dd081301ceff3fe39b0235e 100644 --- a/src/ui/QGCBaseParamWidget.h +++ b/src/ui/QGCBaseParamWidget.h @@ -29,7 +29,7 @@ protected: virtual void disconnectFromParamManager(); ///< Disconnect from any connected param manager signals signals: - + public slots: virtual void handleOnboardParamUpdate(int component,const QString& parameterName, QVariant value) = 0; virtual void handlePendingParamUpdate(int compId, const QString& paramName, QVariant value, bool isPending) = 0; @@ -43,6 +43,9 @@ public slots: /** @brief Request list of parameters from MAV */ virtual void requestOnboardParamsUpdate(); + /** @brief Request single parameter from MAV */ + virtual void requestOnboardParamUpdate(QString parameterName); + /** @brief Store parameters to a file */ virtual void saveParametersToFile(); diff --git a/src/ui/QGCMapRCToParamDialog.cpp b/src/ui/QGCMapRCToParamDialog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8ac5bacb90368c3acc99cadee0179a5bff01ba86 --- /dev/null +++ b/src/ui/QGCMapRCToParamDialog.cpp @@ -0,0 +1,135 @@ +/*===================================================================== + + QGroundControl Open Source Ground Control Station + + (c) 2009 - 2014 QGROUNDCONTROL PROJECT + + 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 . + + ======================================================================*/ + +/// @file +/// @author Thomas Gubler + +#include "QGCMapRCToParamDialog.h" +#include "ui_QGCMapRCToParamDialog.h" + +#include +#include +#include +#include +#include + +QGCMapRCToParamDialog::QGCMapRCToParamDialog(QString param_id, + UASInterface *mav, QWidget *parent) : + QDialog(parent), + param_id(param_id), + mav(mav), + ui(new Ui::QGCMapRCToParamDialog) +{ + ui->setupUi(this); + + // only enable ok button when param was refreshed + QPushButton *okButton = ui->buttonBox->button(QDialogButtonBox::Ok); + okButton->setEnabled(false); + + ui->paramIdLabel->setText(param_id); + + // Refresh the param + ParamLoader *paramLoader = new ParamLoader(param_id, mav); + paramLoader->moveToThread(¶mLoadThread); + connect(¶mLoadThread, &QThread::finished, paramLoader, &QObject::deleteLater); + connect(this, &QGCMapRCToParamDialog::refreshParam, paramLoader, &ParamLoader::load); + connect(paramLoader, &ParamLoader::paramLoaded, this, &QGCMapRCToParamDialog::paramLoaded); + paramLoadThread.start(); + emit refreshParam(); +} + +QGCMapRCToParamDialog::~QGCMapRCToParamDialog() +{ + delete ui; +} + +void QGCMapRCToParamDialog::accept() { + emit mapRCToParamDialogResult(param_id, + (float)ui->scaleDoubleSpinBox->value(), + (float)ui->value0DoubleSpinBox->value(), + (quint8)ui->rcParamChannelComboBox->currentIndex(), + (float)ui->minValueDoubleSpinBox->value(), + (float)ui->maxValueDoubleSpinBox->value()); + + QDialog::accept(); +} + +void QGCMapRCToParamDialog::paramLoaded(bool success, float value, QString message) +{ + paramLoadThread.quit(); + if (success) { + ui->infoLabel->setText("Parameter value is up to date"); + ui->value0DoubleSpinBox->setValue(value); + ui->value0DoubleSpinBox->setEnabled(true); + + connect(this, &QGCMapRCToParamDialog::mapRCToParamDialogResult, + mav, &UASInterface::sendMapRCToParam); + QPushButton *okButton = ui->buttonBox->button(QDialogButtonBox::Ok); + okButton->setEnabled(true); + } else { + qDebug() << "Error while reading param" << param_id; + ui->infoLabel->setText("Error while refreshing param (" + message + ")"); + } +} + +void ParamLoader::load() +{ + // refresh the parameter from onboard to make sure the current value is used + paramMgr->requestParameterUpdate(paramMgr->getDefaultComponentId(), param_id); + + // wait until parameter update is received + QEventLoop loop; + QTimer timer; + connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit); + timer.start(10 * 1e3); + // overloaded signal: + connect(mav, static_cast(&UASInterface::parameterChanged), + this, &ParamLoader::handleParameterChanged); + connect(this, &ParamLoader::correctParameterChanged, + &loop, &QEventLoop::quit); + loop.exec(); + + if (!param_received == true) { + // timeout + emit paramLoaded(false, 0.0f, "Timeout"); + return; + } + + QVariant current_param_value; + bool got_param = paramMgr->getParameterValue(paramMgr->getDefaultComponentId(), + param_id, current_param_value); + + QString message = got_param ? "" : "param manager Error"; + emit paramLoaded(got_param, current_param_value.toFloat(), message); +} + +void ParamLoader::handleParameterChanged(int uas, int component, QString parameterName, QVariant value) +{ + Q_UNUSED(component); + Q_UNUSED(value); + if (uas == mav->getUASID() && parameterName == param_id) { + param_received = true; + emit correctParameterChanged(); + } +} diff --git a/src/ui/QGCMapRCToParamDialog.h b/src/ui/QGCMapRCToParamDialog.h new file mode 100644 index 0000000000000000000000000000000000000000..82f0d90307e43aa44fce0ec635c55ebd6527d302 --- /dev/null +++ b/src/ui/QGCMapRCToParamDialog.h @@ -0,0 +1,96 @@ +/*===================================================================== + + QGroundControl Open Source Ground Control Station + + (c) 2009 - 2014 QGROUNDCONTROL PROJECT + + 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 . + + ======================================================================*/ + +/// @file +/// @brief Dialog to configure RC to paramter mapping +/// @author Thomas Gubler + +#ifndef QGCMAPRCTOPARAMDIALOG_H +#define QGCMAPRCTOPARAMDIALOG_H + +#include +#include +#include "UASInterface.h" + +namespace Ui { +class QGCMapRCToParamDialog; +} + + +class ParamLoader : public QObject +{ + Q_OBJECT + +public: + ParamLoader(QString param_id, UASInterface *mav, QObject * parent = 0): + QObject(parent), + mav(mav), + paramMgr(mav->getParamManager()), + param_id(param_id), + param_received(false) +{} + +public slots: + void load(); + void handleParameterChanged(int uas, int component, QString parameterName, QVariant value); + +signals: + void paramLoaded(bool success, float value, QString message = ""); + void correctParameterChanged(); + +protected: + UASInterface *mav; + QGCUASParamManagerInterface* paramMgr; + QString param_id; + bool param_received; +}; + +class QGCMapRCToParamDialog : public QDialog +{ + Q_OBJECT + QThread paramLoadThread; + +public: + explicit QGCMapRCToParamDialog(QString param_id, + UASInterface *mav, QWidget *parent = 0); + ~QGCMapRCToParamDialog(); + +signals: + void mapRCToParamDialogResult(QString param_id, float scale, float value0, + quint8 param_rc_channel_index, float valueMin, float valueMax); + void refreshParam(); + +public slots: + void accept(); + void paramLoaded(bool success, float value, QString message); + +protected: + // void showEvent(QShowEvent * event ); + QString param_id; + UASInterface *mav; + +private: + Ui::QGCMapRCToParamDialog *ui; +}; + +#endif // QGCMAPRCTOPARAMDIALOG_H diff --git a/src/ui/QGCMapRCToParamDialog.ui b/src/ui/QGCMapRCToParamDialog.ui new file mode 100644 index 0000000000000000000000000000000000000000..8fde55314b79ea2913881056387b92e4fb62783d --- /dev/null +++ b/src/ui/QGCMapRCToParamDialog.ui @@ -0,0 +1,253 @@ + + + QGCMapRCToParamDialog + + + + 0 + 0 + 400 + 315 + + + + Dialog + + + + + 30 + 280 + 341 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + 9 + 9 + 381 + 271 + + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + Bind + + + + + + + RC-Parameter Channel (Knob No.) + + + + + + + false + + + 1 + + + + 1 + + + + + 2 + + + + + 3 + + + + + + + + to + + + + + + + Parameter + + + + + + + TextLabel + + + + + + + with + + + + + + + Scale + + + + + + + 1.000000000000000 + + + + + + + Initial Value + + + + + + + false + + + 8 + + + -100000.000000000000000 + + + 100000.000000000000000 + + + + + + + Minimum Value + + + + + + + 8 + + + -100000.000000000000000 + + + 100000.000000000000000 + + + + + + + Maximum Value + + + + + + + 8 + + + -10000.000000000000000 + + + 100000.000000000000000 + + + 1.000000000000000 + + + 10.000000000000000 + + + + + + + Waiting for parameter refresh,,, + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + buttonBox + accepted() + QGCMapRCToParamDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + QGCMapRCToParamDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/ui/QGCParamTreeWidget.cpp b/src/ui/QGCParamTreeWidget.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7934d2977c570d88a00c12aebf6f6ccd4aa2f9f1 --- /dev/null +++ b/src/ui/QGCParamTreeWidget.cpp @@ -0,0 +1,96 @@ +/*===================================================================== + + QGroundControl Open Source Ground Control Station + + (c) 2009 - 2014 QGROUNDCONTROL PROJECT + + 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 . + + ======================================================================*/ + +/// @file +/// @author Thomas Gubler + +#include "QGCParamTreeWidget.h" +#include +#include +#include + +QGCParamTreeWidget::QGCParamTreeWidget(QWidget *parent) : + QTreeWidget(parent) +{ + setContextMenuPolicy(Qt::CustomContextMenu); + + QObject::connect(this, &QGCParamTreeWidget::customContextMenuRequested, + this, &QGCParamTreeWidget::showContextMenu); + qDebug() << "create QGCParamTreeWidget"; + +} + +QGCParamTreeWidget::~QGCParamTreeWidget() +{ + +} + +void QGCParamTreeWidget::showContextMenu(const QPoint &pos) +{ + QMenu menu; + QTreeWidgetItem* item = itemAt(pos); + + // Only show context menu for parameter items and not for group items + // (show for TEST_P but not for TEST) + // If a context menu is needed later for the groups then move this 'if' + // to below where the actions are created and filter out certain actions + // for the outer nodes + if (indexOfTopLevelItem(item) > -1 || + indexOfTopLevelItem(item->parent()) > -1) { + return; + } + + QString param_id = item->data(0, Qt::DisplayRole).toString(); + + // Refresh single parameter + QAction* act = new QAction(tr("Refresh this param"), this); + act->setProperty("action", "refresh"); + act->setProperty("param_id", param_id); + connect(act, &QAction::triggered, this, + &QGCParamTreeWidget::contextMenuAction); + menu.addAction(act); + + // RC to parameter mapping + act = new QAction(tr("Map Parameter to RC"), this); + act->setProperty("action", "maprc"); + act->setProperty("param_id", param_id); + connect(act, &QAction::triggered, this, + &QGCParamTreeWidget::contextMenuAction); + menu.addAction(act); + menu.exec(mapToGlobal(pos)); +} + +void QGCParamTreeWidget::contextMenuAction() { + QString action = qobject_cast( + sender())->property("action").toString(); + QString param_id = qobject_cast( + sender())->property("param_id").toString(); + + if (action == "refresh") { + emit refreshParamRequest(param_id); + } else if (action == "maprc") { + emit mapRCToParamRequest(param_id); + } else { + qDebug() << "Undefined context menu action"; + } +} diff --git a/src/ui/QGCParamTreeWidget.h b/src/ui/QGCParamTreeWidget.h new file mode 100644 index 0000000000000000000000000000000000000000..9c63456db98672555a5f874f2a54be5f2b40bcc9 --- /dev/null +++ b/src/ui/QGCParamTreeWidget.h @@ -0,0 +1,51 @@ +/*===================================================================== + + QGroundControl Open Source Ground Control Station + + (c) 2009 - 2014 QGROUNDCONTROL PROJECT + + 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 . + + ======================================================================*/ + +/// @file +/// @brief A treeview with context menus for parameters +/// @author Thomas Gubler + +#ifndef QGCPARAMTREEWIDGET_H +#define QGCPARAMTREEWIDGET_H + +#include + +/// Implements individual context menus for the QTreeWidgetItems +class QGCParamTreeWidget : public QTreeWidget +{ + Q_OBJECT +public: + QGCParamTreeWidget(QWidget *parent = 0); + ~QGCParamTreeWidget(); + +signals: + void mapRCToParamRequest(QString param_id); + void refreshParamRequest(QString param_id); + +public slots: + void showContextMenu(const QPoint &pos); + void contextMenuAction(); + +}; + +#endif // QGCPARAMTREEWIDGET_H diff --git a/src/ui/QGCParamWidget.cc b/src/ui/QGCParamWidget.cc index d0ab5349acf92332ad6710125c1020d53f1e868a..7084ba0e6c846f0f7c43279f2e797115b23b8a13 100644 --- a/src/ui/QGCParamWidget.cc +++ b/src/ui/QGCParamWidget.cc @@ -36,12 +36,15 @@ This file is part of the QGROUNDCONTROL project #include #include #include +#include +#include #include "MainWindow.h" #include "QGC.h" #include "QGCParamWidget.h" #include "UASInterface.h" #include "UASParameterCommsMgr.h" +#include "QGCMapRCToParamDialog.h" /** * @param uas MAV to set the parameters on @@ -51,7 +54,7 @@ QGCParamWidget::QGCParamWidget(QWidget *parent) : QGCBaseParamWidget(parent), componentItems(new QMap()), statusLabel(new QLabel(this)), - tree(new QTreeWidget(this)), + tree(new QGCParamTreeWidget(this)), _fullParamListLoaded(false) { @@ -64,6 +67,8 @@ void QGCParamWidget::disconnectViewSignalsAndSlots() { disconnect(tree, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, SLOT(parameterItemChanged(QTreeWidgetItem*,int))); + disconnect(tree, &QGCParamTreeWidget::mapRCToParamRequest, this, + &QGCParamWidget::configureRCToParam); } @@ -72,6 +77,10 @@ void QGCParamWidget::connectViewSignalsAndSlots() // Listen for edits to the tree UI connect(tree, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, SLOT(parameterItemChanged(QTreeWidgetItem*,int))); + connect(tree, &QGCParamTreeWidget::mapRCToParamRequest, this, + &QGCParamWidget::configureRCToParam); + connect(tree, &QGCParamTreeWidget::refreshParamRequest, this, + &QGCParamWidget::requestOnboardParamUpdate); } @@ -119,6 +128,13 @@ void QGCParamWidget::addActionButtonsToLayout(QGridLayout* layout) paramMgr, SLOT(copyPersistentParamsToVolatile())); layout->addWidget(readButton, 3, 2); + QPushButton* unsetRCToParamMapButton = new QPushButton(tr("Clear Rc to Param")); + unsetRCToParamMapButton->setToolTip(tr("Remove any bindings between RC channels and parameters.")); + unsetRCToParamMapButton->setWhatsThis(tr("Remove any bindings between RC channels and parameters.")); + connect(unsetRCToParamMapButton, &QPushButton::clicked, + mav, &UASInterface::unsetRCToParameterMap); + layout->addWidget(unsetRCToParamMapButton, 4, 1); + } void QGCParamWidget::layoutWidget() @@ -241,9 +257,9 @@ void QGCParamWidget::handleOnboardParameterListUpToDate() if (_fullParamListLoaded) { return; } - + _fullParamListLoaded = true; - + //turn off updates while we refresh the entire list tree->setUpdatesEnabled(false); @@ -355,7 +371,7 @@ void QGCParamWidget::insertParamAlphabetical(int indexLowerBound, int indexUpper QTreeWidgetItem* QGCParamWidget::updateParameterDisplay(int compId, QString parameterName, QVariant value) { //qDebug() << "QGCParamWidget::updateParameterDisplay" << parameterName; - + // Filter the parameters according to the filter list if (_filterList.count() != 0) { bool filterFound = false; @@ -366,7 +382,7 @@ QTreeWidgetItem* QGCParamWidget::updateParameterDisplay(int compId, QString para } if (paramFilter == parameterName) { filterFound = true; - break; + break; } } if (!filterFound) { @@ -509,7 +525,6 @@ void QGCParamWidget::parameterItemChanged(QTreeWidgetItem* paramItem, int column } } - void QGCParamWidget::setParameterStatusMsg(const QString& msg) { statusLabel->setText(msg); @@ -544,3 +559,9 @@ void QGCParamWidget::handleParamStatusMsgUpdate(QString msg, int level) statusLabel->setPalette(pal); statusLabel->setText(msg); } + +void QGCParamWidget::configureRCToParam(QString param_id) { + QGCMapRCToParamDialog * d = new QGCMapRCToParamDialog(param_id, + mav, this); + d->exec(); +} diff --git a/src/ui/QGCParamWidget.h b/src/ui/QGCParamWidget.h index 5db5a6fd3ed76f372456bcafbbc4bb8b2fbf7dd0..61314bc8907bfde38ff2b61e5a5cf0d113af41b3 100644 --- a/src/ui/QGCParamWidget.h +++ b/src/ui/QGCParamWidget.h @@ -32,10 +32,10 @@ This file is part of the QGROUNDCONTROL project #include #include -#include #include #include #include +#include "QGCParamTreeWidget.h" #include "QGCBaseParamWidget.h" @@ -52,7 +52,7 @@ class QGCParamWidget : public QGCBaseParamWidget Q_OBJECT public: QGCParamWidget(QWidget *parent = 0); - + /// @brief Sets the list of parameters which should be shown by this editor. Parameter names can be /// wildcarded at the end such as this: "RC*". Which will filter to all parameters which begin /// with "RC". The wildcard (*) can only be at the end of the string. @@ -75,10 +75,6 @@ protected: virtual void addActionButtonsToLayout(QGridLayout* layout); - -signals: - - public slots: virtual void handleOnboardParamUpdate(int component,const QString& parameterName, QVariant value); virtual void handlePendingParamUpdate(int compId, const QString& paramName, QVariant value, bool isPending); @@ -97,14 +93,18 @@ public slots: /** @brief Update when user changes parameters */ void parameterItemChanged(QTreeWidgetItem* prev, int column); + /** Promt configuration for param map config from user */ + void configureRCToParam(QString param_id); + + protected: QMap* componentItems; ///< The tree of component items, stored by component ID QMap* > paramGroups; ///< Parameter groups to organize component items QLabel* statusLabel; ///< User-facing parameter status label - QTreeWidget* tree; ///< The parameter tree + QGCParamTreeWidget* tree; ///< The parameter tree QStringList _filterList; - + private: bool _fullParamListLoaded; };