diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index eadd028c0d79f9b5d678f5f7621b9e993b4faae3..443a94c5ed7f1331940d37c4ead6b9f96744d9a7 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -151,7 +151,10 @@ FORMS += src/ui/MainWindow.ui \ src/ui/SlugsPIDControl.ui \ src/ui/SlugsVideoCamControl.ui \ src/ui/SlugsPadCameraControl.ui \ - src/ui/uas/QGCUnconnectedInfoWidget.ui + src/ui/uas/QGCUnconnectedInfoWidget.ui \ + src/ui/designer/QGCToolWidget.ui \ + src/ui/designer/QGCParamSlider.ui \ + src/ui/designer/QGCActionButton.ui INCLUDEPATH += src \ src/ui \ @@ -166,7 +169,8 @@ INCLUDEPATH += src \ src/ui/mavlink \ src/ui/param \ src/ui/watchdog \ - src/ui/map3D + src/ui/map3D \ + src/ui/designer HEADERS += src/MG.h \ src/Core.h \ @@ -252,7 +256,11 @@ HEADERS += src/MG.h \ src/ui/SlugsPadCameraControl.h \ src/ui/QGCMainWindowAPConfigurator.h \ src/comm/MAVLinkSwarmSimulationLink.h \ - src/ui/uas/QGCUnconnectedInfoWidget.h + src/ui/uas/QGCUnconnectedInfoWidget.h \ + src/ui/designer/QGCToolWidget.h \ + src/ui/designer/QGCParamSlider.h \ + src/ui/designer/QGCActionButton.h \ + src/ui/designer/QGCToolWidgetItem.h # Google Earth is only supported on Mac OS and Windows with Visual Studio Compiler macx|win32-msvc2008: { @@ -369,7 +377,11 @@ SOURCES += src/main.cc \ src/ui/SlugsPadCameraControl.cpp \ src/ui/QGCMainWindowAPConfigurator.cc \ src/comm/MAVLinkSwarmSimulationLink.cc \ - src/ui/uas/QGCUnconnectedInfoWidget.cc + src/ui/uas/QGCUnconnectedInfoWidget.cc \ + src/ui/designer/QGCToolWidget.cc \ + src/ui/designer/QGCParamSlider.cc \ + src/ui/designer/QGCActionButton.cc \ + src/ui/designer/QGCToolWidgetItem.cc macx|win32-msvc2008: { SOURCES += src/ui/map3D/QGCGoogleEarthView.cc diff --git a/src/uas/UAS.cc b/src/uas/UAS.cc index a7510d4bbbfcb4272e8d1089b839ac115f2b7968..209838809b435d955968372a4884e106d75ef139 100644 --- a/src/uas/UAS.cc +++ b/src/uas/UAS.cc @@ -86,7 +86,8 @@ UAS::UAS(MAVLinkProtocol* protocol, int id) : UASInterface(), roll(0.0), pitch(0.0), yaw(0.0), - statusTimeout(new QTimer(this)) + statusTimeout(new QTimer(this)), + paramsOnceRequested(false) { color = UASInterface::getNextColor(); setBattery(LIPOLY, 3); @@ -356,7 +357,7 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message) { mavlink_global_position_int_t pos; mavlink_msg_global_position_int_decode(&message, &pos); - quint64 time = QGC::groundTimeUsecs(); + quint64 time = QGC::groundTimeUsecs()/1000; latitude = pos.lat/(double)1E7; longitude = pos.lon/(double)1E7; altitude = pos.alt/1000.0; @@ -474,7 +475,23 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message) { mavlink_param_value_t value; mavlink_msg_param_value_decode(&message, &value); - emit parameterChanged(uasId, message.compid, QString((char*)value.param_id), value.param_value); + + QString parameterName = QString((char*)value.param_id); + int component = message.compid; + float val = value.param_value; + + // Insert component if necessary + if (!parameters.contains(component)) + { + parameters.insert(component, new QMap()); + } + + // Insert parameter into registry + if (parameters.value(component)->contains(parameterName)) parameters.value(component)->remove(parameterName); + parameters.value(component)->insert(parameterName, val); + + // Emit change + emit parameterChanged(uasId, message.compid, parameterName, val); } break; case MAVLINK_MSG_ID_DEBUG: @@ -820,6 +837,23 @@ quint64 UAS::getUnixTime(quint64 time) } } +QList UAS::getParameterNames(int component) +{ + if (parameters.contains(component)) + { + return parameters.value(component)->keys(); + } + else + { + return QList(); + } +} + +QList UAS::getComponentIds() +{ + return parameters.keys(); +} + void UAS::setMode(int mode) { if ((uint8_t)mode >= MAV_MODE_LOCKED && (uint8_t)mode <= MAV_MODE_RC_TRAINING) diff --git a/src/uas/UAS.h b/src/uas/UAS.h index 7826b819f89d8ee12deccdc6c7b3e6ec3ce5485c..d246b6772a0cd166e6ecef4276edc96cb9cb71d5 100644 --- a/src/uas/UAS.h +++ b/src/uas/UAS.h @@ -153,6 +153,8 @@ protected: double pitch; double yaw; QTimer* statusTimeout; ///< Timer for various status timeouts + QMap* > parameters; ///< All parameters + bool paramsOnceRequested; ///< If the parameter list has been read at least once /** @brief Set the current battery type */ void setBattery(BatteryType type, int cells); @@ -199,7 +201,7 @@ public slots: //void requestWaypoints(); FIXME tbd //void clearWaypointList(); FIXME tbd - void requestParameters(); + /** @brief Enable the motors */ void enable_motors(); /** @brief Disable the motors */ @@ -230,6 +232,9 @@ public slots: /** @brief Set current mode of operation, e.g. auto or manual */ void setMode(int mode); + /** @brief Request all parameters */ + void requestParameters(); + /** @brief Set a system parameter */ void setParameter(int component, QString id, float value); @@ -238,6 +243,12 @@ public slots: /** @brief Read parameters from permanent storage */ void readParametersFromStorage(); + /** @brief Get the names of all parameters */ + QList getParameterNames(int component); + + /** @brief Get the ids of all components */ + QList getComponentIds(); + void enableAllDataTransmission(int rate); void enableRawSensorDataTransmission(int rate); void enableExtendedSystemStatusTransmission(int rate); diff --git a/src/ui/MainWindow.cc b/src/ui/MainWindow.cc index ddad6c027da283c9f15925499f1dd1a09bb92c6c..325f627ab4aa17ca8ac371214b0e00726ddcbbc2 100644 --- a/src/ui/MainWindow.cc +++ b/src/ui/MainWindow.cc @@ -26,6 +26,7 @@ #include "MainWindow.h" #include "JoystickWidget.h" #include "GAudioOutput.h" +#include "QGCToolWidget.h" #ifdef QGC_OSG_ENABLED #include "Q3DWidgetFactory.h" @@ -107,6 +108,8 @@ MainWindow::MainWindow(QWidget *parent): // Create actions connectCommonActions(); + // Add option for custom widgets + connect(ui.actionNewCustomWidget, SIGNAL(triggered()), this, SLOT(createCustomWidget())); // Set dock options setDockOptions(AnimatedDocks | AllowTabbedDocks | AllowNestedDocks); @@ -694,7 +697,16 @@ void MainWindow::connectCommonWidgets() // it notifies that a waypoint global goes to do create and a map graphic too connect(waypointsDockWidget->widget(), SIGNAL(createWaypointAtMap(QPointF)), mapWidget, SLOT(createWaypointGraphAtMap(QPointF))); } +} +void MainWindow::createCustomWidget() +{ + qDebug() << "ADDING CUSTOM WIDGET"; + QGCToolWidget* tool = new QGCToolWidget(this); + QDockWidget* dock = new QDockWidget("Unnamed Tool", this); + dock->setWidget(tool); + this->addDockWidget(Qt::LeftDockWidgetArea, dock); + dock->setVisible(true); } void MainWindow::connectPxWidgets() diff --git a/src/ui/MainWindow.h b/src/ui/MainWindow.h index f866e9a1c6339a393d75d920c39ac639f6a996af..4e4302e753f86cc9001ff274f51c026a49317a05 100644 --- a/src/ui/MainWindow.h +++ b/src/ui/MainWindow.h @@ -140,6 +140,9 @@ public slots: /** @brief Reload the CSS style sheet */ void reloadStylesheet(); + /** @brief Add a custom tool widget */ + void createCustomWidget(); + void closeEvent(QCloseEvent* event); /* diff --git a/src/ui/MainWindow.ui b/src/ui/MainWindow.ui index de35a73d547a73cb8896053fd51a32b07dcd0439..934850a985955e5c8f9a6b0ae5502252eec5f037 100644 --- a/src/ui/MainWindow.ui +++ b/src/ui/MainWindow.ui @@ -38,7 +38,7 @@ 0 0 1000 - 22 + 25 @@ -46,6 +46,7 @@ File + @@ -108,7 +109,6 @@ - @@ -430,6 +430,11 @@ Pilot + + + New Custom Widget + + @@ -454,5 +459,3 @@ - - diff --git a/src/ui/designer/QGCActionButton.cc b/src/ui/designer/QGCActionButton.cc new file mode 100644 index 0000000000000000000000000000000000000000..84c5f2f85f6cd6acc97bba56e4d321713ffab005 --- /dev/null +++ b/src/ui/designer/QGCActionButton.cc @@ -0,0 +1,32 @@ +#include "QGCActionButton.h" +#include "ui_QGCActionButton.h" + +QGCActionButton::QGCActionButton(QWidget *parent) : + QGCToolWidgetItem(parent), + ui(new Ui::QGCActionButton) +{ + ui->setupUi(this); + connect(ui->editFinishButton, SIGNAL(clicked()), this, SLOT(endEditMode())); + endEditMode(); +} + +QGCActionButton::~QGCActionButton() +{ + delete ui; +} + +void QGCActionButton::startEditMode() +{ + ui->editActionComboBox->show(); + ui->editActionsRefreshButton->show(); + ui->editFinishButton->show(); + isInEditMode = true; +} + +void QGCActionButton::endEditMode() +{ + ui->editActionComboBox->hide(); + ui->editActionsRefreshButton->hide(); + ui->editFinishButton->hide(); + isInEditMode = false; +} diff --git a/src/ui/designer/QGCActionButton.h b/src/ui/designer/QGCActionButton.h new file mode 100644 index 0000000000000000000000000000000000000000..63556d6fef07c219543970c07dc1a82fbf1f4410 --- /dev/null +++ b/src/ui/designer/QGCActionButton.h @@ -0,0 +1,26 @@ +#ifndef QGCACTIONBUTTON_H +#define QGCACTIONBUTTON_H + +#include "QGCToolWidgetItem.h" + +namespace Ui { + class QGCActionButton; +} + +class QGCActionButton : public QGCToolWidgetItem +{ + Q_OBJECT + +public: + explicit QGCActionButton(QWidget *parent = 0); + ~QGCActionButton(); + +public slots: + void startEditMode(); + void endEditMode(); + +private: + Ui::QGCActionButton *ui; +}; + +#endif // QGCACTIONBUTTON_H diff --git a/src/ui/designer/QGCActionButton.ui b/src/ui/designer/QGCActionButton.ui new file mode 100644 index 0000000000000000000000000000000000000000..86224813375e7bbba19927aa7660a41f0389c2cf --- /dev/null +++ b/src/ui/designer/QGCActionButton.ui @@ -0,0 +1,99 @@ + + + QGCActionButton + + + + 0 + 0 + 400 + 111 + + + + Form + + + + + + Description + + + + + + + Button name + + + + + + + + + + Refresh Actions + + + + + + + Done + + + + + + + Button name + + + + + + + Description + + + + + + + + + editButtonName + textChanged(QString) + actionButton + setWindowTitle(QString) + + + 310 + 22 + + + 310 + 55 + + + + + editNameLabel + textChanged(QString) + nameLabel + setText(QString) + + + 116 + 22 + + + 116 + 55 + + + + + diff --git a/src/ui/designer/QGCParamSlider.cc b/src/ui/designer/QGCParamSlider.cc index bfaf3e3258757d933c0af29b5760727285802af4..3b8435e8dcb397f97ffcd9ce4aba21a76a0b80df 100644 --- a/src/ui/designer/QGCParamSlider.cc +++ b/src/ui/designer/QGCParamSlider.cc @@ -1,11 +1,16 @@ +#include +#include + #include "QGCParamSlider.h" #include "ui_QGCParamSlider.h" QGCParamSlider::QGCParamSlider(QWidget *parent) : - QWidget(parent), + QGCToolWidgetItem(parent), ui(new Ui::QGCParamSlider) { ui->setupUi(this); + endEditMode(); + connect(ui->doneButton, SIGNAL(clicked()), this, SLOT(endEditMode())); } QGCParamSlider::~QGCParamSlider() @@ -13,6 +18,36 @@ QGCParamSlider::~QGCParamSlider() delete ui; } +void QGCParamSlider::startEditMode() +{ + ui->doneButton->show(); + ui->maxLabel->show(); + ui->minLabel->show(); + ui->nameLineEdit->show(); + ui->instructionsLabel->show(); + ui->refreshParamsButton->show(); + ui->selectParamComboBox->show(); + ui->minSpinBox->show(); + ui->maxSpinBox->show(); + ui->typeComboBox->show(); + isInEditMode = true; +} + +void QGCParamSlider::endEditMode() +{ + ui->doneButton->hide(); + ui->maxLabel->hide(); + ui->minLabel->hide(); + ui->nameLineEdit->hide(); + ui->instructionsLabel->hide(); + ui->refreshParamsButton->hide(); + ui->selectParamComboBox->hide(); + ui->minSpinBox->hide(); + ui->maxSpinBox->hide(); + ui->typeComboBox->hide(); + isInEditMode = false; +} + void QGCParamSlider::changeEvent(QEvent *e) { QWidget::changeEvent(e); diff --git a/src/ui/designer/QGCParamSlider.h b/src/ui/designer/QGCParamSlider.h index 56f063b96c4fefa4246bce115e8fcbe5060431b6..3f73ec5d00f2e93ae5be2c927d32416b30185778 100644 --- a/src/ui/designer/QGCParamSlider.h +++ b/src/ui/designer/QGCParamSlider.h @@ -2,13 +2,16 @@ #define QGCPARAMSLIDER_H #include +#include #include +#include "QGCToolWidgetItem.h" + namespace Ui { class QGCParamSlider; } -class QDESIGNER_WIDGET_EXPORT QGCParamSlider : public QWidget +class QDESIGNER_WIDGET_EXPORT QGCParamSlider : public QGCToolWidgetItem { Q_OBJECT @@ -16,6 +19,10 @@ public: explicit QGCParamSlider(QWidget *parent = 0); ~QGCParamSlider(); +public slots: + void startEditMode(); + void endEditMode(); + protected: void changeEvent(QEvent *e); diff --git a/src/ui/designer/QGCParamSlider.ui b/src/ui/designer/QGCParamSlider.ui index 9534679e76f860edb7b862631eee2d9121af53dd..c7022526a3727edbd9717f22775090df76833dff 100644 --- a/src/ui/designer/QGCParamSlider.ui +++ b/src/ui/designer/QGCParamSlider.ui @@ -6,41 +6,124 @@ 0 0 - 400 - 22 + 436 + 136 Form - - - 8 - - - 0 - - + + + + + Informal Name.. + + + + + + + + Float + + + + + Integer + + + + + Double + + + + + Short + + + + + Byte/Char + + + + + + + + Min + + + + + + + Max + + + + Name - + 0.00 - + + + + Qt::Horizontal + + + + + + + Done + + + + + + + + Select Parameter.. + + + + + + + + true + + + Refresh + + + + + + + Please configure the parameter slider now: + + + diff --git a/src/ui/designer/QGCToolWidget.cc b/src/ui/designer/QGCToolWidget.cc new file mode 100644 index 0000000000000000000000000000000000000000..ff52d6af2693204565e04bf39f0bcd67009d6e4f --- /dev/null +++ b/src/ui/designer/QGCToolWidget.cc @@ -0,0 +1,100 @@ +#include "QGCToolWidget.h" +#include "ui_QGCToolWidget.h" + +#include +#include +#include +#include +#include +#include "QGCParamSlider.h" +#include "QGCActionButton.h" +#include "UASManager.h" + +QGCToolWidget::QGCToolWidget(QWidget *parent) : + QWidget(parent), + toolLayout(new QVBoxLayout(this)), + mav(NULL), + ui(new Ui::QGCToolWidget) +{ + ui->setupUi(this); + createActions(); + toolLayout->setAlignment(Qt::AlignTop); + + QList systems = UASManager::instance()->getUASList(); + foreach (UASInterface* uas, systems) + { + UAS* newMav = dynamic_cast(uas); + if (newMav) + { + addUAS(uas); + } + } + connect(UASManager::instance(), SIGNAL(UASCreated(UASInterface*)), this, SLOT(addUAS(UASInterface*))); +} + +QGCToolWidget::~QGCToolWidget() +{ + delete ui; +} + +void QGCToolWidget::addUAS(UASInterface* uas) +{ + UAS* newMav = dynamic_cast(uas); + if (newMav) + { + // FIXME Convert to list + if (mav == NULL) mav = newMav; + } +} + +void QGCToolWidget::contextMenuEvent (QContextMenuEvent* event) +{ + QMenu menu(this); + menu.addAction(addParamAction); + menu.addAction(addButtonAction); + menu.addAction(setTitleAction); + menu.exec(event->globalPos()); +} + +void QGCToolWidget::createActions() +{ + addParamAction = new QAction(tr("New &Parameter Slider"), this); + addParamAction->setStatusTip(tr("Add a parameter setting slider widget to the tool")); + connect(addParamAction, SIGNAL(triggered()), this, SLOT(addParam())); + + addButtonAction = new QAction(tr("New MAV &Action Button"), this); + addButtonAction->setStatusTip(tr("Add a new action button to the tool")); + connect(addButtonAction, SIGNAL(triggered()), this, SLOT(addAction())); + + setTitleAction = new QAction(tr("Set Widget Title"), this); + setTitleAction->setStatusTip(tr("Set the title caption of this tool widget")); + connect(setTitleAction, SIGNAL(triggered()), this, SLOT(setTitle())); +} + +void QGCToolWidget::addParam() +{ + QGCParamSlider* slider = new QGCParamSlider(this); + toolLayout->addWidget(slider); + slider->startEditMode(); +} + +void QGCToolWidget::addAction() +{ + QGCActionButton* button = new QGCActionButton(this); + toolLayout->addWidget(button); + button->startEditMode(); +} + +void QGCToolWidget::setTitle() +{ + QDockWidget* parent = dynamic_cast(this->parentWidget()); + if (parent) + { + bool ok; + QString text = QInputDialog::getText(this, tr("QInputDialog::getText()"), + tr("Widget title:"), QLineEdit::Normal, + parent->windowTitle(), &ok); + if (ok && !text.isEmpty()) + parent->setWindowTitle(text); + } +} diff --git a/src/ui/designer/QGCToolWidget.h b/src/ui/designer/QGCToolWidget.h new file mode 100644 index 0000000000000000000000000000000000000000..90d90eac8be3400581da89d2d225aa746aa36146 --- /dev/null +++ b/src/ui/designer/QGCToolWidget.h @@ -0,0 +1,45 @@ +#ifndef QGCTOOLWIDGET_H +#define QGCTOOLWIDGET_H + +#include +#include +#include + +#include "UAS.h" + +namespace Ui { + class QGCToolWidget; +} + +class QGCToolWidget : public QWidget +{ + Q_OBJECT + +public: + explicit QGCToolWidget(QWidget *parent = 0); + ~QGCToolWidget(); + +public slots: + void addUAS(UASInterface* uas); + +protected: + QAction* addParamAction; + QAction* addButtonAction; + QAction* setTitleAction; + QVBoxLayout* toolLayout; + UAS* mav; + + void contextMenuEvent(QContextMenuEvent* event); + void createActions(); + +protected slots: + void addParam(); + void addAction(); + void setTitle(); + + +private: + Ui::QGCToolWidget *ui; +}; + +#endif // QGCTOOLWIDGET_H diff --git a/src/ui/designer/QGCToolWidget.ui b/src/ui/designer/QGCToolWidget.ui new file mode 100644 index 0000000000000000000000000000000000000000..212fe670abd8315a7e7aa3d11751dce7fd591717 --- /dev/null +++ b/src/ui/designer/QGCToolWidget.ui @@ -0,0 +1,21 @@ + + + + + QGCToolWidget + + + + 0 + 0 + 400 + 300 + + + + Form + + + + + diff --git a/src/ui/designer/QGCToolWidgetItem.cc b/src/ui/designer/QGCToolWidgetItem.cc new file mode 100644 index 0000000000000000000000000000000000000000..b1f9559899f43e68aac8471c63ee563a70845811 --- /dev/null +++ b/src/ui/designer/QGCToolWidgetItem.cc @@ -0,0 +1,37 @@ +#include "QGCToolWidgetItem.h" + +#include +#include + +QGCToolWidgetItem::QGCToolWidgetItem(QWidget *parent) : + QWidget(parent), + isInEditMode(false), + _component(-1) +{ + startEditAction = new QAction("Edit Slider", this); + connect(startEditAction, SIGNAL(triggered()), this, SLOT(startEditMode())); + stopEditAction = new QAction("Finish Editing Slider", this); + connect(stopEditAction, SIGNAL(triggered()), this, SLOT(endEditMode())); + + endEditMode(); +} + +QGCToolWidgetItem::~QGCToolWidgetItem() +{ + delete startEditAction; + delete stopEditAction; +} + +void QGCToolWidgetItem::contextMenuEvent (QContextMenuEvent* event) +{ + QMenu menu(this); + if (!isInEditMode) + { + menu.addAction(startEditAction); + } + else + { + menu.addAction(stopEditAction); + } + menu.exec(event->globalPos()); +} diff --git a/src/ui/designer/QGCToolWidgetItem.h b/src/ui/designer/QGCToolWidgetItem.h new file mode 100644 index 0000000000000000000000000000000000000000..2577f438e2e69daa790ce742304bbb7a21874e67 --- /dev/null +++ b/src/ui/designer/QGCToolWidgetItem.h @@ -0,0 +1,32 @@ +#ifndef QGCTOOLWIDGETITEM_H +#define QGCTOOLWIDGETITEM_H + +#include +#include + +class QGCToolWidgetItem : public QWidget +{ + Q_OBJECT +public: + explicit QGCToolWidgetItem(QWidget *parent = 0); + ~QGCToolWidgetItem(); + + int component() {return _component;} + +public slots: + virtual void startEditMode() {} + virtual void endEditMode() {} + virtual void setComponent(int comp) {_component = comp;} + +protected: + QAction* startEditAction; + QAction* stopEditAction; + + bool isInEditMode; + int _component; ///< The MAV component (the process or device ID) + + void contextMenuEvent (QContextMenuEvent* event); + +}; + +#endif // QGCTOOLWIDGETITEM_H