diff --git a/flight/modules/ManualControl/armhandler.c b/flight/modules/ManualControl/armhandler.c index b16f1e39b..76833678e 100644 --- a/flight/modules/ManualControl/armhandler.c +++ b/flight/modules/ManualControl/armhandler.c @@ -274,6 +274,9 @@ static bool okToArm(void) case FLIGHTSTATUS_FLIGHTMODE_STABILIZED1: case FLIGHTSTATUS_FLIGHTMODE_STABILIZED2: case FLIGHTSTATUS_FLIGHTMODE_STABILIZED3: + case FLIGHTSTATUS_FLIGHTMODE_STABILIZED4: + case FLIGHTSTATUS_FLIGHTMODE_STABILIZED5: + case FLIGHTSTATUS_FLIGHTMODE_STABILIZED6: return true; break; diff --git a/ground/openpilotgcs/src/libs/opmapcontrol/src/core/urlfactory.cpp b/ground/openpilotgcs/src/libs/opmapcontrol/src/core/urlfactory.cpp index 0bc943ff4..6025eecc1 100644 --- a/ground/openpilotgcs/src/libs/opmapcontrol/src/core/urlfactory.cpp +++ b/ground/openpilotgcs/src/libs/opmapcontrol/src/core/urlfactory.cpp @@ -197,7 +197,6 @@ QString UrlFactory::MakeImageUrl(const MapType::Types &type, const Point &pos, c QString sec2 = ""; // after &zoom=... GetSecGoogleWords(pos, sec1, sec2); TryCorrectGoogleVersions(); - QString VersionGoogleSatellite = "132"; return QString("https://%1%2.google.com/%3/v=%4&hl=%5&x=%6%7&y=%8&z=%9&s=%10").arg(server).arg(GetServerNum(pos, 4)).arg(request).arg(VersionGoogleSatellite).arg(language).arg(pos.X()).arg(sec1).arg(pos.Y()).arg(zoom).arg(sec2); } break; diff --git a/ground/openpilotgcs/src/libs/utils/coordinateconversions.cpp b/ground/openpilotgcs/src/libs/utils/coordinateconversions.cpp index 4de1f311b..c6ceb0f01 100644 --- a/ground/openpilotgcs/src/libs/utils/coordinateconversions.cpp +++ b/ground/openpilotgcs/src/libs/utils/coordinateconversions.cpp @@ -44,7 +44,7 @@ CoordinateConversions::CoordinateConversions() * @param[in] LLA Longitude latitude altitude for this location * @param[out] Rne[3][3] Rotation matrix */ -void CoordinateConversions::RneFromLLA(double LLA[3], double Rne[3][3]) +void CoordinateConversions::RneFromLLA(double LLA[3], float Rne[3][3]) { float sinLat, sinLon, cosLat, cosLon; @@ -134,7 +134,7 @@ int CoordinateConversions::NED2LLA_HomeECEF(double BaseECEFm[3], double NED[3], // stored value is in cm, convert to m double BaseLLA[3]; double ECEF[3]; - double Rne[3][3]; + float Rne[3][3]; // Get LLA address to compute conversion matrix ECEF2LLA(BaseECEFm, BaseLLA); diff --git a/ground/openpilotgcs/src/libs/utils/coordinateconversions.h b/ground/openpilotgcs/src/libs/utils/coordinateconversions.h index de6ac7568..23b28fe47 100644 --- a/ground/openpilotgcs/src/libs/utils/coordinateconversions.h +++ b/ground/openpilotgcs/src/libs/utils/coordinateconversions.h @@ -41,7 +41,7 @@ public: CoordinateConversions(); int NED2LLA_HomeECEF(double BaseECEFcm[3], double NED[3], double position[3]); int NED2LLA_HomeLLA(double LLA[3], double NED[3], double position[3]); - void RneFromLLA(double LLA[3], double Rne[3][3]); + void RneFromLLA(double LLA[3], float Rne[3][3]); void LLA2ECEF(double LLA[3], double ECEF[3]); int ECEF2LLA(double ECEF[3], double LLA[3]); void LLA2Base(double LLA[3], double BaseECEF[3], float Rne[3][3], float NED[3]); diff --git a/ground/openpilotgcs/src/libs/utils/mytabbedstackwidget.cpp b/ground/openpilotgcs/src/libs/utils/mytabbedstackwidget.cpp index 2626ca47b..bc31f58c0 100644 --- a/ground/openpilotgcs/src/libs/utils/mytabbedstackwidget.cpp +++ b/ground/openpilotgcs/src/libs/utils/mytabbedstackwidget.cpp @@ -82,13 +82,34 @@ MyTabbedStackWidget::MyTabbedStackWidget(QWidget *parent, bool isVertical, bool void MyTabbedStackWidget::insertTab(const int index, QWidget *tab, const QIcon &icon, const QString &label) { - tab->setContentsMargins(0, 0, 0, 0); - m_stackWidget->insertWidget(index, tab); + // create and insert item QListWidgetItem *item = new QListWidgetItem(icon, label); + item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); item->setTextAlignment(Qt::AlignHCenter | Qt::AlignBottom); item->setToolTip(label); m_listWidget->insertItem(index, item); + + // setup and insert widget + tab->setContentsMargins(0, 0, 0, 0); + m_stackWidget->insertWidget(index, tab); +} + +void MyTabbedStackWidget::replaceTab(int index, QWidget *tab) +{ + QWidget *wid = m_stackWidget->widget(index); + + // setup and insert new widget + tab->setContentsMargins(0, 0, 0, 0); + m_stackWidget->insertWidget(index, tab); + // check special case when replacing currenlty selected tab + if (index == currentIndex()) { + // currently selected tab is being replaced so select the new tab before removing the old one + m_stackWidget->setCurrentWidget(tab); + } + // remove and delete old widget + m_stackWidget->removeWidget(wid); + delete wid; } void MyTabbedStackWidget::removeTab(int index) @@ -97,6 +118,7 @@ void MyTabbedStackWidget::removeTab(int index) m_stackWidget->removeWidget(wid); delete wid; + QListWidgetItem *item = m_listWidget->item(index); m_listWidget->removeItemWidget(item); delete item; diff --git a/ground/openpilotgcs/src/libs/utils/mytabbedstackwidget.h b/ground/openpilotgcs/src/libs/utils/mytabbedstackwidget.h index 661200383..169eca9ba 100644 --- a/ground/openpilotgcs/src/libs/utils/mytabbedstackwidget.h +++ b/ground/openpilotgcs/src/libs/utils/mytabbedstackwidget.h @@ -40,6 +40,7 @@ public: MyTabbedStackWidget(QWidget *parent = 0, bool isVertical = false, bool iconAbove = true); void insertTab(int index, QWidget *tab, const QIcon &icon, const QString &label); + void replaceTab(int index, QWidget *tab); void removeTab(int index); void setIconSize(int size) { diff --git a/ground/openpilotgcs/src/plugins/config/channelform.cpp b/ground/openpilotgcs/src/plugins/config/channelform.cpp new file mode 100644 index 000000000..a15a5f713 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/config/channelform.cpp @@ -0,0 +1,73 @@ +#include "channelform.h" + +#include + + +ChannelForm::ChannelForm(const int index, QWidget *parent) : ConfigTaskWidget(parent), m_index(index) +{} + +ChannelForm::~ChannelForm() +{} + +int ChannelForm::index() const +{ + return m_index; +} + +void ChannelForm::moveTo(QGridLayout &dstLayout) +{ + QGridLayout *srcLayout = dynamic_cast(layout()); + + Q_ASSERT(srcLayout); + + // if we are the first row to be inserted then show the legend + bool showLegend = (dstLayout.rowCount() == 1); + + if (showLegend) { + // move legend row to target grid layout + moveRow(0, *srcLayout, dstLayout); + } else { + removeRow(0, *srcLayout); + } + + // move field row to target grid layout + moveRow(1, *srcLayout, dstLayout); + + // this form is now empty so hide it + setVisible(false); +} + +void ChannelForm::moveRow(int row, QGridLayout &srcLayout, QGridLayout &dstLayout) +{ + int dstRow = dstLayout.rowCount(); + + for (int col = 0; col < srcLayout.columnCount(); col++) { + QLayoutItem *item = srcLayout.itemAtPosition(row, col); + if (!item) { + continue; + } + QWidget *widget = item->widget(); + if (widget) { + dstLayout.addWidget(widget, dstRow, col); + continue; + } + // TODO handle item of type QLayout + } +} + +void ChannelForm::removeRow(int row, QGridLayout &layout) +{ + for (int col = 0; col < layout.columnCount(); col++) { + QLayoutItem *item = layout.itemAtPosition(row, col); + if (!item) { + continue; + } + QWidget *widget = item->widget(); + if (widget) { + layout.removeWidget(widget); + delete widget; + continue; + } + // TODO handle item of type QLayout + } +} diff --git a/ground/openpilotgcs/src/plugins/config/channelform.h b/ground/openpilotgcs/src/plugins/config/channelform.h new file mode 100644 index 000000000..6c62a2f4b --- /dev/null +++ b/ground/openpilotgcs/src/plugins/config/channelform.h @@ -0,0 +1,36 @@ +#ifndef CHANNELFORM_H +#define CHANNELFORM_H + +#include "configtaskwidget.h" + +#include + +namespace Ui { +class ChannelForm; +} + +class QGridLayout; + +class ChannelForm : public ConfigTaskWidget { + Q_OBJECT + +public: + explicit ChannelForm(const int index, QWidget *parent = 0); + ~ChannelForm(); + + int index() const; + + virtual QString name() = 0; + virtual void setName(const QString &name) = 0; + + void moveTo(QGridLayout &dstLayout); + +private: + // Channel index + int m_index; + + static void moveRow(int row, QGridLayout &srcLayout, QGridLayout &dstLayout); + static void removeRow(int row, QGridLayout &layout); +}; + +#endif // CHANNELFORM_H diff --git a/ground/openpilotgcs/src/plugins/config/config.pro b/ground/openpilotgcs/src/plugins/config/config.pro index 8c73c6d28..cea1b866d 100644 --- a/ground/openpilotgcs/src/plugins/config/config.pro +++ b/ground/openpilotgcs/src/plugins/config/config.pro @@ -1,18 +1,19 @@ TEMPLATE = lib TARGET = Config DEFINES += CONFIG_LIBRARY -QT += svg -QT += opengl -QT += qml quick + +QT += svg opengl qml quick include(config_dependencies.pri) INCLUDEPATH += ../../libs/eigen -OTHER_FILES += Config.pluginspec \ +OTHER_FILES += \ + Config.pluginspec \ calibration/WizardStepIndicator.qml -HEADERS += configplugin.h \ +HEADERS += \ + configplugin.h \ configgadgetwidget.h \ configgadgetfactory.h \ configgadget.h \ @@ -27,6 +28,7 @@ HEADERS += configplugin.h \ assertions.h \ defaultattitudewidget.h \ defaulthwsettingswidget.h \ + channelform.h \ inputchannelform.h \ configcamerastabilizationwidget.h \ configtxpidwidget.h \ @@ -57,7 +59,8 @@ HEADERS += configplugin.h \ calibration/gyrobiascalibrationmodel.h \ calibration/calibrationuiutils.h -SOURCES += configplugin.cpp \ +SOURCES += \ + configplugin.cpp \ configgadgetwidget.cpp \ configgadgetfactory.cpp \ configgadget.cpp \ @@ -71,6 +74,7 @@ SOURCES += configplugin.cpp \ configpipxtremewidget.cpp \ defaultattitudewidget.cpp \ defaulthwsettingswidget.cpp \ + channelform.cpp \ inputchannelform.cpp \ configcamerastabilizationwidget.cpp \ configrevowidget.cpp \ @@ -95,7 +99,8 @@ SOURCES += configplugin.cpp \ calibration/levelcalibrationmodel.cpp \ calibration/gyrobiascalibrationmodel.cpp -FORMS += airframe.ui \ +FORMS += \ + airframe.ui \ airframe_ccpm.ui \ airframe_fixedwing.ui \ airframe_ground.ui \ diff --git a/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp b/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp index 4ae81eb08..cd359019b 100644 --- a/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp @@ -55,69 +55,67 @@ ConfigGadgetWidget::ConfigGadgetWidget(QWidget *parent) : QWidget(parent) { setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); - ftw = new MyTabbedStackWidget(this, true, true); - ftw->setIconSize(64); + stackWidget = new MyTabbedStackWidget(this, true, true); + stackWidget->setIconSize(64); QVBoxLayout *layout = new QVBoxLayout; layout->setContentsMargins(0, 0, 0, 0); - layout->addWidget(ftw); + layout->addWidget(stackWidget); setLayout(layout); - // ********************* QWidget *qwd; QIcon *icon = new QIcon(); icon->addFile(":/configgadget/images/hardware_normal.png", QSize(), QIcon::Normal, QIcon::Off); icon->addFile(":/configgadget/images/hardware_selected.png", QSize(), QIcon::Selected, QIcon::Off); qwd = new DefaultHwSettingsWidget(this); - ftw->insertTab(ConfigGadgetWidget::hardware, qwd, *icon, QString("Hardware")); + stackWidget->insertTab(ConfigGadgetWidget::hardware, qwd, *icon, QString("Hardware")); icon = new QIcon(); icon->addFile(":/configgadget/images/vehicle_normal.png", QSize(), QIcon::Normal, QIcon::Off); icon->addFile(":/configgadget/images/vehicle_selected.png", QSize(), QIcon::Selected, QIcon::Off); qwd = new ConfigVehicleTypeWidget(this); - ftw->insertTab(ConfigGadgetWidget::aircraft, qwd, *icon, QString("Vehicle")); + stackWidget->insertTab(ConfigGadgetWidget::aircraft, qwd, *icon, QString("Vehicle")); icon = new QIcon(); icon->addFile(":/configgadget/images/input_normal.png", QSize(), QIcon::Normal, QIcon::Off); icon->addFile(":/configgadget/images/input_selected.png", QSize(), QIcon::Selected, QIcon::Off); qwd = new ConfigInputWidget(this); - ftw->insertTab(ConfigGadgetWidget::input, qwd, *icon, QString("Input")); + stackWidget->insertTab(ConfigGadgetWidget::input, qwd, *icon, QString("Input")); icon = new QIcon(); icon->addFile(":/configgadget/images/output_normal.png", QSize(), QIcon::Normal, QIcon::Off); icon->addFile(":/configgadget/images/output_selected.png", QSize(), QIcon::Selected, QIcon::Off); qwd = new ConfigOutputWidget(this); - ftw->insertTab(ConfigGadgetWidget::output, qwd, *icon, QString("Output")); + stackWidget->insertTab(ConfigGadgetWidget::output, qwd, *icon, QString("Output")); icon = new QIcon(); icon->addFile(":/configgadget/images/ins_normal.png", QSize(), QIcon::Normal, QIcon::Off); icon->addFile(":/configgadget/images/ins_selected.png", QSize(), QIcon::Selected, QIcon::Off); qwd = new DefaultAttitudeWidget(this); - ftw->insertTab(ConfigGadgetWidget::sensors, qwd, *icon, QString("Attitude")); + stackWidget->insertTab(ConfigGadgetWidget::sensors, qwd, *icon, QString("Attitude")); icon = new QIcon(); icon->addFile(":/configgadget/images/stabilization_normal.png", QSize(), QIcon::Normal, QIcon::Off); icon->addFile(":/configgadget/images/stabilization_selected.png", QSize(), QIcon::Selected, QIcon::Off); qwd = new ConfigStabilizationWidget(this); - ftw->insertTab(ConfigGadgetWidget::stabilization, qwd, *icon, QString("Stabilization")); + stackWidget->insertTab(ConfigGadgetWidget::stabilization, qwd, *icon, QString("Stabilization")); icon = new QIcon(); icon->addFile(":/configgadget/images/camstab_normal.png", QSize(), QIcon::Normal, QIcon::Off); icon->addFile(":/configgadget/images/camstab_selected.png", QSize(), QIcon::Selected, QIcon::Off); qwd = new ConfigCameraStabilizationWidget(this); - ftw->insertTab(ConfigGadgetWidget::camerastabilization, qwd, *icon, QString("Gimbal")); + stackWidget->insertTab(ConfigGadgetWidget::camerastabilization, qwd, *icon, QString("Gimbal")); icon = new QIcon(); icon->addFile(":/configgadget/images/txpid_normal.png", QSize(), QIcon::Normal, QIcon::Off); icon->addFile(":/configgadget/images/txpid_selected.png", QSize(), QIcon::Selected, QIcon::Off); qwd = new ConfigTxPIDWidget(this); - ftw->insertTab(ConfigGadgetWidget::txpid, qwd, *icon, QString("TxPID")); + stackWidget->insertTab(ConfigGadgetWidget::txpid, qwd, *icon, QString("TxPID")); + + stackWidget->setCurrentIndex(ConfigGadgetWidget::hardware); - ftw->setCurrentIndex(ConfigGadgetWidget::hardware); - // ********************* // Listen to autopilot connection events - ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); TelemetryManager *telMngr = pm->getObject(); connect(telMngr, SIGNAL(connected()), this, SLOT(onAutopilotConnect())); @@ -129,9 +127,9 @@ ConfigGadgetWidget::ConfigGadgetWidget(QWidget *parent) : QWidget(parent) } help = 0; - connect(ftw, SIGNAL(currentAboutToShow(int, bool *)), this, SLOT(tabAboutToChange(int, bool *))); + connect(stackWidget, SIGNAL(currentAboutToShow(int, bool *)), this, SLOT(tabAboutToChange(int, bool *))); - // Connect to the PipXStatus object updates + // Connect to the OPLinkStatus object updates UAVObjectManager *objManager = pm->getObject(); oplinkStatusObj = dynamic_cast(objManager->getObject("OPLinkStatus")); if (oplinkStatusObj != NULL) { @@ -148,13 +146,13 @@ ConfigGadgetWidget::ConfigGadgetWidget(QWidget *parent) : QWidget(parent) ConfigGadgetWidget::~ConfigGadgetWidget() { - // TODO: properly delete all the tabs in ftw before exiting + delete stackWidget; } void ConfigGadgetWidget::startInputWizard() { - ftw->setCurrentIndex(ConfigGadgetWidget::input); - ConfigInputWidget *inputWidget = dynamic_cast(ftw->getWidget(ConfigGadgetWidget::input)); + stackWidget->setCurrentIndex(ConfigGadgetWidget::input); + ConfigInputWidget *inputWidget = dynamic_cast(stackWidget->getWidget(ConfigGadgetWidget::input)); Q_ASSERT(inputWidget); inputWidget->startInputWizard(); } @@ -166,24 +164,12 @@ void ConfigGadgetWidget::resizeEvent(QResizeEvent *event) void ConfigGadgetWidget::onAutopilotDisconnect() { - int selectedIndex = ftw->currentIndex(); - - QIcon *icon = new QIcon(); - - icon->addFile(":/configgadget/images/ins_normal.png", QSize(), QIcon::Normal, QIcon::Off); - icon->addFile(":/configgadget/images/ins_selected.png", QSize(), QIcon::Selected, QIcon::Off); QWidget *qwd = new DefaultAttitudeWidget(this); - ftw->removeTab(ConfigGadgetWidget::sensors); - ftw->insertTab(ConfigGadgetWidget::sensors, qwd, *icon, QString("Attitude")); - icon = new QIcon(); - icon->addFile(":/configgadget/images/hardware_normal.png", QSize(), QIcon::Normal, QIcon::Off); - icon->addFile(":/configgadget/images/hardware_selected.png", QSize(), QIcon::Selected, QIcon::Off); - qwd = new DefaultHwSettingsWidget(this); - ftw->removeTab(ConfigGadgetWidget::hardware); - ftw->insertTab(ConfigGadgetWidget::hardware, qwd, *icon, QString("Hardware")); + stackWidget->replaceTab(ConfigGadgetWidget::sensors, qwd); - ftw->setCurrentIndex(selectedIndex); + qwd = new DefaultHwSettingsWidget(this); + stackWidget->replaceTab(ConfigGadgetWidget::hardware, qwd); emit autopilotDisconnected(); } @@ -196,45 +182,25 @@ void ConfigGadgetWidget::onAutopilotConnect() ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); UAVObjectUtilManager *utilMngr = pm->getObject(); if (utilMngr) { - int selectedIndex = ftw->currentIndex(); int board = utilMngr->getBoardModel(); if ((board & 0xff00) == 1024) { // CopterControl family - - QIcon *icon = new QIcon(); - icon->addFile(":/configgadget/images/ins_normal.png", QSize(), QIcon::Normal, QIcon::Off); - icon->addFile(":/configgadget/images/ins_selected.png", QSize(), QIcon::Selected, QIcon::Off); QWidget *qwd = new ConfigCCAttitudeWidget(this); - ftw->removeTab(ConfigGadgetWidget::sensors); - ftw->insertTab(ConfigGadgetWidget::sensors, qwd, *icon, QString("Attitude")); + stackWidget->replaceTab(ConfigGadgetWidget::sensors, qwd); - icon = new QIcon(); - icon->addFile(":/configgadget/images/hardware_normal.png", QSize(), QIcon::Normal, QIcon::Off); - icon->addFile(":/configgadget/images/hardware_selected.png", QSize(), QIcon::Selected, QIcon::Off); - qwd = new ConfigCCHWWidget(this); - ftw->removeTab(ConfigGadgetWidget::hardware); - ftw->insertTab(ConfigGadgetWidget::hardware, qwd, *icon, QString("Hardware")); + qwd = new ConfigCCHWWidget(this); + stackWidget->replaceTab(ConfigGadgetWidget::hardware, qwd); } else if ((board & 0xff00) == 0x0900) { // Revolution family - - QIcon *icon = new QIcon(); - icon->addFile(":/configgadget/images/ins_normal.png", QSize(), QIcon::Normal, QIcon::Off); - icon->addFile(":/configgadget/images/ins_selected.png", QSize(), QIcon::Selected, QIcon::Off); QWidget *qwd = new ConfigRevoWidget(this); - ftw->removeTab(ConfigGadgetWidget::sensors); - ftw->insertTab(ConfigGadgetWidget::sensors, qwd, *icon, QString("Attitude")); + stackWidget->replaceTab(ConfigGadgetWidget::sensors, qwd); - icon = new QIcon(); - icon->addFile(":/configgadget/images/hardware_normal.png", QSize(), QIcon::Normal, QIcon::Off); - icon->addFile(":/configgadget/images/hardware_selected.png", QSize(), QIcon::Selected, QIcon::Off); - qwd = new ConfigRevoHWWidget(this); - ftw->removeTab(ConfigGadgetWidget::hardware); - ftw->insertTab(ConfigGadgetWidget::hardware, qwd, *icon, QString("Hardware")); + qwd = new ConfigRevoHWWidget(this); + stackWidget->replaceTab(ConfigGadgetWidget::hardware, qwd); } else { // Unknown board qDebug() << "Unknown board " << board; } - ftw->setCurrentIndex(selectedIndex); } emit autopilotConnected(); @@ -244,7 +210,7 @@ void ConfigGadgetWidget::tabAboutToChange(int i, bool *proceed) { Q_UNUSED(i); *proceed = true; - ConfigTaskWidget *wid = qobject_cast(ftw->currentWidget()); + ConfigTaskWidget *wid = qobject_cast(stackWidget->currentWidget()); if (!wid) { return; } @@ -275,7 +241,7 @@ void ConfigGadgetWidget::updateOPLinkStatus(UAVObject *) icon->addFile(":/configgadget/images/pipx-selected.png", QSize(), QIcon::Selected, QIcon::Off); QWidget *qwd = new ConfigPipXtremeWidget(this); - ftw->insertTab(ConfigGadgetWidget::oplink, qwd, *icon, QString("OPLink")); + stackWidget->insertTab(ConfigGadgetWidget::oplink, qwd, *icon, QString("OPLink")); oplinkConnected = true; } } @@ -284,6 +250,10 @@ void ConfigGadgetWidget::onOPLinkDisconnect() { qDebug() << "ConfigGadgetWidget onOPLinkDisconnect"; oplinkTimeout->stop(); - ftw->removeTab(ConfigGadgetWidget::oplink); oplinkConnected = false; + + if (stackWidget->currentIndex() == ConfigGadgetWidget::oplink) { + stackWidget->setCurrentIndex(0); + } + stackWidget->removeTab(ConfigGadgetWidget::oplink); } diff --git a/ground/openpilotgcs/src/plugins/config/configgadgetwidget.h b/ground/openpilotgcs/src/plugins/config/configgadgetwidget.h index 45eadd8b5..0a443b9e0 100644 --- a/ground/openpilotgcs/src/plugins/config/configgadgetwidget.h +++ b/ground/openpilotgcs/src/plugins/config/configgadgetwidget.h @@ -65,7 +65,6 @@ signals: protected: void resizeEvent(QResizeEvent *event); - MyTabbedStackWidget *ftw; private: UAVDataObject *oplinkStatusObj; @@ -73,6 +72,8 @@ private: // A timer that timesout the connction to the OPLink. QTimer *oplinkTimeout; bool oplinkConnected; + + MyTabbedStackWidget *stackWidget; }; #endif // CONFIGGADGETWIDGET_H diff --git a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp index a4530978b..1f5402a06 100644 --- a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp @@ -80,41 +80,46 @@ ConfigInputWidget::ConfigInputWidget(QWidget *parent) : unsigned int indexRT = 0; foreach(QString name, manualSettingsObj->getField("ChannelNumber")->getElementNames()) { Q_ASSERT(index < ManualControlSettings::CHANNELGROUPS_NUMELEM); - InputChannelForm *inpForm = new InputChannelForm(this, index == 0); - ui->channelSettings->layout()->addWidget(inpForm); // Add the row to the UI - inpForm->setName(name); + InputChannelForm *form = new InputChannelForm(index, this); + form->setName(name); + form->moveTo(*(ui->channelLayout)); // The order of the following binding calls is important. Since the values will be populated // in reverse order of the binding order otherwise the 'Reversed' logic will floor the neutral value // to the max value ( which is smaller than the neutral value when reversed ) and the channel number // will not be set correctly. - addWidgetBinding("ManualControlSettings", "ChannelNumber", inpForm->ui->channelNumber, index); - addWidgetBinding("ManualControlSettings", "ChannelGroups", inpForm->ui->channelGroup, index); - addWidgetBinding("ManualControlSettings", "ChannelNeutral", inpForm->ui->channelNeutral, index); - addWidgetBinding("ManualControlSettings", "ChannelNeutral", inpForm->ui->neutralValue, index); - addWidgetBinding("ManualControlSettings", "ChannelMax", inpForm->ui->channelMax, index); - addWidgetBinding("ManualControlSettings", "ChannelMin", inpForm->ui->channelMin, index); - addWidgetBinding("ManualControlSettings", "ChannelMax", inpForm->ui->channelMax, index); + addWidgetBinding("ManualControlSettings", "ChannelNumber", form->ui->channelNumber, index); + addWidgetBinding("ManualControlSettings", "ChannelGroups", form->ui->channelGroup, index); + addWidgetBinding("ManualControlSettings", "ChannelNeutral", form->ui->channelNeutral, index); + addWidgetBinding("ManualControlSettings", "ChannelNeutral", form->ui->neutralValue, index); + addWidgetBinding("ManualControlSettings", "ChannelMax", form->ui->channelMax, index); + addWidgetBinding("ManualControlSettings", "ChannelMin", form->ui->channelMin, index); + addWidgetBinding("ManualControlSettings", "ChannelMax", form->ui->channelMax, index); - addWidget(inpForm->ui->channelNumberDropdown); - addWidget(inpForm->ui->channelResponseTime); - addWidget(inpForm->ui->channelRev); + addWidget(form->ui->channelRev); + + // Reversing supported for some channels only + bool reversable = ((index == ManualControlSettings::CHANNELGROUPS_THROTTLE) || + (index == ManualControlSettings::CHANNELGROUPS_ROLL) || + (index == ManualControlSettings::CHANNELGROUPS_PITCH) || + (index == ManualControlSettings::CHANNELGROUPS_YAW)); + form->ui->channelRev->setVisible(reversable); // Input filter response time fields supported for some channels only switch (index) { case ManualControlSettings::CHANNELGROUPS_ROLL: case ManualControlSettings::CHANNELGROUPS_PITCH: case ManualControlSettings::CHANNELGROUPS_YAW: + case ManualControlSettings::CHANNELGROUPS_COLLECTIVE: case ManualControlSettings::CHANNELGROUPS_ACCESSORY0: case ManualControlSettings::CHANNELGROUPS_ACCESSORY1: case ManualControlSettings::CHANNELGROUPS_ACCESSORY2: - addWidgetBinding("ManualControlSettings", "ResponseTime", inpForm->ui->channelResponseTime, indexRT); + addWidgetBinding("ManualControlSettings", "ResponseTime", form->ui->channelResponseTime, indexRT); ++indexRT; break; case ManualControlSettings::CHANNELGROUPS_THROTTLE: case ManualControlSettings::CHANNELGROUPS_FLIGHTMODE: - case ManualControlSettings::CHANNELGROUPS_COLLECTIVE: - inpForm->ui->channelResponseTime->setEnabled(false); + form->ui->channelResponseTime->setVisible(false); break; default: Q_ASSERT(0); diff --git a/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp index 9ca2ed943..ba9618eea 100644 --- a/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp @@ -76,10 +76,12 @@ ConfigOutputWidget::ConfigOutputWidget(QWidget *parent) : ConfigTaskWidget(paren // NOTE: we have channel indices from 0 to 9, but the convention for OP is Channel 1 to Channel 10. // Register for ActuatorSettings changes: for (unsigned int i = 0; i < ActuatorCommand::CHANNEL_NUMELEM; i++) { - OutputChannelForm *form = new OutputChannelForm(i, this, i == 0); + OutputChannelForm *form = new OutputChannelForm(i, this); + form->moveTo(*(ui->channelLayout)); + connect(ui->channelOutTest, SIGNAL(toggled(bool)), form, SLOT(enableChannelTest(bool))); connect(form, SIGNAL(channelChanged(int, int)), this, SLOT(sendChannelTest(int, int))); - ui->channelLayout->addWidget(form); + addWidget(form->ui.actuatorMin); addWidget(form->ui.actuatorNeutral); addWidget(form->ui.actuatorMax); @@ -194,7 +196,7 @@ OutputChannelForm *ConfigOutputWidget::getOutputChannelForm(const int index) con /** * Set the label for a channel output assignement */ -void ConfigOutputWidget::assignOutputChannel(UAVDataObject *obj, QString str) +void ConfigOutputWidget::assignOutputChannel(UAVDataObject *obj, QString &str) { // FIXME: use signal/ slot approach UAVObjectField *field = obj->getField(str); @@ -204,7 +206,7 @@ void ConfigOutputWidget::assignOutputChannel(UAVDataObject *obj, QString str) OutputChannelForm *outputChannelForm = getOutputChannelForm(index); if (outputChannelForm) { - outputChannelForm->setAssignment(str); + outputChannelForm->setName(str); } } @@ -254,15 +256,15 @@ void ConfigOutputWidget::refreshWidgetsValues(UAVObject *obj) // Initialize output forms QList outputChannelForms = findChildren(); foreach(OutputChannelForm * outputChannelForm, outputChannelForms) { - outputChannelForm->setAssignment(ChannelDesc[outputChannelForm->index()]); + outputChannelForm->setName(ChannelDesc[outputChannelForm->index()]); // init min,max,neutral int minValue = actuatorSettingsData.ChannelMin[outputChannelForm->index()]; int maxValue = actuatorSettingsData.ChannelMax[outputChannelForm->index()]; - outputChannelForm->minmax(minValue, maxValue); + outputChannelForm->setRange(minValue, maxValue); int neutral = actuatorSettingsData.ChannelNeutral[outputChannelForm->index()]; - outputChannelForm->neutral(neutral); + outputChannelForm->setNeutral(neutral); } // Get the SpinWhileArmed setting @@ -349,10 +351,10 @@ void ConfigOutputWidget::refreshWidgetsValues(UAVObject *obj) int minValue = actuatorSettingsData.ChannelMin[outputChannelForm->index()]; int maxValue = actuatorSettingsData.ChannelMax[outputChannelForm->index()]; - outputChannelForm->minmax(minValue, maxValue); + outputChannelForm->setRange(minValue, maxValue); int neutral = actuatorSettingsData.ChannelNeutral[outputChannelForm->index()]; - outputChannelForm->neutral(neutral); + outputChannelForm->setNeutral(neutral); } setDirty(dirty); diff --git a/ground/openpilotgcs/src/plugins/config/configoutputwidget.h b/ground/openpilotgcs/src/plugins/config/configoutputwidget.h index 1cabfb5a2..fda2922c6 100644 --- a/ground/openpilotgcs/src/plugins/config/configoutputwidget.h +++ b/ground/openpilotgcs/src/plugins/config/configoutputwidget.h @@ -47,6 +47,8 @@ public: ConfigOutputWidget(QWidget *parent = 0); ~ConfigOutputWidget(); +protected: + void enableControls(bool enable); private: Ui_OutputWidget *ui; @@ -55,14 +57,14 @@ private: void updateChannelInSlider(QSlider *slider, QLabel *min, QLabel *max, QCheckBox *rev, int value); - void assignChannel(UAVDataObject *obj, QString str); - void assignOutputChannel(UAVDataObject *obj, QString str); + void assignOutputChannel(UAVDataObject *obj, QString &str); OutputChannelForm *getOutputChannelForm(const int index) const; int mccDataRate; UAVObject::Metadata accInitialData; bool wasItMe; + private slots: void stopTests(); void disableIfNotMe(UAVObject *obj); @@ -71,8 +73,6 @@ private slots: void runChannelTests(bool state); void sendChannelTest(int index, int value); void openHelp(); -protected: - void enableControls(bool enable); }; -#endif // ifndef CONFIGOUTPUTWIDGET_H +#endif // CONFIGOUTPUTWIDGET_H diff --git a/ground/openpilotgcs/src/plugins/config/input.ui b/ground/openpilotgcs/src/plugins/config/input.ui index 48fee6df8..b53d7ba6d 100644 --- a/ground/openpilotgcs/src/plugins/config/input.ui +++ b/ground/openpilotgcs/src/plugins/config/input.ui @@ -116,8 +116,8 @@ 0 0 - 774 - 748 + 772 + 751 @@ -143,16 +143,16 @@ - 12 + 9 - 0 + 9 - 12 + 9 - 0 + 9 @@ -162,21 +162,21 @@ - 12 + 0 - 12 + 0 - 12 + 0 - 12 + 0 - - - 0 + + + 12 @@ -198,7 +198,7 @@ - + Qt::Horizontal @@ -211,14 +211,14 @@ - + Roll/Pitch/Yaw stick deadband - + Stick deadband in percents of full range (0-10), zero to disable @@ -234,22 +234,6 @@ - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 12 - 20 - - - - @@ -260,7 +244,7 @@ 20 - 40 + 10 @@ -369,6 +353,12 @@ + + + 0 + 0 + + 210 @@ -413,6 +403,12 @@ true + + + 0 + 0 + + 210 @@ -546,8 +542,8 @@ 0 0 - 774 - 748 + 772 + 751 @@ -2048,8 +2044,8 @@ Setup the flight mode channel on the RC Input tab if you have not done so alread 0 0 - 504 - 156 + 772 + 751 @@ -2238,7 +2234,7 @@ Set to 0 to disable (recommended for soaring fixed wings). - + :/core/images/helpicon.svg:/core/images/helpicon.svg diff --git a/ground/openpilotgcs/src/plugins/config/inputchannelform.cpp b/ground/openpilotgcs/src/plugins/config/inputchannelform.cpp index f6df2a3c0..8d5ff8c7f 100644 --- a/ground/openpilotgcs/src/plugins/config/inputchannelform.cpp +++ b/ground/openpilotgcs/src/plugins/config/inputchannelform.cpp @@ -4,69 +4,36 @@ #include "manualcontrolsettings.h" #include "gcsreceiver.h" -InputChannelForm::InputChannelForm(QWidget *parent, bool showlegend) : - ConfigTaskWidget(parent), - ui(new Ui::InputChannelForm) +InputChannelForm::InputChannelForm(const int index, QWidget *parent) : + ChannelForm(index, parent), ui(new Ui::InputChannelForm) { ui->setupUi(this); - // The first time through the loop, keep the legend. All other times, delete it. - if (!showlegend) { - layout()->removeWidget(ui->legend0); - layout()->removeWidget(ui->legend1); - layout()->removeWidget(ui->legend2); - layout()->removeWidget(ui->legend3); - layout()->removeWidget(ui->legend4); - layout()->removeWidget(ui->legend5); - layout()->removeWidget(ui->legend6); - layout()->removeWidget(ui->legend7); - delete ui->legend0; - delete ui->legend1; - delete ui->legend2; - delete ui->legend3; - delete ui->legend4; - delete ui->legend5; - delete ui->legend6; - delete ui->legend7; - } - connect(ui->channelMin, SIGNAL(valueChanged(int)), this, SLOT(minMaxUpdated())); connect(ui->channelMax, SIGNAL(valueChanged(int)), this, SLOT(minMaxUpdated())); connect(ui->neutralValue, SIGNAL(valueChanged(int)), this, SLOT(neutralUpdated())); connect(ui->channelGroup, SIGNAL(currentIndexChanged(int)), this, SLOT(groupUpdated())); connect(ui->channelRev, SIGNAL(toggled(bool)), this, SLOT(reversedUpdated())); - // This is awkward but since we want the UI to be a dropdown but the field is not an enum - // it breaks the UAUVObject widget relation of the task gadget. Running the data through - // a spin box fixes this - connect(ui->channelNumberDropdown, SIGNAL(currentIndexChanged(int)), this, SLOT(channelDropdownUpdated(int))); - connect(ui->channelNumber, SIGNAL(valueChanged(int)), this, SLOT(channelNumberUpdated(int))); - disableMouseWheelEvents(); } - InputChannelForm::~InputChannelForm() { delete ui; } -void InputChannelForm::setName(QString &name) +QString InputChannelForm::name() +{ + return ui->channelName->text(); +} + +/** + * Set the channel assignment label. + */ +void InputChannelForm::setName(const QString &name) { ui->channelName->setText(name); - QFontMetrics metrics(ui->channelName->font()); - int width = metrics.width(name) + 5; - foreach(InputChannelForm * form, parent()->findChildren()) { - if (form == this) { - continue; - } - if (form->ui->channelName->minimumSize().width() < width) { - form->ui->channelName->setMinimumSize(width, 0); - } else { - width = form->ui->channelName->minimumSize().width(); - } - } - ui->channelName->setMinimumSize(width, 0); } /** @@ -136,8 +103,8 @@ void InputChannelForm::reversedUpdated() */ void InputChannelForm::groupUpdated() { - ui->channelNumberDropdown->clear(); - ui->channelNumberDropdown->addItem("Disabled"); + ui->channelNumber->clear(); + ui->channelNumber->addItem("Disabled"); quint8 count = 0; @@ -168,25 +135,6 @@ void InputChannelForm::groupUpdated() } for (int i = 0; i < count; i++) { - ui->channelNumberDropdown->addItem(QString(tr("Chan %1").arg(i + 1))); + ui->channelNumber->addItem(QString(tr("Chan %1").arg(i + 1))); } - - ui->channelNumber->setMaximum(count); - ui->channelNumber->setMinimum(0); -} - -/** - * Update the dropdown from the hidden control - */ -void InputChannelForm::channelDropdownUpdated(int newval) -{ - ui->channelNumber->setValue(newval); -} - -/** - * Update the hidden control from the dropdown - */ -void InputChannelForm::channelNumberUpdated(int newval) -{ - ui->channelNumberDropdown->setCurrentIndex(newval); } diff --git a/ground/openpilotgcs/src/plugins/config/inputchannelform.h b/ground/openpilotgcs/src/plugins/config/inputchannelform.h index 91d665b40..f48bcbd0a 100644 --- a/ground/openpilotgcs/src/plugins/config/inputchannelform.h +++ b/ground/openpilotgcs/src/plugins/config/inputchannelform.h @@ -1,27 +1,32 @@ #ifndef INPUTCHANNELFORM_H #define INPUTCHANNELFORM_H -#include +#include "channelform.h" #include "configinputwidget.h" + +#include + namespace Ui { class InputChannelForm; } -class InputChannelForm : public ConfigTaskWidget { +class InputChannelForm : public ChannelForm { Q_OBJECT public: - explicit InputChannelForm(QWidget *parent = 0, bool showlegend = false); + explicit InputChannelForm(const int index, QWidget *parent = NULL); ~InputChannelForm(); + friend class ConfigInputWidget; - void setName(QString &name); + + virtual QString name(); + virtual void setName(const QString &name); + private slots: void minMaxUpdated(); void neutralUpdated(); void reversedUpdated(); void groupUpdated(); - void channelDropdownUpdated(int); - void channelNumberUpdated(int); private: Ui::InputChannelForm *ui; diff --git a/ground/openpilotgcs/src/plugins/config/inputchannelform.ui b/ground/openpilotgcs/src/plugins/config/inputchannelform.ui index d07f2ae3b..2f4db720c 100644 --- a/ground/openpilotgcs/src/plugins/config/inputchannelform.ui +++ b/ground/openpilotgcs/src/plugins/config/inputchannelform.ui @@ -6,8 +6,8 @@ 0 0 - 828 - 93 + 923 + 51 @@ -24,268 +24,18 @@ 0 - 6 + 0 + + + 12 - - - - true - - - - 0 - 0 - - - - - 0 - 20 - - - - - 75 - false - true - - - - Channel neutral - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); -color: rgb(255, 255, 255); -border-radius: 5; -margin:1px; -font:bold; - - - QFrame::StyledPanel - - - Neutral - - - Qt::AlignCenter - - - - - - - - 0 - 25 - - - - Qt::StrongFocus - - - QAbstractSpinBox::UpDownArrows - - - 9999 - - - 1000 - - - - - - - true - - - - 0 - 0 - - - - - 30 - 20 - - - - - 75 - false - true - - - - Response time - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); -color: rgb(255, 255, 255); -border-radius: 5; -margin:1px; -font:bold; - - - QFrame::StyledPanel - - - 1 - - - RT - - - Qt::AlignCenter - - - - - - - true - - - - 0 - 0 - - - - - 75 - 20 - - - - - 75 - false - true - - - - Channel values are inverted - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); -color: rgb(255, 255, 255); -border-radius: 5; -margin:1px; -font:bold; - - - QFrame::StyledPanel - - - 1 - - - Reversed - - - Qt::AlignCenter - - - - - - - true - - - - 0 - 0 - - - - - 0 - 20 - - - - - 75 - false - true - - - - Channel function - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); -color: rgb(255, 255, 255); -border-radius: 5; -margin:1px; -font:bold; - - - QFrame::StyledPanel - - - Function - - - Qt::AlignCenter - - - - - - - true - - - - 0 - 0 - - - - - 0 - 20 - - - - - 75 - false - true - - - - Channel type - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); -color: rgb(255, 255, 255); -border-radius: 5; -margin:1px; -font:bold; - - - QFrame::StyledPanel - - - Type - - - Qt::AlignCenter - - - true - + 0 0 @@ -298,6 +48,7 @@ font:bold; + -1 75 false true @@ -310,8 +61,8 @@ font:bold; background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); color: rgb(255, 255, 255); border-radius: 5; -margin:1px; -font:bold; +font: bold 12px; +margin:1px; QFrame::StyledPanel @@ -324,133 +75,47 @@ font:bold; - - - - true + + + + Qt::Horizontal - - - 0 - 0 - + + QSizePolicy::Fixed - + - 0 + 10 20 - - - 75 - false - true - - - - Channel min - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); -color: rgb(255, 255, 255); -border-radius: 5; -margin:1px; -font:bold; - - - QFrame::StyledPanel - - - Min - - - Qt::AlignCenter - - + - - + + - + 0 0 - - - 80 - 25 - - - - TextLabel - - - - - - - - 4 - 0 - - 0 - 25 + 0 - 90 + 16777215 16777215 Qt::StrongFocus - - 7 - - - - - - - - 6 - 0 - - - - - 0 - 25 - - - - - 100 - 16777215 - - - - Qt::StrongFocus - - - - - - - - 0 - 25 - - - - Qt::StrongFocus + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter QAbstractSpinBox::UpDownArrows @@ -463,123 +128,111 @@ font:bold; - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 10 - 20 - - - - - - - - true - + + - + 0 0 - 0 - 20 + 110 + 0 - - - 75 - false - true - - - - Channel max - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); -color: rgb(255, 255, 255); -border-radius: 5; -margin:1px; -font:bold; - - - QFrame::StyledPanel - - - 1 - - - Max - - - Qt::AlignCenter - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - + - 10 - 20 - - - - - - - - - 0 - 0 - - - - - 0 - 22 + 16777215 + 16777215 Qt::StrongFocus - - Qt::Horizontal + + QComboBox::AdjustToContents - - - - true - + + - + 0 0 - 30 - 25 + 100 + 0 + + + + + 16777215 + 16777215 + + + + Qt::StrongFocus + + + 7 + + + QComboBox::AdjustToContents + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 16777215 + 16777215 + + + + Text + + + + + + + true + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 16777215 @@ -598,6 +251,9 @@ even lead to crash. Use with caution. true + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + QAbstractSpinBox::UpDownArrows @@ -606,21 +262,544 @@ even lead to crash. Use with caution. - + + + + true + + + + 0 + 0 + + + + + 0 + 20 + + + + + -1 + 75 + false + true + + + + Channel function + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + QFrame::StyledPanel + + + Function + + + Qt::AlignCenter + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 10 + 20 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 10 + 20 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 10 + 20 + + + + + + + + true + + + + 0 + 0 + + + + + 0 + 20 + + + + + -1 + 75 + false + true + + + + Channel values are inverted + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + QFrame::StyledPanel + + + 1 + + + Reversed + + + Qt::AlignCenter + + + + + + + true + + + + 0 + 0 + + + + + 0 + 20 + + + + + -1 + 75 + false + true + + + + Response time + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + QFrame::StyledPanel + + + 1 + + + RT + + + Qt::AlignCenter + + + + + + + true + + + + 0 + 0 + + + + + 0 + 20 + + + + + -1 + 75 + false + true + + + + Channel max + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + QFrame::StyledPanel + + + 1 + + + Max + + + Qt::AlignCenter + + + + + + + true + + + + 0 + 0 + + + + + 0 + 20 + + + + + -1 + 75 + false + true + + + + Channel neutral + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + QFrame::StyledPanel + + + Neutral + + + Qt::AlignCenter + + + + + + + true + + + + 0 + 0 + + + + + 0 + 20 + + + + + -1 + 75 + false + true + + + + Channel min + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + QFrame::StyledPanel + + + Min + + + Qt::AlignCenter + + + + + + + true + + + + 0 + 0 + + + + + 0 + 20 + + + + + -1 + 75 + false + true + + + + Channel type + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + QFrame::StyledPanel + + + Type + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + Qt::StrongFocus + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + QAbstractSpinBox::UpDownArrows + + + 9999 + + + 1000 + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + QFrame::NoFrame + + + QFrame::Plain + + + + 2 + + + 0 + + + 2 + + + 0 + + + + + + 0 + 0 + + + + + 50 + 0 + + + + Qt::StrongFocus + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 9999 + + + 1000 + + + + + + + + + + + 0 + 0 + + 75 0 + + + 16777215 + 16777215 + + QFrame::NoFrame QFrame::Raised - + 0 @@ -633,15 +812,21 @@ even lead to crash. Use with caution. 0 - + true + + + 0 + 0 + + 0 - 20 + 0 @@ -652,51 +837,8 @@ even lead to crash. Use with caution. - - - - - 0 - 25 - - - - 9999 - - - 1000 - - - - - - true - - - - 216 - 26 - 0 - 0 - - - - - 0 - 0 - - - - - channelNumber - channelGroup - channelNumberDropdown - channelMin - channelNeutral - channelMax - diff --git a/ground/openpilotgcs/src/plugins/config/output.ui b/ground/openpilotgcs/src/plugins/config/output.ui index aa2f892c7..575b03e58 100644 --- a/ground/openpilotgcs/src/plugins/config/output.ui +++ b/ground/openpilotgcs/src/plugins/config/output.ui @@ -122,8 +122,8 @@ 0 0 - 676 - 674 + 674 + 677 @@ -654,41 +654,46 @@ Leave at 50Hz for fixed wing. - - - QLayout::SetDefaultConstraint + + + 12 - - - - - - 519 - 20 - - - - Motors spin at neutral output when armed and throttle below zero (be careful) - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 10 + + + + + + + + + 0 + 0 + + + + + 519 + 20 + + + + Motors spin at neutral output when armed and throttle below zero (be careful) + + diff --git a/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp b/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp index a69a88bf9..0ca1ecaf7 100644 --- a/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp +++ b/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp @@ -26,52 +26,24 @@ */ #include "outputchannelform.h" -#include "configoutputwidget.h" -OutputChannelForm::OutputChannelForm(const int index, QWidget *parent, const bool showLegend) : - ConfigTaskWidget(parent), - ui(), - m_index(index), - m_inChannelTest(false) +OutputChannelForm::OutputChannelForm(const int index, QWidget *parent) : + ChannelForm(index, parent), ui(), m_inChannelTest(false) { ui.setupUi(this); - if (!showLegend) { - // Remove legend - QGridLayout *grid_layout = dynamic_cast(layout()); - Q_ASSERT(grid_layout); - for (int col = 0; col < grid_layout->columnCount(); col++) { // remove every item in first row - QLayoutItem *item = grid_layout->itemAtPosition(0, col); - if (!item) { - continue; - } - // get widget from layout item - QWidget *legend_widget = item->widget(); - if (!legend_widget) { - continue; - } - // delete widget - grid_layout->removeWidget(legend_widget); - delete legend_widget; - } - } // The convention for OP is Channel 1 to Channel 10. - ui.actuatorNumber->setText(QString("%1:").arg(m_index + 1)); + ui.actuatorNumber->setText(QString("%1:").arg(index + 1)); // Register for ActuatorSettings changes: - connect(ui.actuatorMin, SIGNAL(editingFinished()), - this, SLOT(setChannelRange())); - connect(ui.actuatorMax, SIGNAL(editingFinished()), - this, SLOT(setChannelRange())); - connect(ui.actuatorRev, SIGNAL(toggled(bool)), - this, SLOT(reverseChannel(bool))); + connect(ui.actuatorMin, SIGNAL(editingFinished()), this, SLOT(setChannelRange())); + connect(ui.actuatorMax, SIGNAL(editingFinished()), this, SLOT(setChannelRange())); + connect(ui.actuatorRev, SIGNAL(toggled(bool)), this, SLOT(reverseChannel(bool))); // Now connect the channel out sliders to our signal to send updates in test mode - connect(ui.actuatorNeutral, SIGNAL(valueChanged(int)), - this, SLOT(sendChannelTest(int))); + connect(ui.actuatorNeutral, SIGNAL(valueChanged(int)), this, SLOT(sendChannelTest(int))); ui.actuatorLink->setChecked(false); - connect(ui.actuatorLink, SIGNAL(toggled(bool)), - this, SLOT(linkToggled(bool))); + connect(ui.actuatorLink, SIGNAL(toggled(bool)), this, SLOT(linkToggled(bool))); disableMouseWheelEvents(); } @@ -81,6 +53,19 @@ OutputChannelForm::~OutputChannelForm() // Do nothing } +QString OutputChannelForm::name() +{ + return ui.actuatorName->text(); +} + +/** + * Set the channel assignment label. + */ +void OutputChannelForm::setName(const QString &name) +{ + ui.actuatorName->setText(name); +} + /** * Restrict UI to protect users from accidental misuse. */ @@ -149,26 +134,49 @@ void OutputChannelForm::linkToggled(bool state) } } +int OutputChannelForm::max() const +{ + return ui.actuatorMax->value(); +} + /** * Set maximal channel value. */ -void OutputChannelForm::max(int maximum) +void OutputChannelForm::setMax(int maximum) { - minmax(ui.actuatorMin->value(), maximum); + setRange(ui.actuatorMin->value(), maximum); +} + +int OutputChannelForm::min() const +{ + return ui.actuatorMin->value(); } /** * Set minimal channel value. */ -void OutputChannelForm::min(int minimum) +void OutputChannelForm::setMin(int minimum) { - minmax(minimum, ui.actuatorMax->value()); + setRange(minimum, ui.actuatorMax->value()); +} + +int OutputChannelForm::neutral() const +{ + return ui.actuatorNeutral->value(); +} + +/** + * Set neutral of channel. + */ +void OutputChannelForm::setNeutral(int value) +{ + ui.actuatorNeutral->setValue(value); } /** * Set minimal and maximal channel value. */ -void OutputChannelForm::minmax(int minimum, int maximum) +void OutputChannelForm::setRange(int minimum, int maximum) { ui.actuatorMin->setValue(minimum); ui.actuatorMax->setValue(maximum); @@ -180,35 +188,6 @@ void OutputChannelForm::minmax(int minimum, int maximum) } } -/** - * Set neutral of channel. - */ -void OutputChannelForm::neutral(int value) -{ - ui.actuatorNeutral->setValue(value); -} - -/** - * Set the channel assignment label. - */ -void OutputChannelForm::setAssignment(const QString &assignment) -{ - ui.actuatorName->setText(assignment); - QFontMetrics metrics(ui.actuatorName->font()); - int width = metrics.width(assignment) + 1; - foreach(OutputChannelForm * form, parent()->findChildren()) { - if (form == this) { - continue; - } - if (form->ui.actuatorName->minimumSize().width() < width) { - form->ui.actuatorName->setMinimumSize(width, 0); - } else { - width = form->ui.actuatorName->minimumSize().width(); - } - } - ui.actuatorName->setMinimumSize(width, 0); -} - /** * Sets the minimum/maximum value of the channel output sliders. * Have to do it here because setMinimum is not a slot. @@ -220,7 +199,7 @@ void OutputChannelForm::setChannelRange() { int oldMini = ui.actuatorNeutral->minimum(); -// int oldMaxi = ui.actuatorNeutral->maximum(); + // int oldMaxi = ui.actuatorNeutral->maximum(); if (ui.actuatorMin->value() < ui.actuatorMax->value()) { ui.actuatorNeutral->setRange(ui.actuatorMin->value(), ui.actuatorMax->value()); @@ -234,8 +213,9 @@ void OutputChannelForm::setChannelRange() ui.actuatorNeutral->setValue(ui.actuatorNeutral->minimum()); } -// if (ui.actuatorNeutral->value() == oldMaxi) -// ui.actuatorNeutral->setValue(ui.actuatorNeutral->maximum()); // this can be dangerous if it happens to be controlling a motor at the time! + // if (ui.actuatorNeutral->value() == oldMaxi) + // this can be dangerous if it happens to be controlling a motor at the time! + // ui.actuatorNeutral->setValue(ui.actuatorNeutral->maximum()); } /** @@ -252,8 +232,7 @@ void OutputChannelForm::reverseChannel(bool state) return; } - // Now, swap the min & max values (only on the spinboxes, the slider - // does not change! + // Now, swap the min & max values (only on the spinboxes, the slider does not change!) int temp = ui.actuatorMax->value(); ui.actuatorMax->setValue(ui.actuatorMin->value()); ui.actuatorMin->setValue(temp); @@ -286,12 +265,14 @@ void OutputChannelForm::sendChannelTest(int value) } if (ui.actuatorRev->isChecked()) { - value = ui.actuatorMin->value() - value + ui.actuatorMax->value(); // the channel is reversed + // the channel is reversed + value = ui.actuatorMin->value() - value + ui.actuatorMax->value(); } // update the label - ui.actuatorValue->setText(QString::number(value)); + ui.actuatorValue->setValue(value); - if (ui.actuatorLink->checkState() && parent()) { // the channel is linked to other channels + if (ui.actuatorLink->checkState() && parent()) { + // the channel is linked to other channels QList outputChannelForms = parent()->findChildren(); // set the linked channels of the parent widget to the same value foreach(OutputChannelForm * outputChannelForm, outputChannelForms) { @@ -315,12 +296,13 @@ void OutputChannelForm::sendChannelTest(int value) } outputChannelForm->ui.actuatorNeutral->setValue(val); - outputChannelForm->ui.actuatorValue->setText(QString::number(val)); + outputChannelForm->ui.actuatorValue->setValue(val); } } if (!m_inChannelTest) { - return; // we are not in Test Output mode + // we are not in Test Output mode + return; } emit channelChanged(index(), value); } diff --git a/ground/openpilotgcs/src/plugins/config/outputchannelform.h b/ground/openpilotgcs/src/plugins/config/outputchannelform.h index a537f55e7..78d008115 100644 --- a/ground/openpilotgcs/src/plugins/config/outputchannelform.h +++ b/ground/openpilotgcs/src/plugins/config/outputchannelform.h @@ -27,29 +27,32 @@ #ifndef OUTPUTCHANNELFORM_H #define OUTPUTCHANNELFORM_H -#include +#include "channelform.h" +#include "configoutputwidget.h" #include "ui_outputchannelform.h" -#include "configtaskwidget.h" -class OutputChannelForm : public ConfigTaskWidget { +#include + +class OutputChannelForm : public ChannelForm { Q_OBJECT public: - explicit OutputChannelForm(const int index, QWidget *parent = NULL, const bool showLegend = false); + explicit OutputChannelForm(const int index, QWidget *parent = NULL); ~OutputChannelForm(); + friend class ConfigOutputWidget; - void setAssignment(const QString &assignment); - int index() const; + virtual QString name(); + virtual void setName(const QString &name); public slots: - void max(int maximum); - int max() const; - void min(int minimum); int min() const; - void minmax(int minimum, int maximum); - void neutral(int value); + void setMin(int minimum); + int max() const; + void setMax(int maximum); int neutral() const; + void setNeutral(int value); + void setRange(int minimum, int maximum); void enableChannelTest(bool state); signals: @@ -57,8 +60,6 @@ signals: private: Ui::outputChannelForm ui; - /// Channel index - int m_index; bool m_inChannelTest; private slots: @@ -68,23 +69,4 @@ private slots: void setChannelRange(); }; -inline int OutputChannelForm::index() const -{ - return m_index; -} - -inline int OutputChannelForm::max() const -{ - return ui.actuatorMax->value(); -} - -inline int OutputChannelForm::min() const -{ - return ui.actuatorMin->value(); -} - -inline int OutputChannelForm::neutral() const -{ - return ui.actuatorNeutral->value(); -} #endif // OUTPUTCHANNELFORM_H diff --git a/ground/openpilotgcs/src/plugins/config/outputchannelform.ui b/ground/openpilotgcs/src/plugins/config/outputchannelform.ui index abe5d04dd..f6227939a 100644 --- a/ground/openpilotgcs/src/plugins/config/outputchannelform.ui +++ b/ground/openpilotgcs/src/plugins/config/outputchannelform.ui @@ -6,39 +6,52 @@ 0 0 - 825 - 58 + 768 + 51 Form + + 0 + - 1 + 0 + + + 0 - 1 + 0 12 - - + + - + 0 0 - 45 + 0 20 + + + 16777215 + 16777215 + + + -1 75 false true @@ -48,37 +61,61 @@ background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); color: rgb(255, 255, 255); border-radius: 5; -font:bold; +font: bold 12px; margin:1px; - Link + Assignment Qt::AlignCenter - - + + + + + 0 + 0 + + 0 - 25 + 20 - - Qt::StrongFocus + + + 16777215 + 16777215 + - - Maximum PWM value, beware of not overdriving your servo. + + + -1 + 75 + false + true + - - 9999 + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + Min + + + Qt::AlignCenter - + @@ -94,6 +131,7 @@ margin:1px; + -1 75 false true @@ -103,7 +141,7 @@ margin:1px; background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); color: rgb(255, 255, 255); border-radius: 5; -font:bold; +font: bold 12px; margin:1px; @@ -114,10 +152,26 @@ margin:1px; + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 5 + 20 + + + + - + 0 0 @@ -128,8 +182,15 @@ margin:1px; 20 + + + 16777215 + 16777215 + + + -1 75 false true @@ -142,7 +203,7 @@ margin:1px; background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); color: rgb(255, 255, 255); border-radius: 5; -font:bold; +font: bold 12px; margin:1px; @@ -156,13 +217,13 @@ margin:1px; - - + + Qt::Horizontal - QSizePolicy::Minimum + QSizePolicy::Fixed @@ -172,10 +233,42 @@ margin:1px; - - + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 5 + 20 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 5 + 20 + + + + + + - + 0 0 @@ -183,37 +276,13 @@ margin:1px; 0 - 20 + 0 - - - 75 - false - true - - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); -color: rgb(255, 255, 255); -border-radius: 5; -font:bold; -margin:1px; - - - Assignment - - - Qt::AlignCenter - - - - - - + - 0 - 25 + 16777215 + 16777215 @@ -222,69 +291,14 @@ margin:1px; Minimum PWM value, beware of not overdriving your servo. - - 9999 - - - - - - - - 0 - 0 - - - - - 0 - 25 - - - - Qt::StrongFocus - - - 9999 - - - Qt::Horizontal - - - - - - - - 0 - 0 - - - - - 0 - 20 - - - - - 75 - false - true - - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); -color: rgb(255, 255, 255); -border-radius: 5; -font:bold; -margin:1px; - - - Max - - Qt::AlignCenter + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 9999 + + + 0 @@ -299,35 +313,154 @@ margin:1px; 20 - 25 + 0 + + + + + 16777215 + 16777215 Channel Number - TextLabel + 0: Qt::AlignCenter - - - - Qt::Horizontal + + + + + 0 + 0 + - - QSizePolicy::Minimum - - + - 5 + 0 20 - + + + 16777215 + 16777215 + + + + + -1 + 75 + false + true + + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + Max + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 20 + + + + + 16777215 + 16777215 + + + + + -1 + 75 + false + true + + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + Reversed + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 20 + + + + + 16777215 + 16777215 + + + + + -1 + 75 + false + true + + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + Link + + + Qt::AlignCenter + + @@ -340,21 +473,27 @@ margin:1px; 110 - 25 + 0 + + + + + 16777215 + 16777215 - TextLabel + - Qt::AlignCenter - - + + - + 0 0 @@ -362,98 +501,133 @@ margin:1px; 0 - 20 + 0 - - - 75 - false - true - + + + 16777215 + 16777215 + - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); -color: rgb(255, 255, 255); -border-radius: 5; -font:bold; -margin:1px; + + Qt::StrongFocus - - Reversed + + Maximum PWM value, beware of not overdriving your servo. - Qt::AlignCenter + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 9999 - - + + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 2 + + + 0 + + + 2 + + + 0 + + + + + + 0 + 0 + + + + + 50 + 0 + + + + Qt::StrongFocus + + + 9999 + + + Qt::Horizontal + + + + + + + true + + + + 0 + 0 + + + + true + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + true + + + QAbstractSpinBox::UpDownArrows + + + 9999 + + + + + + + + 0 0 - - - 0 - 25 - - - - Current value of slider. - - - 0000 - - - - - - - - 0 - 0 - - - - - 0 - 20 - - - - - 75 - false - true - - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); -color: rgb(255, 255, 255); -border-radius: 5; -font:bold; -margin:1px; - - - Min - - - Qt::AlignCenter - - - - - 75 0 - + + QFrame::NoFrame + + + + 0 + 0 @@ -466,13 +640,10 @@ margin:1px; 0 - - 0 - - + - + 0 0 @@ -494,8 +665,14 @@ margin:1px; - - + + + + + 0 + 0 + + 45 @@ -506,9 +683,12 @@ margin:1px; QFrame::NoFrame - QFrame::Raised + QFrame::Plain - + + + 0 + 0 @@ -521,13 +701,10 @@ margin:1px; 0 - - 0 - - + - + 0 0 @@ -551,11 +728,6 @@ margin:1px; - - actuatorMin - actuatorNeutral - actuatorMax - diff --git a/ground/openpilotgcs/src/plugins/coreplugin/mainwindow.cpp b/ground/openpilotgcs/src/plugins/coreplugin/mainwindow.cpp index 12b89cd46..81817c5d1 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/mainwindow.cpp +++ b/ground/openpilotgcs/src/plugins/coreplugin/mainwindow.cpp @@ -270,7 +270,7 @@ void MainWindow::extensionsInitialized() // We'll use qApp macro to get the QApplication pointer // and set the style sheet application wide. - qDebug() << "Setting application style sheet to:" << style; + // qDebug() << "Setting application style sheet to:" << style; qApp->setStyleSheet(style); qs->endGroup(); diff --git a/ground/openpilotgcs/src/plugins/hitl/fgsimulator.cpp b/ground/openpilotgcs/src/plugins/hitl/fgsimulator.cpp index 1b4b2a8da..eb53b75fb 100644 --- a/ground/openpilotgcs/src/plugins/hitl/fgsimulator.cpp +++ b/ground/openpilotgcs/src/plugins/hitl/fgsimulator.cpp @@ -268,12 +268,12 @@ void FGSimulator::processUpdate(const QByteArray & inp) float temperature = fields[19].toFloat(); // Get pressure (kpa) float pressure = fields[20].toFloat() * INHG2KPA; - // Get VelocityState Down (cm/s) - float velocityStateDown = -fields[21].toFloat() * FPS2CMPS; - // Get VelocityState East (cm/s) - float velocityStateEast = fields[22].toFloat() * FPS2CMPS; - // Get VelocityState Down (cm/s) - float velocityStateNorth = fields[23].toFloat() * FPS2CMPS; + // Get VelocityState Down (m/s) + float velocityStateDown = -fields[21].toFloat() * FPS2CMPS * 1e-2f; + // Get VelocityState East (m/s) + float velocityStateEast = fields[22].toFloat() * FPS2CMPS * 1e-2f; + // Get VelocityState Down (m/s) + float velocityStateNorth = fields[23].toFloat() * FPS2CMPS * 1e-2f; // Get UDP packets received by FG int n = fields[24].toInt(); @@ -286,16 +286,15 @@ void FGSimulator::processUpdate(const QByteArray & inp) Output2Hardware out; memset(&out, 0, sizeof(Output2Hardware)); + HomeLocation::DataFields homeData = posHome->getData(); + double HomeLLA[3] = { (double)homeData.Latitude * 1e-7, (double)homeData.Longitude * 1e-7, homeData.Altitude }; + double HomeECEF[3]; + float HomeRNE[3][3]; + double LLA[3] = { latitude, longitude, altitude_msl }; float NED[3]; - // convert from cm back to meters - - double LLA[3] = { latitude, longitude, altitude_msl }; - double ECEF[3]; - double RNE[9]; - Utils::CoordinateConversions().RneFromLLA(LLA, (double(*)[3])RNE); - Utils::CoordinateConversions().LLA2ECEF(LLA, ECEF); - Utils::CoordinateConversions().LLA2Base(LLA, ECEF, (float(*)[3])RNE, NED); - + Utils::CoordinateConversions().RneFromLLA(HomeLLA, HomeRNE); + Utils::CoordinateConversions().LLA2ECEF(HomeLLA, HomeECEF); + Utils::CoordinateConversions().LLA2Base(LLA, HomeECEF, HomeRNE, NED); // Update GPS Position objects out.latitude = latitude * 1e7; diff --git a/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.cpp b/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.cpp index 235448a57..1ab86536a 100644 --- a/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.cpp +++ b/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.cpp @@ -199,14 +199,14 @@ void UAVObjectField::limitsInitialize(const QString &limits) elementLimits.insert(index, limitList); ++index; } - foreach(QList limitList, elementLimits) { - foreach(LimitStruct limit, limitList) { - qDebug() << "Limit type" << limit.type << "for board" << limit.board << "for field" << getName(); - foreach(QVariant var, limit.values) { - qDebug() << "value" << var; - } - } - } + // foreach(QList limitList, elementLimits) { + // foreach(LimitStruct limit, limitList) { + // qDebug() << "Limit type" << limit.type << "for board" << limit.board << "for field" << getName(); + // foreach(QVariant var, limit.values) { + // qDebug() << "value" << var; + // } + // } + // } } bool UAVObjectField::isWithinLimits(QVariant var, quint32 index, int board) { @@ -811,43 +811,31 @@ bool UAVObjectField::isNumeric() { switch (type) { case INT8: - return true; - - break; case INT16: - return true; - - break; case INT32: - return true; - - break; case UINT8: - return true; - - break; case UINT16: - return true; - - break; case UINT32: - return true; - - break; case FLOAT32: - return true; - - break; - case ENUM: - return false; - - break; case BITFIELD: return true; break; - case STRING: + default: return false; + } +} + +bool UAVObjectField::isInteger() +{ + switch (type) { + case INT8: + case INT16: + case INT32: + case UINT8: + case UINT16: + case UINT32: + return true; break; default: @@ -858,42 +846,7 @@ bool UAVObjectField::isNumeric() bool UAVObjectField::isText() { switch (type) { - case INT8: - return false; - - break; - case INT16: - return false; - - break; - case INT32: - return false; - - break; - case UINT8: - return false; - - break; - case UINT16: - return false; - - break; - case UINT32: - return false; - - break; - case FLOAT32: - return false; - - break; case ENUM: - return true; - - break; - case BITFIELD: - return false; - - break; case STRING: return true; diff --git a/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.h b/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.h index 141fa6af7..778096729 100644 --- a/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.h +++ b/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.h @@ -71,6 +71,7 @@ public: quint32 getDataOffset(); quint32 getNumBytes(); bool isNumeric(); + bool isInteger(); bool isText(); QString toString(); void toXML(QXmlStreamWriter *xmlWriter); diff --git a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.cpp b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.cpp index 0dd434c01..6df939d0a 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.cpp +++ b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.cpp @@ -58,7 +58,7 @@ void ConfigTaskWidget::addUAVObject(QString objectName, QList *reloadGroups void ConfigTaskWidget::addUAVObject(UAVObject *objectName, QList *reloadGroups) { - addUAVObject(objectName ? objectName->getName() : QString(""), reloadGroups); + addUAVObject(objectName ? objectName->getName() : QString(), reloadGroups); } int ConfigTaskWidget::fieldIndexFromElementName(QString objectName, QString fieldName, QString elementName) @@ -84,7 +84,7 @@ void ConfigTaskWidget::addWidgetBinding(QString objectName, QString fieldName, Q void ConfigTaskWidget::addWidgetBinding(UAVObject *object, UAVObjectField *field, QWidget *widget, QString elementName) { - addWidgetBinding(object ? object->getName() : QString(""), field ? field->getName() : QString(""), widget, elementName); + addWidgetBinding(object ? object->getName() : QString(), field ? field->getName() : QString(), widget, elementName); } void ConfigTaskWidget::addWidgetBinding(QString objectName, QString fieldName, QWidget *widget, QString elementName, double scale, @@ -97,14 +97,14 @@ void ConfigTaskWidget::addWidgetBinding(QString objectName, QString fieldName, Q void ConfigTaskWidget::addWidgetBinding(UAVObject *object, UAVObjectField *field, QWidget *widget, QString elementName, double scale, bool isLimited, QList *reloadGroupIDs, quint32 instID) { - addWidgetBinding(object ? object->getName() : QString(""), field ? field->getName() : QString(""), widget, elementName, scale, + addWidgetBinding(object ? object->getName() : QString(), field ? field->getName() : QString(), widget, elementName, scale, isLimited, reloadGroupIDs, instID); } void ConfigTaskWidget::addWidgetBinding(UAVObject *object, UAVObjectField *field, QWidget *widget, int index, double scale, bool isLimited, QList *reloadGroupIDs, quint32 instID) { - addWidgetBinding(object ? object->getName() : QString(""), field ? field->getName() : QString(""), widget, index, scale, + addWidgetBinding(object ? object->getName() : QString(), field ? field->getName() : QString(), widget, index, scale, isLimited, reloadGroupIDs, instID); } @@ -146,7 +146,6 @@ void ConfigTaskWidget::doAddWidgetBinding(QString objectName, QString fieldName, binding->setIsEnabled(m_widgetBindingsPerWidget.count(widget) == 0); m_widgetBindingsPerWidget.insert(widget, binding); - if (object) { m_widgetBindingsPerObject.insert(object, binding); if (m_saveButton) { @@ -183,9 +182,9 @@ void ConfigTaskWidget::setWidgetBindingObjectEnabled(QString objectName, bool en binding->setIsEnabled(enabled); if (enabled) { if (binding->value().isValid() && !binding->value().isNull()) { - setWidgetFromVariant(binding->widget(), binding->value(), binding->scale()); + setWidgetFromVariant(binding->widget(), binding->value(), binding); } else { - setWidgetFromField(binding->widget(), binding->field(), binding->index(), binding->scale(), binding->isLimited()); + setWidgetFromField(binding->widget(), binding->field(), binding); } } } @@ -236,7 +235,8 @@ void ConfigTaskWidget::onAutopilotDisconnect() invalidateObjects(); } -void ConfigTaskWidget::forceConnectedState() // dynamic widgets don't recieve the connected signal. This should be called instead. +// dynamic widgets don't recieve the connected signal. This should be called instead. +void ConfigTaskWidget::forceConnectedState() { m_isConnected = true; setDirty(false); @@ -261,7 +261,7 @@ void ConfigTaskWidget::populateWidgets() foreach(WidgetBinding * binding, m_widgetBindingsPerObject) { if (binding->isEnabled() && binding->object() != NULL && binding->field() != NULL && binding->widget() != NULL) { - setWidgetFromField(binding->widget(), binding->field(), binding->index(), binding->scale(), binding->isLimited()); + setWidgetFromField(binding->widget(), binding->field(), binding); } } setDirty(dirtyBack); @@ -277,7 +277,7 @@ void ConfigTaskWidget::refreshWidgetsValues(UAVObject *obj) emit refreshWidgetsValuesRequested(); foreach(WidgetBinding * binding, m_widgetBindingsPerObject.values(obj)) { if (binding->isEnabled() && binding->field() != NULL && binding->widget() != NULL) { - setWidgetFromField(binding->widget(), binding->field(), binding->index(), binding->scale(), binding->isLimited()); + setWidgetFromField(binding->widget(), binding->field(), binding); } } setDirty(dirtyBack); @@ -357,13 +357,15 @@ void ConfigTaskWidget::forceShadowUpdates() if (!binding->isEnabled()) { continue; } - QVariant widgetValue = getVariantFromWidget(binding->widget(), binding->scale(), binding->units()); + QVariant widgetValue = getVariantFromWidget(binding->widget(), binding); foreach(ShadowWidgetBinding * shadow, binding->shadows()) { disconnectWidgetUpdatesToSlot(shadow->widget(), SLOT(widgetsContentsChanged())); checkWidgetsLimits(shadow->widget(), binding->field(), binding->index(), shadow->isLimited(), widgetValue, shadow->scale()); - setWidgetFromVariant(shadow->widget(), widgetValue, shadow->scale()); + + WidgetBinding tmpBinding(shadow->widget(), binding->object(), binding->field(), binding->index(), shadow->scale(), shadow->isLimited()); + setWidgetFromVariant(shadow->widget(), widgetValue, &tmpBinding); emit widgetContentsChanged(shadow->widget()); connectWidgetUpdatesToSlot(shadow->widget(), SLOT(widgetsContentsChanged())); @@ -376,25 +378,23 @@ void ConfigTaskWidget::widgetsContentsChanged() { QWidget *emitter = ((QWidget *)sender()); emit widgetContentsChanged(emitter); - double scale = 1.0; QVariant value; foreach(WidgetBinding * binding, m_widgetBindingsPerWidget.values(emitter)) { if (binding && binding->isEnabled()) { if (binding->widget() == emitter) { - scale = binding->scale(); - checkWidgetsLimits(emitter, binding->field(), binding->index(), binding->isLimited(), - getVariantFromWidget(emitter, scale, binding->units()), scale); + value = getVariantFromWidget(emitter, binding); + checkWidgetsLimits(emitter, binding->field(), binding->index(), binding->isLimited(), value, binding->scale()); } else { foreach(ShadowWidgetBinding * shadow, binding->shadows()) { if (shadow->widget() == emitter) { - scale = shadow->scale(); - checkWidgetsLimits(emitter, binding->field(), binding->index(), shadow->isLimited(), - getVariantFromWidget(emitter, scale, binding->units()), scale); + WidgetBinding tmpBinding(shadow->widget(), binding->object(), binding->field(), + binding->index(), shadow->scale(), shadow->isLimited()); + value = getVariantFromWidget(emitter, &tmpBinding); + checkWidgetsLimits(emitter, binding->field(), binding->index(), shadow->isLimited(), value, shadow->scale()); } } } - value = getVariantFromWidget(emitter, scale, binding->units()); binding->setValue(value); if (binding->widget() != emitter) { @@ -402,7 +402,7 @@ void ConfigTaskWidget::widgetsContentsChanged() checkWidgetsLimits(binding->widget(), binding->field(), binding->index(), binding->isLimited(), value, binding->scale()); - setWidgetFromVariant(binding->widget(), value, binding->scale()); + setWidgetFromVariant(binding->widget(), value, binding); emit widgetContentsChanged(binding->widget()); connectWidgetUpdatesToSlot(binding->widget(), SLOT(widgetsContentsChanged())); @@ -413,7 +413,8 @@ void ConfigTaskWidget::widgetsContentsChanged() checkWidgetsLimits(shadow->widget(), binding->field(), binding->index(), shadow->isLimited(), value, shadow->scale()); - setWidgetFromVariant(shadow->widget(), value, shadow->scale()); + WidgetBinding tmp(shadow->widget(), binding->object(), binding->field(), binding->index(), shadow->scale(), shadow->isLimited()); + setWidgetFromVariant(shadow->widget(), value, &tmp); emit widgetContentsChanged(shadow->widget()); connectWidgetUpdatesToSlot(shadow->widget(), SLOT(widgetsContentsChanged())); @@ -708,7 +709,7 @@ void ConfigTaskWidget::defaultButtonClicked() continue; } UAVDataObject *temp = ((UAVDataObject *)binding->object())->dirtyClone(); - setWidgetFromField(binding->widget(), temp->getField(binding->field()->getName()), binding->index(), binding->scale(), binding->isLimited()); + setWidgetFromField(binding->widget(), temp->getField(binding->field()->getName()), binding); } } @@ -751,7 +752,7 @@ void ConfigTaskWidget::reloadButtonClicked() if (m_realtimeUpdateTimer->isActive()) { binding->object()->requestUpdate(); if (binding->widget()) { - setWidgetFromField(binding->widget(), binding->field(), binding->index(), binding->scale(), binding->isLimited()); + setWidgetFromField(binding->widget(), binding->field(), binding); } } m_realtimeUpdateTimer->stop(); @@ -823,9 +824,14 @@ void ConfigTaskWidget::disconnectWidgetUpdatesToSlot(QWidget *widget, const char } } -QVariant ConfigTaskWidget::getVariantFromWidget(QWidget *widget, double scale, QString units) +QVariant ConfigTaskWidget::getVariantFromWidget(QWidget *widget, WidgetBinding *binding) { + double scale = binding->scale(); + if (QComboBox * cb = qobject_cast(widget)) { + if (binding->isInteger()) { + return cb->currentIndex(); + } return (QString)cb->currentText(); } else if (QDoubleSpinBox * cb = qobject_cast(widget)) { return (double)(cb->value() * scale); @@ -837,7 +843,7 @@ QVariant ConfigTaskWidget::getVariantFromWidget(QWidget *widget, double scale, Q return (QString)(cb->isChecked() ? "TRUE" : "FALSE"); } else if (QLineEdit * cb = qobject_cast(widget)) { QString value = (QString)cb->displayText(); - if (units == "hex") { + if (binding->units() == "hex") { bool ok; return value.toUInt(&ok, 16); } else { @@ -848,11 +854,18 @@ QVariant ConfigTaskWidget::getVariantFromWidget(QWidget *widget, double scale, Q } } -bool ConfigTaskWidget::setWidgetFromVariant(QWidget *widget, QVariant value, double scale, QString units) +bool ConfigTaskWidget::setWidgetFromVariant(QWidget *widget, QVariant value, WidgetBinding *binding) { + double scale = binding->scale(); + if (QComboBox * cb = qobject_cast(widget)) { - cb->setCurrentIndex(cb->findText(value.toString())); - return true; + bool ok = true; + if (binding->isInteger()) { + cb->setCurrentIndex(value.toInt(&ok)); + } else { + cb->setCurrentIndex(cb->findText(value.toString())); + } + return ok; } else if (QLabel * cb = qobject_cast(widget)) { if (scale == 0) { cb->setText(value.toString()); @@ -875,7 +888,7 @@ bool ConfigTaskWidget::setWidgetFromVariant(QWidget *widget, QVariant value, dou return true; } else if (QLineEdit * cb = qobject_cast(widget)) { if ((scale == 0) || (scale == 1)) { - if (units == "hex") { + if (binding->units() == "hex") { cb->setText(QString::number(value.toUInt(), 16).toUpper()); } else { cb->setText(value.toString()); @@ -889,24 +902,19 @@ bool ConfigTaskWidget::setWidgetFromVariant(QWidget *widget, QVariant value, dou } } -bool ConfigTaskWidget::setWidgetFromVariant(QWidget *widget, QVariant value, double scale) -{ - return setWidgetFromVariant(widget, value, scale, QString("")); -} - -bool ConfigTaskWidget::setWidgetFromField(QWidget *widget, UAVObjectField *field, int index, double scale, bool hasLimits) +bool ConfigTaskWidget::setWidgetFromField(QWidget *widget, UAVObjectField *field, WidgetBinding *binding) { if (!widget || !field) { return false; } if (QComboBox * cb = qobject_cast(widget)) { if (cb->count() == 0) { - loadWidgetLimits(cb, field, index, hasLimits, scale); + loadWidgetLimits(cb, field, binding->index(), binding->isLimited(), binding->scale()); } } - QVariant value = field->getValue(index); - checkWidgetsLimits(widget, field, index, hasLimits, value, scale); - bool result = setWidgetFromVariant(widget, value, scale, field->getUnits()); + QVariant value = field->getValue(binding->index()); + checkWidgetsLimits(widget, field, binding->index(), binding->isLimited(), value, binding->scale()); + bool result = setWidgetFromVariant(widget, value, binding); if (result) { return true; } else { @@ -1070,7 +1078,23 @@ QString WidgetBinding::units() const if (m_field) { return m_field->getUnits(); } - return QString(""); + return QString(); +} + +QString WidgetBinding::type() const +{ + if (m_field) { + return m_field->getTypeAsString(); + } + return QString(); +} + +bool WidgetBinding::isInteger() const +{ + if (m_field) { + return m_field->isInteger(); + } + return false; } UAVObject *WidgetBinding::object() const diff --git a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.h b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.h index dfc9a9c76..6ff337060 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.h +++ b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.h @@ -69,6 +69,8 @@ public: ~WidgetBinding(); QString units() const; + QString type() const; + bool isInteger() const; UAVObject *object() const; UAVObjectField *field() const; int index() const; @@ -219,11 +221,10 @@ private: QString m_outOfLimitsStyle; QTimer *m_realtimeUpdateTimer; - bool setWidgetFromField(QWidget *widget, UAVObjectField *field, int index, double scale, bool hasLimits); + bool setWidgetFromField(QWidget *widget, UAVObjectField *field, WidgetBinding *binding); - QVariant getVariantFromWidget(QWidget *widget, double scale, const QString units); - bool setWidgetFromVariant(QWidget *widget, QVariant value, double scale, QString units); - bool setWidgetFromVariant(QWidget *widget, QVariant value, double scale); + QVariant getVariantFromWidget(QWidget *widget, WidgetBinding *binding); + bool setWidgetFromVariant(QWidget *widget, QVariant value, WidgetBinding *binding); void connectWidgetUpdatesToSlot(QWidget *widget, const char *function); void disconnectWidgetUpdatesToSlot(QWidget *widget, const char *function);