diff --git a/src/comm/MAVLinkSimulationLink.cc b/src/comm/MAVLinkSimulationLink.cc index f94f4021aa2f77b7e1762a8570f4fb87e68f0fab..fa28b2748db8be72aad2dd2cf549ba2d372d8007 100644 --- a/src/comm/MAVLinkSimulationLink.cc +++ b/src/comm/MAVLinkSimulationLink.cc @@ -684,7 +684,7 @@ void MAVLinkSimulationLink::writeBytes(const char* data, qint64 size) if (mavlink_parse_char(this->id, data[i], &msg, &comm)) { // MESSAGE RECEIVED! - qDebug() << "SIMULATION LINK RECEIVED MESSAGE!"; +// qDebug() << "SIMULATION LINK RECEIVED MESSAGE!"; emit messageReceived(msg); switch (msg.msgid) @@ -722,7 +722,7 @@ void MAVLinkSimulationLink::writeBytes(const char* data, qint64 size) mavlink_command_long_t action; mavlink_msg_command_long_decode(&msg, &action); - qDebug() << "SIM" << "received action" << action.command << "for system" << action.target_system; +// qDebug() << "SIM" << "received action" << action.command << "for system" << action.target_system; // FIXME MAVLINKV10PORTINGNEEDED // switch (action.action) { @@ -756,13 +756,13 @@ void MAVLinkSimulationLink::writeBytes(const char* data, qint64 size) case MAVLINK_MSG_ID_MANUAL_CONTROL: { mavlink_manual_control_t control; mavlink_msg_manual_control_decode(&msg, &control); - qDebug() << "\n" << "ROLL:" << control.x << "PITCH:" << control.y; +// qDebug() << "\n" << "ROLL:" << control.x << "PITCH:" << control.y; } break; #endif case MAVLINK_MSG_ID_PARAM_REQUEST_LIST: { - qDebug() << "GCS REQUESTED PARAM LIST FROM SIMULATION"; +// qDebug() << "GCS REQUESTED PARAM LIST FROM SIMULATION"; mavlink_param_request_list_t read; mavlink_msg_param_request_list_decode(&msg, &read); if (read.target_system == systemId) @@ -785,7 +785,7 @@ void MAVLinkSimulationLink::writeBytes(const char* data, qint64 size) j++; } - qDebug() << "SIMULATION SENT PARAMETERS TO GCS"; +// qDebug() << "SIMULATION SENT PARAMETERS TO GCS"; } } break; @@ -794,7 +794,7 @@ void MAVLinkSimulationLink::writeBytes(const char* data, qint64 size) // Drop on even milliseconds if (QGC::groundTimeMilliseconds() % 2 == 0) { - qDebug() << "SIMULATION RECEIVED COMMAND TO SET PARAMETER"; +// qDebug() << "SIMULATION RECEIVED COMMAND TO SET PARAMETER"; mavlink_param_set_t set; mavlink_msg_param_set_decode(&msg, &set); // if (set.target_system == systemId) @@ -819,7 +819,7 @@ void MAVLinkSimulationLink::writeBytes(const char* data, qint64 size) break; case MAVLINK_MSG_ID_PARAM_REQUEST_READ: { - qDebug() << "SIMULATION RECEIVED COMMAND TO SEND PARAMETER"; +// qDebug() << "SIMULATION RECEIVED COMMAND TO SEND PARAMETER"; mavlink_param_request_read_t read; mavlink_msg_param_request_read_decode(&msg, &read); QByteArray bytes((char*)read.param_id, MAVLINK_MSG_PARAM_REQUEST_READ_FIELD_PARAM_ID_LEN); diff --git a/src/comm/MAVLinkSimulationMAV.cc b/src/comm/MAVLinkSimulationMAV.cc index d65ea66ddb50e31eaf8fcb1f6f6e2ddc62d813bc..b0ffb8b924b5e75f4fb6f330c59f0af2c3d2e55d 100644 --- a/src/comm/MAVLinkSimulationMAV.cc +++ b/src/comm/MAVLinkSimulationMAV.cc @@ -130,7 +130,7 @@ void MAVLinkSimulationMAV::mainloop() y = nextSPY; z = nextSPZ; firstWP = false; - qDebug() << "INIT STEP"; +// qDebug() << "INIT STEP"; } } else @@ -139,7 +139,6 @@ void MAVLinkSimulationMAV::mainloop() } - // GLOBAL POSITION mavlink_message_t msg; mavlink_global_position_int_t pos; @@ -395,7 +394,7 @@ void MAVLinkSimulationMAV::handleMessage(const mavlink_message_t& msg) if (msg.sysid != systemid) { print_message(&msg); - qDebug() << "MAV:" << systemid << "RECEIVED MESSAGE FROM" << msg.sysid << "COMP" << msg.compid; +// qDebug() << "MAV:" << systemid << "RECEIVED MESSAGE FROM" << msg.sysid << "COMP" << msg.compid; } switch(msg.msgid) { diff --git a/src/uas/UASInterface.h b/src/uas/UASInterface.h index 06a03b70a893929e0a9adc373a429f0f856fca06..a8377f326f4a86f53b9ffd95a61056684fe16252 100644 --- a/src/uas/UASInterface.h +++ b/src/uas/UASInterface.h @@ -358,9 +358,6 @@ signals: * @param description longer textual description. Should be however limited to a short text, e.g. 200 chars. */ void statusChanged(UASInterface* uas, QString status, QString description); - /** @brief System has been removed / disconnected / shutdown cleanly, remove */ - void systemRemoved(UASInterface* uas); - void systemRemoved(); /** * @brief Received a plain text message from the robot * This signal should NOT be used for standard communication, but rather for VERY IMPORTANT diff --git a/src/uas/UASManager.cc b/src/uas/UASManager.cc index 00bb81ba261c39ba2c9c27ee302d1cbf3e3d595d..a714bcca027efe3958bdcf60f7a55f061d8042af 100644 --- a/src/uas/UASManager.cc +++ b/src/uas/UASManager.cc @@ -269,7 +269,6 @@ void UASManager::addUAS(UASInterface* uas) if (!systems.contains(uas)) { systems.append(uas); - connect(uas, SIGNAL(destroyed(QObject*)), this, SLOT(removeUAS(QObject*))); // Set home position on UAV if set in UI // - this is done on a per-UAV basis // Set home position in UI if UAV chooses a new one (caution! if multiple UAVs are connected, take care!) @@ -300,14 +299,19 @@ void UASManager::addUAS(UASInterface* uas) } } -void UASManager::removeUAS(QObject* uas) +/** + * @brief The function that should be used when removing UASes from QGC. emits UASDeletect(UASInterface*) when triggered + * so that UI elements can update accordingly. + * @param uas The UAS to remove + */ +void UASManager::removeUAS(UASInterface* uas) { - UASInterface* mav = qobject_cast(uas); - - if (mav) { - int listindex = systems.indexOf(mav); + if (uas) + { + int listindex = systems.indexOf(uas); - if (mav == activeUAS) + // If this is the active UAS, select a new one. + if (uas == activeUAS) { if (systems.count() > 1) { @@ -334,8 +338,14 @@ void UASManager::removeUAS(QObject* uas) // XXX Not emitting the null pointer yet } } + + // Finally delete a local reference to this UAS systems.removeAt(listindex); - emit UASDeleted(mav); + + // Notify other UI elements that a UAS is being deleted before finally deleting it. + qDebug() << "Deleting UAS object: " << uas->getUASName(); + emit UASDeleted(uas); + uas->deleteLater(); } } diff --git a/src/uas/UASManager.h b/src/uas/UASManager.h index ff4c89731f1f5c55fd5f2f0a71d1ec37ec399223..c1243520e4f3770c924269da367454355f3cb763 100644 --- a/src/uas/UASManager.h +++ b/src/uas/UASManager.h @@ -151,8 +151,8 @@ public slots: **/ void addUAS(UASInterface* UAS); - /** @brief Remove a system from the list */ - void removeUAS(QObject* uas); + /** @brief Remove a system from the list. Also triggers the UAS to kill itself. */ + void removeUAS(UASInterface* uas); /** diff --git a/src/ui/HSIDisplay.cc b/src/ui/HSIDisplay.cc index 7bbdeac9e6cdb89996d6949a8dd8e0a1538de374..f4e5ee81ad475e14b1989b2217b061c2e57730d1 100644 --- a/src/ui/HSIDisplay.cc +++ b/src/ui/HSIDisplay.cc @@ -181,6 +181,9 @@ HSIDisplay::HSIDisplay(QWidget *parent) : setActiveUAS(UASManager::instance()->getActiveUAS()); + // Listen for the removal of the active UAS. + setActiveUAS(UASManager::instance()->getActiveUAS()); + setFocusPolicy(Qt::StrongFocus); } @@ -978,6 +981,12 @@ void HSIDisplay::setActiveUAS(UASInterface* uas) resetMAVState(); } +void HSIDisplay::removeUAS(UASInterface* uas) +{ + this->uas = NULL; + resetMAVState(); +} + void HSIDisplay::updateSpeed(UASInterface* uas, double vx, double vy, double vz, quint64 time) { Q_UNUSED(uas); diff --git a/src/ui/HSIDisplay.h b/src/ui/HSIDisplay.h index 6ebfeb73880c4532fca3e752d087fd4b4a4faf54..2ddcc6dd1d4b6b1e3d1c12304817805c5e05d38a 100644 --- a/src/ui/HSIDisplay.h +++ b/src/ui/HSIDisplay.h @@ -52,6 +52,7 @@ public: public slots: void setActiveUAS(UASInterface* uas); + void removeUAS(UASInterface* uas); /** @brief Set the width in meters this widget shows from top */ void setMetricWidth(double width); void updateSatellite(int uasid, int satid, float azimuth, float direction, float snr, bool used); diff --git a/src/ui/MainWindow.cc b/src/ui/MainWindow.cc index c29a4c62b47bad1d7d92fb6ae38778b96854e166..8e9c488a58e62935829de3d68f0c0a5c508fa88a 100644 --- a/src/ui/MainWindow.cc +++ b/src/ui/MainWindow.cc @@ -1676,7 +1676,6 @@ void MainWindow::UASCreated(UASInterface* uas) // this code piece might be removed later if this is the final // conclusion (May 2013) // QAction* uasAction = new QAction(icon, tr("Select %1 for control").arg(uas->getUASName()), ui.menuConnected_Systems); - // connect(uas, SIGNAL(systemRemoved()), uasAction, SLOT(deleteLater())); // connect(uasAction, SIGNAL(triggered()), uas, SLOT(setSelected())); // ui.menuConnected_Systems->addAction(uasAction); diff --git a/src/ui/QGCToolBar.cc b/src/ui/QGCToolBar.cc index 4dbb791053aede059ae81369b95d230ec5845370..73d6d15b735821701b37b2b2e74798e61980765a 100644 --- a/src/ui/QGCToolBar.cc +++ b/src/ui/QGCToolBar.cc @@ -31,7 +31,6 @@ This file is part of the QGROUNDCONTROL project QGCToolBar::QGCToolBar(QWidget *parent) : QToolBar(parent), mav(NULL), - player(NULL), changed(true), batteryPercent(0), batteryVoltage(0), @@ -91,28 +90,28 @@ void QGCToolBar::createUI() symbolLabel = new QLabel(this); addWidget(symbolLabel); - toolBarNameLabel = new QLabel("------", this); + toolBarNameLabel = new QLabel(this); toolBarNameLabel->setToolTip(tr("Currently controlled vehicle")); toolBarNameLabel->setAlignment(Qt::AlignCenter); addWidget(toolBarNameLabel); - toolBarTimeoutLabel = new QLabel("UNCONNECTED", this); + toolBarTimeoutLabel = new QLabel(this); toolBarTimeoutLabel->setToolTip(tr("System timed out, interval since last message")); toolBarTimeoutLabel->setAlignment(Qt::AlignCenter); toolBarTimeoutLabel->setObjectName("toolBarTimeoutLabel"); addWidget(toolBarTimeoutLabel); - toolBarSafetyLabel = new QLabel("----", this); + toolBarSafetyLabel = new QLabel(this); toolBarSafetyLabel->setToolTip(tr("Vehicle safety state")); toolBarSafetyLabel->setAlignment(Qt::AlignCenter); addWidget(toolBarSafetyLabel); - toolBarModeLabel = new QLabel("------", this); + toolBarModeLabel = new QLabel(this); toolBarModeLabel->setToolTip(tr("Vehicle mode")); toolBarModeLabel->setAlignment(Qt::AlignCenter); addWidget(toolBarModeLabel); - toolBarStateLabel = new QLabel("------", this); + toolBarStateLabel = new QLabel(this); toolBarStateLabel->setToolTip(tr("Vehicle state")); toolBarStateLabel->setAlignment(Qt::AlignCenter); addWidget(toolBarStateLabel); @@ -122,28 +121,27 @@ void QGCToolBar::createUI() toolBarBatteryBar->setMaximum(100); toolBarBatteryBar->setMinimumWidth(20); toolBarBatteryBar->setMaximumWidth(100); - toolBarBatteryBar->setValue(0); toolBarBatteryBar->setToolTip(tr("Battery charge level")); toolBarBatteryBar->setObjectName("toolBarBatteryBar"); addWidget(toolBarBatteryBar); - toolBarBatteryVoltageLabel = new QLabel("xx.x V"); + toolBarBatteryVoltageLabel = new QLabel(this); toolBarBatteryVoltageLabel->setObjectName("toolBarBatteryVoltageLabel"); toolBarBatteryVoltageLabel->setToolTip(tr("Battery voltage")); toolBarBatteryVoltageLabel->setAlignment(Qt::AlignCenter); addWidget(toolBarBatteryVoltageLabel); - toolBarWpLabel = new QLabel("WP--", this); + toolBarWpLabel = new QLabel(this); toolBarWpLabel->setToolTip(tr("Current waypoint")); toolBarWpLabel->setAlignment(Qt::AlignCenter); addWidget(toolBarWpLabel); - toolBarDistLabel = new QLabel("--- ---- m", this); + toolBarDistLabel = new QLabel(this); toolBarDistLabel->setToolTip(tr("Distance to current waypoint")); toolBarDistLabel->setAlignment(Qt::AlignCenter); addWidget(toolBarDistLabel); - toolBarMessageLabel = new QLabel("", this); + toolBarMessageLabel = new QLabel(this); toolBarMessageLabel->setToolTip(tr("Most recent system message")); addWidget(toolBarMessageLabel); @@ -158,11 +156,17 @@ void QGCToolBar::createUI() addWidget(connectButton); connect(connectButton, SIGNAL(clicked(bool)), this, SLOT(connectLink(bool))); + resetToolbarUI(); + // DONE INITIALIZING BUTTONS + // Set the toolbar to be updated every 2s + connect(&updateViewTimer, SIGNAL(timeout()), this, SLOT(updateView())); + // Configure the toolbar for the current default UAS setActiveUAS(UASManager::instance()->getActiveUAS()); connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)), this, SLOT(setActiveUAS(UASInterface*))); + connect(UASManager::instance(), SIGNAL(UASDeleted(UASInterface*)), this, SLOT(removeUAS(UASInterface*))); if (LinkManager::instance()->getLinks().count() > 2) addLink(LinkManager::instance()->getLinks().last()); @@ -175,15 +179,33 @@ void QGCToolBar::createUI() connectButton->setText(tr("New Link")); } - // Set the toolbar to be updated every 2s - connect(&updateViewTimer, SIGNAL(timeout()), this, SLOT(updateView())); - updateViewTimer.start(2000); - loadSettings(); changed = false; } +/** + * Reset all the labels and stuff for the toolbar to a pristine state. Done at startup after + * all UI has been created and also when the last UAS has been deleted. + **/ +void QGCToolBar::resetToolbarUI() +{ + toolBarNameLabel->setText("------"); + toolBarNameLabel->setStyleSheet(""); + toolBarTimeoutLabel->setText(tr("UNCONNECTED")); + toolBarSafetyLabel->setText("----"); + toolBarModeLabel->setText("------"); + toolBarStateLabel->setText("------"); + toolBarBatteryBar->setValue(0); + toolBarBatteryBar->setDisabled(true); + toolBarBatteryVoltageLabel->setText("xx.x V"); + toolBarWpLabel->setText("WP--"); + toolBarDistLabel->setText("--- ---- m"); + toolBarMessageLabel->clear(); + symbolLabel->setStyleSheet(""); + symbolLabel->clear(); +} + void QGCToolBar::setPerspectiveChangeActions(const QList &actions) { if (actions.count() > 1) @@ -269,9 +291,9 @@ void QGCToolBar::setActiveUAS(UASInterface* active) // Do nothing if system is the same or NULL if ((active == NULL) || mav == active) return; + // If switching UASes, disconnect the only one. if (mav) { - // Disconnect old system disconnect(mav, SIGNAL(statusChanged(UASInterface*,QString,QString)), this, SLOT(updateState(UASInterface*,QString,QString))); disconnect(mav, SIGNAL(modeChanged(int,QString,QString)), this, SLOT(updateMode(int,QString,QString))); disconnect(mav, SIGNAL(nameChanged(QString)), this, SLOT(updateName(QString))); @@ -287,6 +309,11 @@ void QGCToolBar::setActiveUAS(UASInterface* active) disconnect(mav->getWaypointManager(), SIGNAL(waypointDistanceChanged(double)), this, SLOT(updateWaypointDistance(double))); } } + else + { + // Only update the UI once a UAS has been selected. + updateViewTimer.start(2000); + } // Connect new system mav = active; @@ -315,9 +342,24 @@ void QGCToolBar::setActiveUAS(UASInterface* active) toolBarStateLabel->setText(mav->getShortState()); toolBarTimeoutLabel->setText(""); toolBarDistLabel->setText(""); + toolBarBatteryBar->setEnabled(true); setSystemType(mav, mav->getSystemType()); } +/** + * @brief Handle removal of the UAS that is currently being displayed. + * Stop updating the UI periodically, reset the UI, and reset our stored UAS. + * @param uas The UAS to remove. + */ +void QGCToolBar::removeUAS(UASInterface* uas) +{ + if (mav == uas) { + updateViewTimer.stop(); + resetToolbarUI(); + mav = NULL; + } +} + void QGCToolBar::createCustomWidgets() { diff --git a/src/ui/QGCToolBar.h b/src/ui/QGCToolBar.h index 9e65d988869606b7943b5327a8f34615eae2e3f3..924fa6dbb8161496ba40be51ee7148c5b8534577 100644 --- a/src/ui/QGCToolBar.h +++ b/src/ui/QGCToolBar.h @@ -46,6 +46,8 @@ public: public slots: /** @brief Set the system that is currently displayed by this widget */ void setActiveUAS(UASInterface* active); + /** @brief Remove the provided UAS if it's currently active from the toolbar */ + void removeUAS(UASInterface* uas); /** @brief Set the link which is currently handled with connecting / disconnecting */ void addLink(LinkInterface* link); /** @brief Remove link which is currently handled */ @@ -88,6 +90,7 @@ protected: void storeSettings(); void loadSettings(); void createUI(); + void resetToolbarUI(); UASInterface* mav; QLabel* symbolLabel; @@ -102,7 +105,6 @@ protected: QPushButton* connectButton; QProgressBar* toolBarBatteryBar; QLabel* toolBarBatteryVoltageLabel; - QGCMAVLinkLogPlayer* player; bool changed; float batteryPercent; float batteryVoltage; diff --git a/src/ui/uas/UASListWidget.cc b/src/ui/uas/UASListWidget.cc index 913955f4c4f7302baf69915d832639d416b08de4..0c3343344fb71197ecc3b090e5d2e4683a9fc278 100644 --- a/src/ui/uas/UASListWidget.cc +++ b/src/ui/uas/UASListWidget.cc @@ -147,32 +147,32 @@ void UASListWidget::activeUAS(UASInterface* uas) * If the UAS was removed, check to see if it was the last one in the QGroupBox and delete * the QGroupBox if so. */ -void UASListWidget::removeUASView(QObject* widget) +void UASListWidget::removeUAS(UASInterface* uas) { - UASView* view = (UASView*)widget; - if (view) { - int views = view->parentWidget()->findChildren().size(); - if (views == 0) { - // Delete the groupbox - view->parentWidget()->deleteLater(); - - // Remove the associated UAS from our list. - UASInterface* uas = uasViews.key(view, NULL); - if (uas) - { - uasViews.remove(uas); - } + // Remove the UAS from our data structures and + // the global listing. + uasViews.remove(uas); + + // Check all groupboxes for all links this uas had and check if they're empty. + // Delete them if they are. + QListIterator i = *uas->getLinks(); + while (i.hasNext()) + { + LinkInterface* link = i.next(); - // And remove this GroupBox from our mapping. - LinkInterface* link = linkToBoxMapping.key((QGroupBox*)view->parentWidget(), NULL); - if (link) - { + QGroupBox* box = linkToBoxMapping[link]; + if (box) + { + // If this was the last UAS in the GroupBox, remove it and its corresponding link. + int views = box->findChildren().size(); + if (views == 0) { + box->deleteLater(); linkToBoxMapping.remove(link); } - - // And put the initial widget back. - uWidget = new QGCUnconnectedInfoWidget(this); - m_ui->verticalLayout->addWidget(uWidget); } } + + // And if no QGroupBoxes are left, put the initial widget back. + uWidget = new QGCUnconnectedInfoWidget(this); + m_ui->verticalLayout->addWidget(uWidget); } diff --git a/src/ui/uas/UASListWidget.h b/src/ui/uas/UASListWidget.h index b78a1811361d618443db51c5810626543bf0bde9..58c5fafc6245600de4cbac0db494476fcd9058fc 100644 --- a/src/ui/uas/UASListWidget.h +++ b/src/ui/uas/UASListWidget.h @@ -51,7 +51,7 @@ public: public slots: void addUAS(UASInterface* uas); void activeUAS(UASInterface* uas); - void removeUASView(QObject* widget); + void removeUAS(UASInterface* uas); protected: // Keep a mapping from Links to GroupBoxes for adding new links. diff --git a/src/ui/uas/UASView.cc b/src/ui/uas/UASView.cc index 8f605e1ee3a30fe5f1b37864d7d30f98d78a7b2a..df50d922a9a4f93b29d8ca9d8a43295aefe9d58e 100644 --- a/src/ui/uas/UASView.cc +++ b/src/ui/uas/UASView.cc @@ -117,13 +117,12 @@ UASView::UASView(UASInterface* uas, QWidget *parent) : connect(m_ui->shutdownButton, SIGNAL(clicked()), uas, SLOT(shutdown())); // Allow to delete this widget - connect(removeAction, SIGNAL(triggered()), this, SLOT(deleteLater())); + connect(removeAction, SIGNAL(triggered()), this, SLOT(prepareForDeletion())); connect(renameAction, SIGNAL(triggered()), this, SLOT(rename())); connect(selectAction, SIGNAL(triggered()), uas, SLOT(setSelected())); connect(hilAction, SIGNAL(triggered(bool)), this, SLOT(showHILUi())); connect(selectAirframeAction, SIGNAL(triggered()), this, SLOT(selectAirframe())); connect(setBatterySpecsAction, SIGNAL(triggered()), this, SLOT(setBatterySpecs())); - connect(uas, SIGNAL(systemRemoved()), this, SLOT(deleteLater())); // Name changes connect(uas, SIGNAL(nameChanged(QString)), this, SLOT(updateName(QString))); @@ -562,6 +561,16 @@ void UASView::showHILUi() MainWindow::instance()->showHILConfigurationWidget(uas); } +/** + * @brief Stop updating this UASView, queue it for deletion, and also tell the UASManager to delete the UAS. + */ +void UASView::prepareForDeletion() +{ + refreshTimer->stop(); + UASManager::instance()->removeUAS(uas); + deleteLater(); +} + void UASView::refresh() { //setUpdatesEnabled(false); @@ -569,7 +578,6 @@ void UASView::refresh() //repaint(); //qDebug() << "UPDATING UAS WIDGET!" << uas->getUASName(); - if (generalUpdateCount == 4) { #if (QGC_EVENTLOOP_DEBUG) diff --git a/src/ui/uas/UASView.h b/src/ui/uas/UASView.h index edc8bee406da628a5580385e19f38ba671d2c9f8..1bcdd4dbd6d441fedd2de3fb8b92f618aff9d543 100644 --- a/src/ui/uas/UASView.h +++ b/src/ui/uas/UASView.h @@ -65,6 +65,8 @@ public slots: void updateLoad(UASInterface* uas, double load); //void receiveValue(int uasid, QString id, double value, quint64 time); void showHILUi(); + /** @brief Disables the widget from accessing the UAS object in preparation for being deleted */ + void prepareForDeletion(); void refresh(); /** @brief Receive new waypoint information */ void setWaypoint(int uasId, int id, double x, double y, double z, double yaw, bool autocontinue, bool current);