diff --git a/QGCApplication.pro b/QGCApplication.pro index f32186ca295398c22ae02db366304c2c95c6f3f1..06ecd51971046d7f4cb277f224bcb765d2282419 100644 --- a/QGCApplication.pro +++ b/QGCApplication.pro @@ -352,6 +352,8 @@ HEADERS += \ src/ui/WaypointList.h \ src/ui/WaypointViewOnlyView.h \ src/ViewWidgets/ParameterEditorWidget.h \ + src/ViewWidgets/CustomCommandWidget.h \ + src/ViewWidgets/CustomCommandWidgetController.h \ src/ViewWidgets/ViewWidgetController.h \ src/Waypoint.h \ @@ -479,6 +481,8 @@ SOURCES += \ src/ui/WaypointList.cc \ src/ui/WaypointViewOnlyView.cc \ src/ViewWidgets/ParameterEditorWidget.cc \ + src/ViewWidgets/CustomCommandWidget.cc \ + src/ViewWidgets/CustomCommandWidgetController.cc \ src/ViewWidgets/ViewWidgetController.cc \ src/Waypoint.cc \ diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc index c3b264b8a1866729cefe8cc7d5cbc1631d030235..3d7bab682cbb7c65678411303839e77a18e31b7f 100644 --- a/qgroundcontrol.qrc +++ b/qgroundcontrol.qrc @@ -34,6 +34,7 @@ src/QmlControls/ParameterEditor.qml src/ViewWidgets/ParameterEditorWidget.qml + src/ViewWidgets/CustomCommandWidget.qml src/VehicleSetup/SetupViewButtonsConnected.qml src/VehicleSetup/SetupViewButtonsDisconnected.qml diff --git a/src/QGCApplication.cc b/src/QGCApplication.cc index 90c5e5a2ba39a38e05e4da4fc7e73c86cec770e7..7c6e65fd2d7d4cd09961fbde544e8a187bb1f2b3 100644 --- a/src/QGCApplication.cc +++ b/src/QGCApplication.cc @@ -62,6 +62,7 @@ #include "QGCLoggingCategory.h" #include "ViewWidgetController.h" #include "ParameterEditorController.h" +#include "CustomCommandWidgetController.h" #ifdef QGC_RTLAB_ENABLED #include "OpalLink.h" @@ -285,9 +286,10 @@ void QGCApplication::_initCommon(void) qmlRegisterType("QGroundControl.Palette", 1, 0, "QGCPalette"); qmlRegisterType("QGroundControl.Controllers", 1, 0, "ViewWidgetController"); qmlRegisterType("QGroundControl.Controllers", 1, 0, "ParameterEditorController"); + qmlRegisterType("QGroundControl.Controllers", 1, 0, "CustomCommandWidgetController"); + //-- Create QML Singleton Interfaces qmlRegisterSingletonType("QGroundControl.ScreenTools", 1, 0, "ScreenTools", screenToolsSingletonFactory); - } bool QGCApplication::_initForNormalAppBoot(void) diff --git a/src/ViewWidgets/CustomCommandWidget.cc b/src/ViewWidgets/CustomCommandWidget.cc new file mode 100644 index 0000000000000000000000000000000000000000..c7e5ece821d2022c9888f7030772f5fbebd6a0a5 --- /dev/null +++ b/src/ViewWidgets/CustomCommandWidget.cc @@ -0,0 +1,30 @@ +/*===================================================================== + +QGroundControl Open Source Ground Control Station + +(c) 2009, 2010 QGROUNDCONTROL PROJECT + +This file is part of the QGROUNDCONTROL project + + QGROUNDCONTROL is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + QGROUNDCONTROL is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with QGROUNDCONTROL. If not, see . + +======================================================================*/ + +#include "CustomCommandWidget.h" + +CustomCommandWidget::CustomCommandWidget(QWidget *parent) : + QGCQmlWidgetHolder(parent) +{ + setSource(QUrl::fromUserInput("qrc:/qml/CustomCommandWidget.qml")); +} diff --git a/src/ViewWidgets/CustomCommandWidget.h b/src/ViewWidgets/CustomCommandWidget.h new file mode 100644 index 0000000000000000000000000000000000000000..5471d38d069dc8cb74a1bed68076d7db8f5f724f --- /dev/null +++ b/src/ViewWidgets/CustomCommandWidget.h @@ -0,0 +1,40 @@ +/*===================================================================== + +QGroundControl Open Source Ground Control Station + +(c) 2009, 2015 QGROUNDCONTROL PROJECT + +This file is part of the QGROUNDCONTROL project + + QGROUNDCONTROL is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + QGROUNDCONTROL is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with QGROUNDCONTROL. If not, see . + +======================================================================*/ + +/// @file +/// @author Don Gagne + +#ifndef CustomCommandWidget_H +#define CustomCommandWidget_H + +#include "QGCQmlWidgetHolder.h" + +class CustomCommandWidget : public QGCQmlWidgetHolder +{ + Q_OBJECT + +public: + CustomCommandWidget(QWidget *parent = 0); +}; + +#endif diff --git a/src/ViewWidgets/CustomCommandWidget.qml b/src/ViewWidgets/CustomCommandWidget.qml new file mode 100644 index 0000000000000000000000000000000000000000..5f353f065774bb76a8a0d0240836d39803a54002 --- /dev/null +++ b/src/ViewWidgets/CustomCommandWidget.qml @@ -0,0 +1,110 @@ +/*===================================================================== + +QGroundControl Open Source Ground Control Station + +(c) 2009, 2015 QGROUNDCONTROL PROJECT + +This file is part of the QGROUNDCONTROL project + +QGROUNDCONTROL is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +QGROUNDCONTROL is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with QGROUNDCONTROL. If not, see . + +======================================================================*/ + +/// @file +/// @author Don Gagne + +import QtQuick 2.2 + +import QGroundControl.Palette 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.Controllers 1.0 + +ViewWidget { + connectedComponent: commandComponenet + + Component { + id: commandComponenet + + Item { + + CustomCommandWidgetController { id: controller } + + Item { + anchors.top: parent.top + anchors.bottom: buttonRow.top + width: parent.width + + QGCLabel { + id: errorOutput + anchors.fill: parent + wrapMode: Text.WordWrap + visible: false + } + + QGCLabel { + id: warning + anchors.fill: parent + wrapMode: Text.WordWrap + visible: !controller.customQmlFile + text: "You can create your own commands and parameter editing user interface in this widget. " + + "You do this by providing your own Qml file. " + + "This support is a work in progress and the details may change somewhat in the future. " + + "By using this feature you are connecting directly to the internals of QGroundControl. " + + "Doing so incorrectly may cause instability both in QGroundControl and/or your vehicle. " + + "So make sure to test your changes thoroughly before using them in flight.\n\n" + + "Click 'Select Qml file' to provide your custom qml file.\n" + + "Click 'Clear Qml file' to reset to none.\n" + + "Example usage: http://www.qgroundcontrol.org/custom_command_qml_widgets" + } + + Loader { + id: loader + anchors.fill: parent + source: controller.customQmlFile + visible: controller.customQmlFile + + onStatusChanged: { + if (loader.status == Loader.Error) { + if (sourceComponent.status == Component.Error) { + errorOutput.text = sourceComponent.errorString() + errorOutput.visible = true + loader.visible = false + } + } + } + } + } + + Row { + id: buttonRow + spacing: 10 + anchors.bottom: parent.bottom + + QGCButton { + text: "Select Qml file..." + onClicked: controller.selectQmlFile() + } + + QGCButton { + text: "Clear Qml file" + + onClicked: { + errorOutput.visible = false + controller.clearQmlFile() + } + } + } + } + } +} diff --git a/src/ViewWidgets/CustomCommandWidgetController.cc b/src/ViewWidgets/CustomCommandWidgetController.cc new file mode 100644 index 0000000000000000000000000000000000000000..a4282a286dfb2e3593b1ec1135d08194b785794d --- /dev/null +++ b/src/ViewWidgets/CustomCommandWidgetController.cc @@ -0,0 +1,82 @@ +/*===================================================================== + + QGroundControl Open Source Ground Control Station + + (c) 2009 - 2014 QGROUNDCONTROL PROJECT + + This file is part of the QGROUNDCONTROL project + + QGROUNDCONTROL is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + QGROUNDCONTROL is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with QGROUNDCONTROL. If not, see . + + ======================================================================*/ + +#include "CustomCommandWidgetController.h" +#include "UASManager.h" +#include "QGCMAVLink.h" +#include "QGCFileDialog.h" + +#include +#include + +const char* CustomCommandWidgetController::_settingsKey = "CustomCommand.QmlFile"; + +CustomCommandWidgetController::CustomCommandWidgetController(void) : + _uas(NULL) +{ + _uas = UASManager::instance()->getActiveUAS(); + Q_ASSERT(_uas); + + QSettings settings; + _customQmlFile = settings.value(_settingsKey).toString(); +} + +void CustomCommandWidgetController::sendCommand(int commandId, QVariant componentId, QVariant confirm, QVariant param1, QVariant param2, QVariant param3, QVariant param4, QVariant param5, QVariant param6, QVariant param7) +{ + Q_UNUSED(commandId); + Q_UNUSED(componentId); + Q_UNUSED(confirm); + Q_UNUSED(param1); + Q_UNUSED(param2); + Q_UNUSED(param3); + Q_UNUSED(param4); + Q_UNUSED(param5); + Q_UNUSED(param6); + Q_UNUSED(param7); + _uas->executeCommand((MAV_CMD)commandId, confirm.toInt(), param1.toFloat(), param2.toFloat(), param3.toFloat(), param4.toFloat(), param5.toFloat(), param6.toFloat(), param7.toFloat(), componentId.toInt()); +} + +void CustomCommandWidgetController::selectQmlFile(void) +{ + QSettings settings; + + QString qmlFile = QGCFileDialog::getOpenFileName(NULL, "Select custom Qml file", QString(), "Qml files (*.qml)"); + if (qmlFile.isEmpty()) { + _customQmlFile.clear(); + settings.remove(_settingsKey); + } else { + QUrl url = QUrl::fromLocalFile(qmlFile); + _customQmlFile = url.toString(); + settings.setValue(_settingsKey, _customQmlFile); + } + + emit customQmlFileChanged(_customQmlFile); +} + +void CustomCommandWidgetController::clearQmlFile(void) +{ + _customQmlFile.clear(); + QSettings settings; + settings.remove(_settingsKey); + emit customQmlFileChanged(_customQmlFile); +} diff --git a/src/ViewWidgets/CustomCommandWidgetController.h b/src/ViewWidgets/CustomCommandWidgetController.h new file mode 100644 index 0000000000000000000000000000000000000000..be9dcdc91483caa621ca4199fb06e393c4361391 --- /dev/null +++ b/src/ViewWidgets/CustomCommandWidgetController.h @@ -0,0 +1,55 @@ +/*===================================================================== + + QGroundControl Open Source Ground Control Station + + (c) 2009 - 2014 QGROUNDCONTROL PROJECT + + This file is part of the QGROUNDCONTROL project + + QGROUNDCONTROL is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + QGROUNDCONTROL is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with QGROUNDCONTROL. If not, see . + + ======================================================================*/ + +#ifndef CustomCommandWidgetController_H +#define CustomCommandWidgetController_H + +#include + +#include "UASInterface.h" +#include "AutoPilotPlugin.h" +#include "UASManagerInterface.h" + +class CustomCommandWidgetController : public QObject +{ + Q_OBJECT + +public: + CustomCommandWidgetController(void); + + Q_PROPERTY(QString customQmlFile MEMBER _customQmlFile NOTIFY customQmlFileChanged) + + Q_INVOKABLE void sendCommand(int commandId, QVariant componentId, QVariant confirm, QVariant param1, QVariant param2, QVariant param3, QVariant param4, QVariant param5, QVariant param6, QVariant param7); + Q_INVOKABLE void selectQmlFile(void); + Q_INVOKABLE void clearQmlFile(void); + +signals: + void customQmlFileChanged(const QString& customQmlFile); + +private: + UASInterface* _uas; + QString _customQmlFile; + static const char* _settingsKey; +}; + +#endif \ No newline at end of file diff --git a/src/ui/MainWindow.cc b/src/ui/MainWindow.cc index d035870866635cf8d09b80793f5cefe14bd122b7..fde97c80208517ec189fae77cf154e31506e0ba0 100644 --- a/src/ui/MainWindow.cc +++ b/src/ui/MainWindow.cc @@ -69,6 +69,7 @@ This file is part of the QGROUNDCONTROL project #include "QGCFileDialog.h" #include "QGCMessageBox.h" #include "QGCDockWidget.h" +#include "CustomCommandWidget.h" #ifdef UNITTEST_BUILD #include "QmlControls/QmlTestWidget.h" @@ -108,6 +109,7 @@ const char* MainWindow::_uasListDockWidgetName = "UNMANNED_SYSTEM_LIST_DOCKWIDGE const char* MainWindow::_waypointsDockWidgetName = "WAYPOINT_LIST_DOCKWIDGET"; const char* MainWindow::_mavlinkDockWidgetName = "MAVLINK_INSPECTOR_DOCKWIDGET"; const char* MainWindow::_parametersDockWidgetName = "PARAMETER_INTERFACE_DOCKWIDGET"; +const char* MainWindow::_customCommandWidgetName = "CUSTOM_COMMAND_DOCKWIDGET"; const char* MainWindow::_filesDockWidgetName = "FILE_VIEW_DOCKWIDGET"; const char* MainWindow::_uasStatusDetailsDockWidgetName = "UAS_STATUS_DETAILS_DOCKWIDGET"; const char* MainWindow::_mapViewDockWidgetName = "MAP_VIEW_DOCKWIDGET"; @@ -433,6 +435,7 @@ void MainWindow::_buildCommonWidgets(void) { _waypointsDockWidgetName, "Mission Plan", Qt::BottomDockWidgetArea }, { _mavlinkDockWidgetName, "MAVLink Inspector", Qt::RightDockWidgetArea }, { _parametersDockWidgetName, "Parameter Editor", Qt::RightDockWidgetArea }, + { _customCommandWidgetName, "Custom Command", Qt::RightDockWidgetArea }, { _filesDockWidgetName, "Onboard Files", Qt::RightDockWidgetArea }, { _uasStatusDetailsDockWidgetName, "Status Details", Qt::RightDockWidgetArea }, { _mapViewDockWidgetName, "Map view", Qt::RightDockWidgetArea }, @@ -549,6 +552,8 @@ void MainWindow::_createInnerDockWidget(const QString& widgetName) widget = new QGCMAVLinkInspector(MAVLinkProtocol::instance(),this); } else if (widgetName == _parametersDockWidgetName) { widget = new ParameterEditorWidget(this); + } else if (widgetName == _customCommandWidgetName) { + widget = new CustomCommandWidget(this); } else if (widgetName == _filesDockWidgetName) { widget = new QGCUASFileViewMulti(this); } else if (widgetName == _uasStatusDetailsDockWidgetName) { diff --git a/src/ui/MainWindow.h b/src/ui/MainWindow.h index 54c7023f8f587f7c3d0cab8523e9b15c698396be..e3c0f86da460847fda68855d1284a18aa8db81e7 100644 --- a/src/ui/MainWindow.h +++ b/src/ui/MainWindow.h @@ -324,6 +324,7 @@ private: static const char* _waypointsDockWidgetName; static const char* _mavlinkDockWidgetName; static const char* _parametersDockWidgetName; + static const char* _customCommandWidgetName; static const char* _filesDockWidgetName; static const char* _uasStatusDetailsDockWidgetName; static const char* _mapViewDockWidgetName;