diff --git a/src/uas/UASManager.cc b/src/uas/UASManager.cc index a714bcca027efe3958bdcf60f7a55f061d8042af..0312dc9688cac40b77c7c764446ccea2f4d2b8a8 100644 --- a/src/uas/UASManager.cc +++ b/src/uas/UASManager.cc @@ -310,38 +310,23 @@ void UASManager::removeUAS(UASInterface* uas) { int listindex = systems.indexOf(uas); - // If this is the active UAS, select a new one. + // Remove this system from local data store. + systems.removeAt(listindex); + + // If this is the active UAS, select a new one if one exists otherwise + // indicate that there are no active UASes. if (uas == activeUAS) { - if (systems.count() > 1) + if (systems.count()) { - // We only set a new UAS if more than one is present - if (listindex != 0) - { - // The system to be removed is not at position 1 - // set position one as new active system - setActiveUAS(systems.first()); - } - else - { - // The system to be removed is at position 1, - // select the next system - setActiveUAS(systems.at(1)); - } + setActiveUAS(systems.first()); } else { - // TODO send a null pointer if no UAS is present any more - // This has to be properly tested however, since it might - // crash code parts not handling null pointers correctly. - activeUAS = NULL; - // XXX Not emitting the null pointer yet + setActiveUAS(NULL); } } - // Finally delete a local reference to this UAS - systems.removeAt(listindex); - // Notify other UI elements that a UAS is being deleted before finally deleting it. qDebug() << "Deleting UAS object: " << uas->getUASName(); emit UASDeleted(uas); @@ -449,21 +434,24 @@ UASInterface* UASManager::getUASForId(int id) void UASManager::setActiveUAS(UASInterface* uas) { - if (uas != NULL) { - activeUASMutex.lock(); - if (activeUAS != NULL) { - emit activeUASStatusChanged(activeUAS, false); - emit activeUASStatusChanged(activeUAS->getUASID(), false); - } - activeUAS = uas; - activeUASMutex.unlock(); + // Signal components that the last UAS is no longer active. + activeUASMutex.lock(); + if (activeUAS != NULL) { + emit activeUASStatusChanged(activeUAS, false); + emit activeUASStatusChanged(activeUAS->getUASID(), false); + } + activeUAS = uas; + activeUASMutex.unlock(); + // And signal that a new UAS is. + emit activeUASSet(activeUAS); + if (activeUAS) + { activeUAS->setSelected(); - emit activeUASSet(uas); - emit activeUASSet(uas->getUASID()); - emit activeUASSetListIndex(systems.indexOf(uas)); - emit activeUASStatusChanged(uas, true); - emit activeUASStatusChanged(uas->getUASID(), true); + emit activeUASSet(activeUAS->getUASID()); + emit activeUASSetListIndex(systems.indexOf(activeUAS)); + emit activeUASStatusChanged(activeUAS, true); + emit activeUASStatusChanged(activeUAS->getUASID(), true); } } diff --git a/src/uas/UASManager.h b/src/uas/UASManager.h index c1243520e4f3770c924269da367454355f3cb763..86a13d6dea0d36d24582d323280baa07b341f22f 100644 --- a/src/uas/UASManager.h +++ b/src/uas/UASManager.h @@ -151,12 +151,12 @@ public slots: **/ void addUAS(UASInterface* UAS); - /** @brief Remove a system from the list. Also triggers the UAS to kill itself. */ + /** @brief Remove a system from the list. If this is the active UAS, it switches to another one calling setActiveUAS. Also triggers the UAS to kill itself. */ void removeUAS(UASInterface* uas); /** - * @brief Set a UAS as currently selected + * @brief Set a UAS as currently selected. NULL is a valid value for when no other valid UAS's are available. * * @param UAS Unmanned Air System to set **/ diff --git a/src/ui/HSIDisplay.cc b/src/ui/HSIDisplay.cc index f4e5ee81ad475e14b1989b2217b061c2e57730d1..a2f5c7fa9ec42a424f26986c49e2e0e6a395b613 100644 --- a/src/ui/HSIDisplay.cc +++ b/src/ui/HSIDisplay.cc @@ -177,12 +177,11 @@ HSIDisplay::HSIDisplay(QWidget *parent) : setStatusTip(tr("View from top in body frame. Scroll with mouse wheel to change the horizontal field of view of the widget.")); connect(&statusClearTimer, SIGNAL(timeout()), this, SLOT(clearStatusMessage())); - statusClearTimer.start(3000); setActiveUAS(UASManager::instance()->getActiveUAS()); - // Listen for the removal of the active UAS. - setActiveUAS(UASManager::instance()->getActiveUAS()); + connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)), + this, SLOT(setActiveUAS(UASInterface*))); setFocusPolicy(Qt::StrongFocus); } @@ -236,7 +235,7 @@ void HSIDisplay::paintEvent(QPaintEvent * event) void HSIDisplay::renderOverlay() { - if (!isVisible()) return; + if (!isVisible() || !uas) return; #if (QGC_EVENTLOOP_DEBUG) qDebug() << "EVENTLOOP:" << __FILE__ << __LINE__; #endif @@ -911,9 +910,6 @@ void HSIDisplay::setMetricWidth(double width) */ void HSIDisplay::setActiveUAS(UASInterface* uas) { - if (!uas) - return; - if (this->uas != NULL) { disconnect(this->uas, SIGNAL(gpsSatelliteStatusChanged(int,int,float,float,float,bool)), this, SLOT(updateSatellite(int,int,float,float,float,bool))); disconnect(this->uas, SIGNAL(localPositionChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateLocalPosition(UASInterface*,double,double,double,quint64))); @@ -946,47 +942,49 @@ void HSIDisplay::setActiveUAS(UASInterface* uas) disconnect(this->uas, SIGNAL(actuatorStatusChanged(bool,bool,bool)), this, SLOT(updateActuatorStatus(bool,bool,bool))); } - connect(uas, SIGNAL(gpsSatelliteStatusChanged(int,int,float,float,float,bool)), this, SLOT(updateSatellite(int,int,float,float,float,bool))); - connect(uas, SIGNAL(localPositionChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateLocalPosition(UASInterface*,double,double,double,quint64))); - connect(uas, SIGNAL(globalPositionChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateGlobalPosition(UASInterface*,double,double,double,quint64))); - connect(uas, SIGNAL(attitudeThrustSetPointChanged(UASInterface*,double,double,double,double,quint64)), this, SLOT(updateAttitudeSetpoints(UASInterface*,double,double,double,double,quint64))); - connect(uas, SIGNAL(positionSetPointsChanged(int,float,float,float,float,quint64)), this, SLOT(updatePositionSetpoints(int,float,float,float,float,quint64))); - connect(uas, SIGNAL(userPositionSetPointsChanged(int,float,float,float,float)), this, SLOT(updateUserPositionSetpoints(int,float,float,float,float))); - connect(uas, SIGNAL(speedChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateSpeed(UASInterface*,double,double,double,quint64))); - connect(uas, SIGNAL(attitudeChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateAttitude(UASInterface*,double,double,double,quint64))); - - connect(uas, SIGNAL(attitudeControlEnabled(bool)), this, SLOT(updateAttitudeControllerEnabled(bool))); - connect(uas, SIGNAL(positionXYControlEnabled(bool)), this, SLOT(updatePositionXYControllerEnabled(bool))); - connect(uas, SIGNAL(positionZControlEnabled(bool)), this, SLOT(updatePositionZControllerEnabled(bool))); - connect(uas, SIGNAL(positionYawControlEnabled(bool)), this, SLOT(updatePositionYawControllerEnabled(bool))); - - connect(uas, SIGNAL(localizationChanged(UASInterface*,int)), this, SLOT(updateLocalization(UASInterface*,int))); - connect(uas, SIGNAL(visionLocalizationChanged(UASInterface*,int)), this, SLOT(updateVisionLocalization(UASInterface*,int))); - connect(uas, SIGNAL(gpsLocalizationChanged(UASInterface*,int)), this, SLOT(updateGpsLocalization(UASInterface*,int))); - connect(uas, SIGNAL(irUltraSoundLocalizationChanged(UASInterface*,int)), this, SLOT(updateInfraredUltrasoundLocalization(UASInterface*,int))); - connect(uas, SIGNAL(objectDetected(uint,int,int,QString,int,float,float)), this, SLOT(updateObjectPosition(uint,int,int,QString,int,float,float))); - - connect(uas, SIGNAL(gyroStatusChanged(bool,bool,bool)), this, SLOT(updateGyroStatus(bool,bool,bool))); - connect(uas, SIGNAL(accelStatusChanged(bool,bool,bool)), this, SLOT(updateAccelStatus(bool,bool,bool))); - connect(uas, SIGNAL(magSensorStatusChanged(bool,bool,bool)), this, SLOT(updateMagSensorStatus(bool,bool,bool))); - connect(uas, SIGNAL(baroStatusChanged(bool,bool,bool)), this, SLOT(updateBaroStatus(bool,bool,bool))); - connect(uas, SIGNAL(airspeedStatusChanged(bool,bool,bool)), this, SLOT(updateAirspeedStatus(bool,bool,bool))); - connect(uas, SIGNAL(opticalFlowStatusChanged(bool,bool,bool)), this, SLOT(updateOpticalFlowStatus(bool,bool,bool))); - connect(uas, SIGNAL(laserStatusChanged(bool,bool,bool)), this, SLOT(updateLaserStatus(bool,bool,bool))); - connect(uas, SIGNAL(groundTruthSensorStatusChanged(bool,bool,bool)), this, SLOT(updateGroundTruthSensorStatus(bool,bool,bool))); - connect(uas, SIGNAL(actuatorStatusChanged(bool,bool,bool)), this, SLOT(updateActuatorStatus(bool,bool,bool))); + if (uas) + { + connect(uas, SIGNAL(gpsSatelliteStatusChanged(int,int,float,float,float,bool)), this, SLOT(updateSatellite(int,int,float,float,float,bool))); + connect(uas, SIGNAL(localPositionChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateLocalPosition(UASInterface*,double,double,double,quint64))); + connect(uas, SIGNAL(globalPositionChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateGlobalPosition(UASInterface*,double,double,double,quint64))); + connect(uas, SIGNAL(attitudeThrustSetPointChanged(UASInterface*,double,double,double,double,quint64)), this, SLOT(updateAttitudeSetpoints(UASInterface*,double,double,double,double,quint64))); + connect(uas, SIGNAL(positionSetPointsChanged(int,float,float,float,float,quint64)), this, SLOT(updatePositionSetpoints(int,float,float,float,float,quint64))); + connect(uas, SIGNAL(userPositionSetPointsChanged(int,float,float,float,float)), this, SLOT(updateUserPositionSetpoints(int,float,float,float,float))); + connect(uas, SIGNAL(speedChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateSpeed(UASInterface*,double,double,double,quint64))); + connect(uas, SIGNAL(attitudeChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateAttitude(UASInterface*,double,double,double,quint64))); + + connect(uas, SIGNAL(attitudeControlEnabled(bool)), this, SLOT(updateAttitudeControllerEnabled(bool))); + connect(uas, SIGNAL(positionXYControlEnabled(bool)), this, SLOT(updatePositionXYControllerEnabled(bool))); + connect(uas, SIGNAL(positionZControlEnabled(bool)), this, SLOT(updatePositionZControllerEnabled(bool))); + connect(uas, SIGNAL(positionYawControlEnabled(bool)), this, SLOT(updatePositionYawControllerEnabled(bool))); + + connect(uas, SIGNAL(localizationChanged(UASInterface*,int)), this, SLOT(updateLocalization(UASInterface*,int))); + connect(uas, SIGNAL(visionLocalizationChanged(UASInterface*,int)), this, SLOT(updateVisionLocalization(UASInterface*,int))); + connect(uas, SIGNAL(gpsLocalizationChanged(UASInterface*,int)), this, SLOT(updateGpsLocalization(UASInterface*,int))); + connect(uas, SIGNAL(irUltraSoundLocalizationChanged(UASInterface*,int)), this, SLOT(updateInfraredUltrasoundLocalization(UASInterface*,int))); + connect(uas, SIGNAL(objectDetected(uint,int,int,QString,int,float,float)), this, SLOT(updateObjectPosition(uint,int,int,QString,int,float,float))); + + connect(uas, SIGNAL(gyroStatusChanged(bool,bool,bool)), this, SLOT(updateGyroStatus(bool,bool,bool))); + connect(uas, SIGNAL(accelStatusChanged(bool,bool,bool)), this, SLOT(updateAccelStatus(bool,bool,bool))); + connect(uas, SIGNAL(magSensorStatusChanged(bool,bool,bool)), this, SLOT(updateMagSensorStatus(bool,bool,bool))); + connect(uas, SIGNAL(baroStatusChanged(bool,bool,bool)), this, SLOT(updateBaroStatus(bool,bool,bool))); + connect(uas, SIGNAL(airspeedStatusChanged(bool,bool,bool)), this, SLOT(updateAirspeedStatus(bool,bool,bool))); + connect(uas, SIGNAL(opticalFlowStatusChanged(bool,bool,bool)), this, SLOT(updateOpticalFlowStatus(bool,bool,bool))); + connect(uas, SIGNAL(laserStatusChanged(bool,bool,bool)), this, SLOT(updateLaserStatus(bool,bool,bool))); + connect(uas, SIGNAL(groundTruthSensorStatusChanged(bool,bool,bool)), this, SLOT(updateGroundTruthSensorStatus(bool,bool,bool))); + connect(uas, SIGNAL(actuatorStatusChanged(bool,bool,bool)), this, SLOT(updateActuatorStatus(bool,bool,bool))); + statusClearTimer.start(3000); + } + else + { + statusClearTimer.stop(); + } this->uas = 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); @@ -1091,7 +1089,7 @@ void HSIDisplay::updateAttitude(UASInterface* uas, double roll, double pitch, do void HSIDisplay::updateUserPositionSetpoints(int uasid, float xDesired, float yDesired, float zDesired, float yawDesired) { - Q_UNUSED(uasid); + Q_UNUSED(uasid); uiXSetCoordinate = xDesired; uiYSetCoordinate = yDesired; uiZSetCoordinate = zDesired; diff --git a/src/ui/HSIDisplay.h b/src/ui/HSIDisplay.h index 2ddcc6dd1d4b6b1e3d1c12304817805c5e05d38a..6ebfeb73880c4532fca3e752d087fd4b4a4faf54 100644 --- a/src/ui/HSIDisplay.h +++ b/src/ui/HSIDisplay.h @@ -52,7 +52,6 @@ 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/HUD.cc b/src/ui/HUD.cc index fcd3b28ebfaa6f81ac84f4b3a9b065d43cf99843..0e9c6b5ad24a6d4e4811a42d9691510e164c11bc 100644 --- a/src/ui/HUD.cc +++ b/src/ui/HUD.cc @@ -319,10 +319,10 @@ void HUD::setActiveUAS(UASInterface* uas) connect(u, SIGNAL(imageStarted(quint64)), this, SLOT(startImage(quint64))); connect(u, SIGNAL(imageReady(UASInterface*)), this, SLOT(copyImage())); } - - // Set new UAS - this->uas = uas; } + + // Set new UAS + this->uas = uas; } //void HUD::updateAttitudeThrustSetPoint(UASInterface* uas, double rollDesired, double pitchDesired, double yawDesired, double thrustDesired, quint64 msec) diff --git a/src/ui/QGCToolBar.cc b/src/ui/QGCToolBar.cc index 73d6d15b735821701b37b2b2e74798e61980765a..ff4ee2686995eca30fe06998f586ae10c3529607 100644 --- a/src/ui/QGCToolBar.cc +++ b/src/ui/QGCToolBar.cc @@ -166,7 +166,6 @@ void QGCToolBar::createUI() // 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()); @@ -288,8 +287,8 @@ void QGCToolBar::advancedActivityTriggered(QAction* action) void QGCToolBar::setActiveUAS(UASInterface* active) { - // Do nothing if system is the same or NULL - if ((active == NULL) || mav == active) return; + // Do nothing if system is the same + if (mav == active) return; // If switching UASes, disconnect the only one. if (mav) @@ -317,54 +316,43 @@ void QGCToolBar::setActiveUAS(UASInterface* active) // Connect new system mav = active; - connect(active, SIGNAL(statusChanged(UASInterface*,QString,QString)), this, SLOT(updateState(UASInterface*, QString,QString))); - connect(active, SIGNAL(modeChanged(int,QString,QString)), this, SLOT(updateMode(int,QString,QString))); - connect(active, SIGNAL(nameChanged(QString)), this, SLOT(updateName(QString))); - connect(active, SIGNAL(systemTypeSet(UASInterface*,uint)), this, SLOT(setSystemType(UASInterface*,uint))); - connect(active, SIGNAL(textMessageReceived(int,int,int,QString)), this, SLOT(receiveTextMessage(int,int,int,QString))); - connect(active, SIGNAL(batteryChanged(UASInterface*,double,double,int)), this, SLOT(updateBatteryRemaining(UASInterface*,double,double,int))); - connect(active, SIGNAL(armingChanged(bool)), this, SLOT(updateArmingState(bool))); - connect(active, SIGNAL(heartbeatTimeout(bool, unsigned int)), this, SLOT(heartbeatTimeout(bool,unsigned int))); - connect(active, SIGNAL(globalPositionChanged(UASInterface*,double,double,double,quint64)), this, SLOT(globalPositionChanged(UASInterface*,double,double,double,quint64))); - if (active->getWaypointManager()) + if (mav) { - connect(active->getWaypointManager(), SIGNAL(currentWaypointChanged(quint16)), this, SLOT(updateCurrentWaypoint(quint16))); - connect(active->getWaypointManager(), SIGNAL(waypointDistanceChanged(double)), this, SLOT(updateWaypointDistance(double))); - } - - // Update all values once - systemName = mav->getUASName(); - systemArmed = mav->isArmed(); - toolBarNameLabel->setText(mav->getUASName()); - toolBarNameLabel->setStyleSheet(QString("QLabel {color: %1;}").arg(mav->getColor().name())); - symbolLabel->setStyleSheet(QString("QWidget {background-color: %1;}").arg(mav->getColor().name())); - toolBarModeLabel->setText(mav->getShortMode()); - toolBarStateLabel->setText(mav->getShortState()); - toolBarTimeoutLabel->setText(""); - toolBarDistLabel->setText(""); - toolBarBatteryBar->setEnabled(true); - setSystemType(mav, mav->getSystemType()); -} + connect(mav, SIGNAL(statusChanged(UASInterface*,QString,QString)), this, SLOT(updateState(UASInterface*, QString,QString))); + connect(mav, SIGNAL(modeChanged(int,QString,QString)), this, SLOT(updateMode(int,QString,QString))); + connect(mav, SIGNAL(nameChanged(QString)), this, SLOT(updateName(QString))); + connect(mav, SIGNAL(systemTypeSet(UASInterface*,uint)), this, SLOT(setSystemType(UASInterface*,uint))); + connect(mav, SIGNAL(textMessageReceived(int,int,int,QString)), this, SLOT(receiveTextMessage(int,int,int,QString))); + connect(mav, SIGNAL(batteryChanged(UASInterface*,double,double,int)), this, SLOT(updateBatteryRemaining(UASInterface*,double,double,int))); + connect(mav, SIGNAL(armingChanged(bool)), this, SLOT(updateArmingState(bool))); + connect(mav, SIGNAL(heartbeatTimeout(bool, unsigned int)), this, SLOT(heartbeatTimeout(bool,unsigned int))); + connect(mav, SIGNAL(globalPositionChanged(UASInterface*,double,double,double,quint64)), this, SLOT(globalPositionChanged(UASInterface*,double,double,double,quint64))); + if (mav->getWaypointManager()) + { + connect(mav->getWaypointManager(), SIGNAL(currentWaypointChanged(quint16)), this, SLOT(updateCurrentWaypoint(quint16))); + connect(mav->getWaypointManager(), SIGNAL(waypointDistanceChanged(double)), this, SLOT(updateWaypointDistance(double))); + } -/** - * @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) { + // Update all values once + systemName = mav->getUASName(); + systemArmed = mav->isArmed(); + toolBarNameLabel->setText(mav->getUASName()); + toolBarNameLabel->setStyleSheet(QString("QLabel {color: %1;}").arg(mav->getColor().name())); + symbolLabel->setStyleSheet(QString("QWidget {background-color: %1;}").arg(mav->getColor().name())); + toolBarModeLabel->setText(mav->getShortMode()); + toolBarStateLabel->setText(mav->getShortState()); + toolBarTimeoutLabel->setText(""); + toolBarDistLabel->setText(""); + toolBarBatteryBar->setEnabled(true); + setSystemType(mav, mav->getSystemType()); + } + else + { updateViewTimer.stop(); resetToolbarUI(); - mav = NULL; } } -void QGCToolBar::createCustomWidgets() -{ - -} - void QGCToolBar::updateArmingState(bool armed) { systemArmed = armed; diff --git a/src/ui/QGCToolBar.h b/src/ui/QGCToolBar.h index 924fa6dbb8161496ba40be51ee7148c5b8534577..1d8c4d0da11b2dfb2c4fc019b6578ea4bd21ee04 100644 --- a/src/ui/QGCToolBar.h +++ b/src/ui/QGCToolBar.h @@ -46,8 +46,6 @@ 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 */ @@ -86,7 +84,6 @@ public slots: void advancedActivityTriggered(QAction* action); protected: - void createCustomWidgets(); void storeSettings(); void loadSettings(); void createUI(); diff --git a/src/ui/QGCVehicleConfig.cc b/src/ui/QGCVehicleConfig.cc index 181daba3eaf0341cc327a48555867624dedd183c..570ed95558b085102692e111d8e5fc3d73550a98 100644 --- a/src/ui/QGCVehicleConfig.cc +++ b/src/ui/QGCVehicleConfig.cc @@ -36,11 +36,6 @@ QGCVehicleConfig::QGCVehicleConfig(QWidget *parent) : ui(new Ui::QGCVehicleConfig) { doneLoadingConfig = false; - systemTypeToParamMap["FIXED_WING"] = new QMap(); - systemTypeToParamMap["QUADROTOR"] = new QMap(); - systemTypeToParamMap["GROUND_ROVER"] = new QMap(); - systemTypeToParamMap["BOAT"] = new QMap(); - libParamToWidgetMap = new QMap(); setObjectName("QGC_VEHICLECONFIG"); ui->setupUi(this); @@ -188,19 +183,21 @@ void QGCVehicleConfig::loadQgcConfig(bool primary) //TODO: Throw an error here too, no autopilot specific configuration qWarning() << "Invalid vehicle dir, no vehicle specific configuration will be loaded."; } + + // Generate widgets for the General tab. QGCToolWidget *tool; bool left = true; foreach (QString file,generaldir.entryList(QDir::Files | QDir::NoDotAndDotDot)) { if (file.toLower().endsWith(".qgw")) { - tool = new QGCToolWidget("", this); + QWidget* parent = left?ui->generalLeftContents:ui->generalRightContents; + tool = new QGCToolWidget("", parent); if (tool->loadSettings(generaldir.absoluteFilePath(file), false)) { toolWidgets.append(tool); - //ui->sensorLayout->addWidget(tool); - QGroupBox *box = new QGroupBox(this); + QGroupBox *box = new QGroupBox(parent); box->setTitle(tool->objectName()); - box->setLayout(new QVBoxLayout()); + box->setLayout(new QVBoxLayout(box)); box->layout()->addWidget(tool); if (left) { @@ -217,18 +214,20 @@ void QGCVehicleConfig::loadQgcConfig(bool primary) } } } + + // Generate widgets for the Advanced tab. left = true; foreach (QString file,vehicledir.entryList(QDir::Files | QDir::NoDotAndDotDot)) { if (file.toLower().endsWith(".qgw")) { - tool = new QGCToolWidget("", this); + QWidget* parent = left?ui->advancedLeftContents:ui->advancedRightContents; + tool = new QGCToolWidget("", parent); if (tool->loadSettings(vehicledir.absoluteFilePath(file), false)) { toolWidgets.append(tool); - //ui->sensorLayout->addWidget(tool); - QGroupBox *box = new QGroupBox(this); + QGroupBox *box = new QGroupBox(parent); box->setTitle(tool->objectName()); - box->setLayout(new QVBoxLayout()); + box->setLayout(new QVBoxLayout(box)); box->layout()->addWidget(tool); if (left) { @@ -246,17 +245,18 @@ void QGCVehicleConfig::loadQgcConfig(bool primary) } } - //Load tabs for general configuration + // Load tabs for general configuration foreach (QString dir,generaldir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) { QWidget *tab = new QWidget(ui->tabWidget); + additionalTabs.append(tab); ui->tabWidget->insertTab(2,tab,dir); - tab->setLayout(new QVBoxLayout()); + tab->setLayout(new QVBoxLayout(tab)); tab->show(); - QScrollArea *area = new QScrollArea(); + QScrollArea *area = new QScrollArea(tab); tab->layout()->addWidget(area); - QWidget *scrollArea = new QWidget(); - scrollArea->setLayout(new QVBoxLayout()); + QWidget *scrollArea = new QWidget(tab); + scrollArea->setLayout(new QVBoxLayout(tab)); area->setWidget(scrollArea); area->setWidgetResizable(true); area->show(); @@ -265,14 +265,14 @@ void QGCVehicleConfig::loadQgcConfig(bool primary) foreach (QString file,newdir.entryList(QDir::Files| QDir::NoDotAndDotDot)) { if (file.toLower().endsWith(".qgw")) { - tool = new QGCToolWidget("", this); + tool = new QGCToolWidget("", tab); if (tool->loadSettings(newdir.absoluteFilePath(file), false)) { toolWidgets.append(tool); //ui->sensorLayout->addWidget(tool); - QGroupBox *box = new QGroupBox(this); + QGroupBox *box = new QGroupBox(tab); box->setTitle(tool->objectName()); - box->setLayout(new QVBoxLayout()); + box->setLayout(new QVBoxLayout(tab)); box->layout()->addWidget(tool); scrollArea->layout()->addWidget(box); } else { @@ -282,17 +282,18 @@ void QGCVehicleConfig::loadQgcConfig(bool primary) } } - //Load tabs for vehicle specific configuration + // Load additional tabs for vehicle specific configuration foreach (QString dir,vehicledir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) { QWidget *tab = new QWidget(ui->tabWidget); + additionalTabs.append(tab); ui->tabWidget->insertTab(2,tab,dir); - tab->setLayout(new QVBoxLayout()); + tab->setLayout(new QVBoxLayout(tab)); tab->show(); - QScrollArea *area = new QScrollArea(); + QScrollArea *area = new QScrollArea(tab); tab->layout()->addWidget(area); - QWidget *scrollArea = new QWidget(); - scrollArea->setLayout(new QVBoxLayout()); + QWidget *scrollArea = new QWidget(tab); + scrollArea->setLayout(new QVBoxLayout(tab)); area->setWidget(scrollArea); area->setWidgetResizable(true); area->show(); @@ -302,15 +303,15 @@ void QGCVehicleConfig::loadQgcConfig(bool primary) foreach (QString file,newdir.entryList(QDir::Files| QDir::NoDotAndDotDot)) { if (file.toLower().endsWith(".qgw")) { - tool = new QGCToolWidget("", this); + tool = new QGCToolWidget("", tab); tool->addUAS(mav); if (tool->loadSettings(newdir.absoluteFilePath(file), false)) { toolWidgets.append(tool); //ui->sensorLayout->addWidget(tool); - QGroupBox *box = new QGroupBox(); + QGroupBox *box = new QGroupBox(tab); box->setTitle(tool->objectName()); - box->setLayout(new QVBoxLayout()); + box->setLayout(new QVBoxLayout(box)); box->layout()->addWidget(tool); scrollArea->layout()->addWidget(box); box->show(); @@ -322,30 +323,31 @@ void QGCVehicleConfig::loadQgcConfig(bool primary) } } - // Load calibration + // Load general calibration for autopilot //TODO: Handle this more gracefully, maybe have it scan the directory for multiple calibration entries? - tool = new QGCToolWidget("", this); + tool = new QGCToolWidget("", ui->sensorContents); tool->addUAS(mav); if (tool->loadSettings(autopilotdir.absolutePath() + "/general/calibration/calibration.qgw", false)) { toolWidgets.append(tool); - QGroupBox *box = new QGroupBox(this); + QGroupBox *box = new QGroupBox(ui->sensorContents); box->setTitle(tool->objectName()); - box->setLayout(new QVBoxLayout()); + box->setLayout(new QVBoxLayout(box)); box->layout()->addWidget(tool); ui->sensorLayout->addWidget(box); } else { delete tool; } - tool = new QGCToolWidget("", this); + // Load vehicle-specific autopilot configuration + tool = new QGCToolWidget("", ui->sensorContents); tool->addUAS(mav); if (tool->loadSettings(autopilotdir.absolutePath() + "/" + mav->getSystemTypeName().toLower() + "/calibration/calibration.qgw", false)) { toolWidgets.append(tool); - QGroupBox *box = new QGroupBox(this); + QGroupBox *box = new QGroupBox(ui->sensorContents); box->setTitle(tool->objectName()); - box->setLayout(new QVBoxLayout()); + box->setLayout(new QVBoxLayout(box)); box->layout()->addWidget(tool); ui->sensorLayout->addWidget(box); } else { @@ -391,7 +393,7 @@ void QGCVehicleConfig::loadConfig() QXmlStreamReader xml(xmlfile.readAll()); xmlfile.close(); - //TODO: Testing to ensure that incorrectly formated XML won't break this. + //TODO: Testing to ensure that incorrectly formatted XML won't break this. while (!xml.atEnd()) { if (xml.isStartElement() && xml.name() == "paramfile") @@ -571,7 +573,16 @@ void QGCVehicleConfig::loadConfig() } if (genarraycount > 0) { - tool = new QGCToolWidget("", this); + QWidget* parent = this; + if (valuetype == "vehicles") + { + parent = ui->generalLeftContents; + } + else if (valuetype == "libraries") + { + parent = ui->generalRightContents; + } + tool = new QGCToolWidget("", parent); tool->addUAS(mav); tool->setTitle(parametersname); tool->setObjectName(parametersname); @@ -582,26 +593,26 @@ void QGCVehicleConfig::loadConfig() //Based on the airframe, we add the parameter to different categories. if (parametersname == "ArduPlane") //MAV_TYPE_FIXED_WING FIXED_WING { - systemTypeToParamMap["FIXED_WING"]->insert(paramlist[i],tool); + systemTypeToParamMap["FIXED_WING"].insert(paramlist[i],tool); } else if (parametersname == "ArduCopter") //MAV_TYPE_QUADROTOR "QUADROTOR { - systemTypeToParamMap["QUADROTOR"]->insert(paramlist[i],tool); + systemTypeToParamMap["QUADROTOR"].insert(paramlist[i],tool); } else if (parametersname == "APMrover2") //MAV_TYPE_GROUND_ROVER GROUND_ROVER { - systemTypeToParamMap["GROUND_ROVER"]->insert(paramlist[i],tool); + systemTypeToParamMap["GROUND_ROVER"].insert(paramlist[i],tool); } else { - libParamToWidgetMap->insert(paramlist[i],tool); + libParamToWidgetMap.insert(paramlist[i],tool); } } toolWidgets.append(tool); - QGroupBox *box = new QGroupBox(this); + QGroupBox *box = new QGroupBox(parent); box->setTitle(tool->objectName()); - box->setLayout(new QVBoxLayout()); + box->setLayout(new QVBoxLayout(box)); box->layout()->addWidget(tool); if (valuetype == "vehicles") { @@ -616,7 +627,16 @@ void QGCVehicleConfig::loadConfig() } if (advarraycount > 0) { - tool = new QGCToolWidget("", this); + QWidget* parent = this; + if (valuetype == "vehicles") + { + parent = ui->generalLeftContents; + } + else if (valuetype == "libraries") + { + parent = ui->generalRightContents; + } + tool = new QGCToolWidget("", parent); tool->addUAS(mav); tool->setTitle(parametersname); tool->setObjectName(parametersname); @@ -627,48 +647,42 @@ void QGCVehicleConfig::loadConfig() //Based on the airframe, we add the parameter to different categories. if (parametersname == "ArduPlane") //MAV_TYPE_FIXED_WING FIXED_WING { - systemTypeToParamMap["FIXED_WING"]->insert(paramlist[i],tool); + systemTypeToParamMap["FIXED_WING"].insert(paramlist[i],tool); } else if (parametersname == "ArduCopter") //MAV_TYPE_QUADROTOR "QUADROTOR { - systemTypeToParamMap["QUADROTOR"]->insert(paramlist[i],tool); + systemTypeToParamMap["QUADROTOR"].insert(paramlist[i],tool); } else if (parametersname == "APMrover2") //MAV_TYPE_GROUND_ROVER GROUND_ROVER { - systemTypeToParamMap["GROUND_ROVER"]->insert(paramlist[i],tool); + systemTypeToParamMap["GROUND_ROVER"].insert(paramlist[i],tool); } else { - libParamToWidgetMap->insert(paramlist[i],tool); + libParamToWidgetMap.insert(paramlist[i],tool); } } toolWidgets.append(tool); - QGroupBox *box = new QGroupBox(this); + QGroupBox *box = new QGroupBox(parent); box->setTitle(tool->objectName()); - box->setLayout(new QVBoxLayout()); + box->setLayout(new QVBoxLayout(box)); box->layout()->addWidget(tool); if (valuetype == "vehicles") { - ui->leftAdvancedLayout->addWidget(box); + ui->leftGeneralLayout->addWidget(box); } else if (valuetype == "libraries") { - ui->rightAdvancedLayout->addWidget(box); + ui->rightGeneralLayout->addWidget(box); } box->hide(); toolToBoxMap[tool] = box; } - - - - } xml.readNext(); } - } - xml.readNext(); } } @@ -682,8 +696,8 @@ void QGCVehicleConfig::loadConfig() void QGCVehicleConfig::setActiveUAS(UASInterface* active) { - // Do nothing if system is the same or NULL - if ((active == NULL) || mav == active) return; + // Do nothing if system is the same + if (mav == active) return; if (mav) { @@ -693,11 +707,41 @@ void QGCVehicleConfig::setActiveUAS(UASInterface* active) disconnect(mav, SIGNAL(parameterChanged(int,int,QString,QVariant)), this, SLOT(parameterChanged(int,int,QString,QVariant))); - foreach (QGCToolWidget* tool, toolWidgets) + // Delete all children from all fixed tabs. + foreach(QWidget* child, ui->generalLeftContents->findChildren()) + { + child->deleteLater(); + } + foreach(QWidget* child, ui->generalRightContents->findChildren()) + { + child->deleteLater(); + } + foreach(QWidget* child, ui->advancedLeftContents->findChildren()) + { + child->deleteLater(); + } + foreach(QWidget* child, ui->advancedRightContents->findChildren()) + { + child->deleteLater(); + } + foreach(QWidget* child, ui->sensorContents->findChildren()) + { + child->deleteLater(); + } + + // And then delete any custom tabs + foreach(QWidget* child, additionalTabs) { - delete tool; + child->deleteLater(); } + additionalTabs.clear(); + toolWidgets.clear(); + paramToWidgetMap = NULL; + libParamToWidgetMap.clear(); + systemTypeToParamMap.clear(); + toolToBoxMap.clear(); + paramTooltips.clear(); } // Reset current state @@ -707,44 +751,57 @@ void QGCVehicleConfig::setActiveUAS(UASInterface* active) // Connect new system mav = active; - connect(active, SIGNAL(remoteControlChannelRawChanged(int,float)), this, - SLOT(remoteControlChannelRawChanged(int,float))); - connect(active, SIGNAL(parameterChanged(int,int,QString,QVariant)), this, - SLOT(parameterChanged(int,int,QString,QVariant))); - - if (systemTypeToParamMap.contains(mav->getSystemTypeName())) - { - paramToWidgetMap = systemTypeToParamMap[mav->getSystemTypeName()]; - } - else + if (mav) { - //Indication that we have no meta data for this system type. - qDebug() << "No parameters defined for system type:" << mav->getSystemTypeName(); - systemTypeToParamMap[mav->getSystemTypeName()] = new QMap(); - paramToWidgetMap = systemTypeToParamMap[mav->getSystemTypeName()]; - } + connect(active, SIGNAL(remoteControlChannelRawChanged(int,float)), this, + SLOT(remoteControlChannelRawChanged(int,float))); + connect(active, SIGNAL(parameterChanged(int,int,QString,QVariant)), this, + SLOT(parameterChanged(int,int,QString,QVariant))); - if (!paramTooltips.isEmpty()) - { - mav->getParamManager()->setParamInfo(paramTooltips); - } + if (systemTypeToParamMap.contains(mav->getSystemTypeName())) + { + paramToWidgetMap = &systemTypeToParamMap[mav->getSystemTypeName()]; + } + else + { + //Indication that we have no meta data for this system type. + qDebug() << "No parameters defined for system type:" << mav->getSystemTypeName(); + paramToWidgetMap = &systemTypeToParamMap[mav->getSystemTypeName()]; + } - qDebug() << "CALIBRATION!! System Type Name:" << mav->getSystemTypeName(); + if (!paramTooltips.isEmpty()) + { + mav->getParamManager()->setParamInfo(paramTooltips); + } + + qDebug() << "CALIBRATION!! System Type Name:" << mav->getSystemTypeName(); - //Load configuration after 1ms. This allows it to go into the event loop, and prevents application hangups due to the - //amount of time it actually takes to load the configuration windows. - QTimer::singleShot(1,this,SLOT(loadConfig())); + //Load configuration after 1ms. This allows it to go into the event loop, and prevents application hangups due to the + //amount of time it actually takes to load the configuration windows. + QTimer::singleShot(1,this,SLOT(loadConfig())); - updateStatus(QString("Reading from system %1").arg(mav->getUASName())); + updateStatus(QString("Reading from system %1").arg(mav->getUASName())); - // Since a system is now connected, enable the VehicleConfig UI. - ui->tabWidget->setEnabled(true); - ui->setButton->setEnabled(true); - ui->refreshButton->setEnabled(true); - ui->readButton->setEnabled(true); - ui->writeButton->setEnabled(true); - ui->loadFileButton->setEnabled(true); - ui->saveFileButton->setEnabled(true); + // Since a system is now connected, enable the VehicleConfig UI. + ui->tabWidget->setEnabled(true); + ui->setButton->setEnabled(true); + ui->refreshButton->setEnabled(true); + ui->readButton->setEnabled(true); + ui->writeButton->setEnabled(true); + ui->loadFileButton->setEnabled(true); + ui->saveFileButton->setEnabled(true); + } + else + { + // Disable the vehicle config widget if no new UAS has been enabled. + ui->tabWidget->setEnabled(false); + ui->setButton->setEnabled(false); + ui->refreshButton->setEnabled(false); + ui->readButton->setEnabled(false); + ui->writeButton->setEnabled(false); + ui->loadFileButton->setEnabled(false); + ui->saveFileButton->setEnabled(false); + } } void QGCVehicleConfig::resetCalibrationRC() @@ -986,13 +1043,13 @@ void QGCVehicleConfig::parameterChanged(int uas, int component, QString paramete qCritical() << "Widget with no box, possible memory corruption for param:" << parameterName; } } - else if (libParamToWidgetMap->contains(parameterName)) + else if (libParamToWidgetMap.contains(parameterName)) { //All the library parameters - libParamToWidgetMap->value(parameterName)->setParameterValue(uas,component,parameterName,value); - if (toolToBoxMap.contains(libParamToWidgetMap->value(parameterName))) + libParamToWidgetMap.value(parameterName)->setParameterValue(uas,component,parameterName,value); + if (toolToBoxMap.contains(libParamToWidgetMap.value(parameterName))) { - toolToBoxMap[libParamToWidgetMap->value(parameterName)]->show(); + toolToBoxMap[libParamToWidgetMap.value(parameterName)]->show(); } else { @@ -1010,7 +1067,7 @@ void QGCVehicleConfig::parameterChanged(int uas, int component, QString paramete { //It should be grouped with this one, add it. toolWidgets[i]->addParam(uas,component,parameterName,value); - libParamToWidgetMap->insert(parameterName,toolWidgets[i]); + libParamToWidgetMap.insert(parameterName,toolWidgets[i]); found = true; break; } @@ -1018,7 +1075,18 @@ void QGCVehicleConfig::parameterChanged(int uas, int component, QString paramete if (!found) { //New param type, create a QGroupBox for it. - QGCToolWidget *tool = new QGCToolWidget("", this); + QWidget* parent; + if (ui->leftAdvancedLayout->count() > ui->rightAdvancedLayout->count()) + { + parent = ui->advancedRightContents; + } + else + { + parent = ui->advancedLeftContents; + } + + // Create the tool, attaching it to the QGroupBox + QGCToolWidget *tool = new QGCToolWidget("", parent); QString tooltitle = parameterName; if (parameterName.split("_").size() > 1) { @@ -1026,15 +1094,15 @@ void QGCVehicleConfig::parameterChanged(int uas, int component, QString paramete } tool->setTitle(tooltitle); tool->setObjectName(tooltitle); - //tool->setSettings(set); - tool->addParam(uas,component,parameterName,value); - libParamToWidgetMap->insert(parameterName,tool); - toolWidgets.append(tool); - QGroupBox *box = new QGroupBox(this); + tool->addParam(uas, component, parameterName, value); + QGroupBox *box = new QGroupBox(parent); box->setTitle(tool->objectName()); - box->setLayout(new QVBoxLayout()); + box->setLayout(new QVBoxLayout(box)); box->layout()->addWidget(tool); + libParamToWidgetMap.insert(parameterName,tool); + toolWidgets.append(tool); + //Make sure we have similar number of widgets on each side. if (ui->leftAdvancedLayout->count() > ui->rightAdvancedLayout->count()) diff --git a/src/ui/QGCVehicleConfig.h b/src/ui/QGCVehicleConfig.h index 242c11b20233cda7c2d3523db943b266ace17feb..9b6a6e83e789e24ce9acc73b5512bfb9e108361c 100644 --- a/src/ui/QGCVehicleConfig.h +++ b/src/ui/QGCVehicleConfig.h @@ -16,7 +16,7 @@ class QGCVehicleConfig; class QGCVehicleConfig : public QWidget { Q_OBJECT - + public: explicit QGCVehicleConfig(QWidget *parent = 0); ~QGCVehicleConfig(); @@ -175,12 +175,13 @@ protected: QList toolWidgets; ///< Configurable widgets bool calibrationEnabled; ///< calibration mode on / off - QMap *paramToWidgetMap; ///< Holds the current active MAV's parameter widgets. - QMap *libParamToWidgetMap; ///< Holds the library parameter widgets - QMap*> systemTypeToParamMap; ///< Holds all loaded MAV specific parameter widgets, for every MAV. + QMap* paramToWidgetMap; ///< Holds the current active MAV's parameter widgets. + QList additionalTabs; ///< Stores additional tabs loaded for this vehicle/autopilot configuration. Used for cleaning up. + QMap libParamToWidgetMap; ///< Holds the library parameter widgets + QMap > systemTypeToParamMap; ///< Holds all loaded MAV specific parameter widgets, for every MAV. QMap toolToBoxMap; ///< Easy method of figuring out which QGroupBox is tied to which ToolWidget. QMap paramTooltips; ///< Tooltips for the ? button next to a parameter. - + private: Ui::QGCVehicleConfig *ui; diff --git a/src/ui/QGCVehicleConfig.ui b/src/ui/QGCVehicleConfig.ui index 9e3fccb66804c109c32a8262e2d7554c668dce25..72ed1c3d640b7795b8788eafb64d821c285c96e9 100644 --- a/src/ui/QGCVehicleConfig.ui +++ b/src/ui/QGCVehicleConfig.ui @@ -35,7 +35,7 @@ - 3 + 0 @@ -765,7 +765,7 @@ p, li { white-space: pre-wrap; } true - + 0 @@ -849,7 +849,7 @@ p, li { white-space: pre-wrap; } true - + 0 @@ -886,7 +886,7 @@ p, li { white-space: pre-wrap; } true - + 0 @@ -983,7 +983,7 @@ p, li { white-space: pre-wrap; } true - + 0 @@ -1036,7 +1036,7 @@ p, li { white-space: pre-wrap; } true - + 0 diff --git a/src/ui/map/QGCMapWidget.cc b/src/ui/map/QGCMapWidget.cc index d52994aae944f9219e4b70701e5ff9efa0dbc17c..2088de9c152d549ac70f3e456d97b64f5bd6979d 100644 --- a/src/ui/map/QGCMapWidget.cc +++ b/src/ui/map/QGCMapWidget.cc @@ -302,7 +302,6 @@ void QGCMapWidget::addUAS(UASInterface* uas) void QGCMapWidget::activeUASSet(UASInterface* uas) { // Only execute if proper UAS is set - if (!uas) return; this->uas = uas; // Disconnect old MAV manager @@ -315,17 +314,26 @@ void QGCMapWidget::activeUASSet(UASInterface* uas) disconnect(this, SIGNAL(waypointChanged(Waypoint*)), currWPManager, SLOT(notifyOfChangeEditable(Waypoint*))); } - currWPManager = uas->getWaypointManager(); + // Attach the new waypoint manager if a new UAS was selected. Otherwise, indicate + // that no such manager exists. + if (uas) + { + currWPManager = uas->getWaypointManager(); - updateSelectedSystem(uas->getUASID()); - followUAVID = uas->getUASID(); - updateWaypointList(uas->getUASID()); + updateSelectedSystem(uas->getUASID()); + followUAVID = uas->getUASID(); + updateWaypointList(uas->getUASID()); - // Connect the waypoint manager / data storage to the UI - connect(currWPManager, SIGNAL(waypointEditableListChanged(int)), this, SLOT(updateWaypointList(int))); - connect(currWPManager, SIGNAL(waypointEditableChanged(int, Waypoint*)), this, SLOT(updateWaypoint(int,Waypoint*))); - connect(this, SIGNAL(waypointCreated(Waypoint*)), currWPManager, SLOT(addWaypointEditable(Waypoint*))); - connect(this, SIGNAL(waypointChanged(Waypoint*)), currWPManager, SLOT(notifyOfChangeEditable(Waypoint*))); + // Connect the waypoint manager / data storage to the UI + connect(currWPManager, SIGNAL(waypointEditableListChanged(int)), this, SLOT(updateWaypointList(int))); + connect(currWPManager, SIGNAL(waypointEditableChanged(int, Waypoint*)), this, SLOT(updateWaypoint(int,Waypoint*))); + connect(this, SIGNAL(waypointCreated(Waypoint*)), currWPManager, SLOT(addWaypointEditable(Waypoint*))); + connect(this, SIGNAL(waypointChanged(Waypoint*)), currWPManager, SLOT(notifyOfChangeEditable(Waypoint*))); + } + else + { + currWPManager = NULL; + } } /** diff --git a/src/ui/map3D/Pixhawk3DWidget.cc b/src/ui/map3D/Pixhawk3DWidget.cc index ee535434fb52c794d9c00521a370cc67bb79d8ba..43931008e0ce3e76d8dd7e0b69d89037efd0193c 100644 --- a/src/ui/map3D/Pixhawk3DWidget.cc +++ b/src/ui/map3D/Pixhawk3DWidget.cc @@ -113,7 +113,10 @@ Pixhawk3DWidget::~Pixhawk3DWidget() void Pixhawk3DWidget::activeSystemChanged(UASInterface* uas) { - mActiveSystemId = uas->getUASID(); + if (uas) + { + mActiveSystemId = uas->getUASID(); + } mActiveUAS = uas; diff --git a/src/ui/uas/UASControlWidget.cc b/src/ui/uas/UASControlWidget.cc index 6632aa3276b936518a54e0344e6e6bd8865d9d60..904e73c2ca30ac3435a218d31a31e535a0b6834c 100644 --- a/src/ui/uas/UASControlWidget.cc +++ b/src/ui/uas/UASControlWidget.cc @@ -70,7 +70,7 @@ UASControlWidget::UASControlWidget(QWidget *parent) : QWidget(parent), void UASControlWidget::setUAS(UASInterface* uas) { - if (this->uas != 0) + if (this->uas) { UASInterface* oldUAS = UASManager::instance()->getUASForId(this->uas); disconnect(ui.controlButton, SIGNAL(clicked()), oldUAS, SLOT(armSystem())); @@ -83,18 +83,25 @@ void UASControlWidget::setUAS(UASInterface* uas) } // Connect user interface controls - connect(ui.controlButton, SIGNAL(clicked()), this, SLOT(cycleContextButton())); - connect(ui.liftoffButton, SIGNAL(clicked()), uas, SLOT(launch())); - connect(ui.landButton, SIGNAL(clicked()), uas, SLOT(home())); - connect(ui.shutdownButton, SIGNAL(clicked()), uas, SLOT(shutdown())); - //connect(ui.setHomeButton, SIGNAL(clicked()), uas, SLOT(setLocalOriginAtCurrentGPSPosition())); - connect(uas, SIGNAL(modeChanged(int,QString,QString)), this, SLOT(updateMode(int,QString,QString))); - connect(uas, SIGNAL(statusChanged(int)), this, SLOT(updateState(int))); - - ui.controlStatusLabel->setText(tr("Connected to ") + uas->getUASName()); - - this->uas = uas->getUASID(); - setBackgroundColor(uas->getColor()); + if (uas) + { + connect(ui.controlButton, SIGNAL(clicked()), this, SLOT(cycleContextButton())); + connect(ui.liftoffButton, SIGNAL(clicked()), uas, SLOT(launch())); + connect(ui.landButton, SIGNAL(clicked()), uas, SLOT(home())); + connect(ui.shutdownButton, SIGNAL(clicked()), uas, SLOT(shutdown())); + //connect(ui.setHomeButton, SIGNAL(clicked()), uas, SLOT(setLocalOriginAtCurrentGPSPosition())); + connect(uas, SIGNAL(modeChanged(int,QString,QString)), this, SLOT(updateMode(int,QString,QString))); + connect(uas, SIGNAL(statusChanged(int)), this, SLOT(updateState(int))); + + ui.controlStatusLabel->setText(tr("Connected to ") + uas->getUASName()); + + this->uas = uas->getUASID(); + setBackgroundColor(uas->getColor()); + } + else + { + this->uas = -1; + } } UASControlWidget::~UASControlWidget() diff --git a/src/ui/uas/UASListWidget.cc b/src/ui/uas/UASListWidget.cc index 0c3343344fb71197ecc3b090e5d2e4683a9fc278..4014bc525a8c864bae4ac1c1375890c55787fd22 100644 --- a/src/ui/uas/UASListWidget.cc +++ b/src/ui/uas/UASListWidget.cc @@ -56,15 +56,21 @@ UASListWidget::UASListWidget(QWidget *parent) : QWidget(parent), m_ui->verticalLayout->addWidget(uWidget); linkToBoxMapping = QMap(); + uasToBoxMapping = QMap(); uasViews = QMap(); this->setVisible(false); + // Listen for when UASes are added or removed. This does not manage the UASView + // widgets that are displayed within this widget. connect(UASManager::instance(), SIGNAL(UASCreated(UASInterface*)), this, SLOT(addUAS(UASInterface*))); + connect(UASManager::instance(), SIGNAL(UASDeleted(UASInterface*)), + this, SLOT(removeUAS(UASInterface*))); // Get a list of all existing UAS - foreach (UASInterface* uas, UASManager::instance()->getUASList()) { + foreach (UASInterface* uas, UASManager::instance()->getUASList()) + { addUAS(uas); } } @@ -94,7 +100,7 @@ void UASListWidget::addUAS(UASInterface* uas) if (uasViews.isEmpty()) { m_ui->verticalLayout->removeWidget(uWidget); - delete uWidget; + uWidget->deleteLater(); uWidget = NULL; } @@ -125,6 +131,7 @@ void UASListWidget::addUAS(UASInterface* uas) // And add the new UAS to the UASList UASView* newView = new UASView(uas, newBox); uasViews.insert(uas, newView); + uasToBoxMapping[uas] = newBox; newBox->layout()->addWidget(newView); // Watch for when this widget is destroyed so that we can clean up the @@ -149,30 +156,49 @@ void UASListWidget::activeUAS(UASInterface* uas) */ void UASListWidget::removeUAS(UASInterface* uas) { - // Remove the UAS from our data structures and - // the global listing. + // Remove the UASView and check if its parent GroupBox has any other children, + // delete it if it doesn't. + QGroupBox* box = uasToBoxMapping[uas]; + uasToBoxMapping.remove(uas); 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()) + int otherViews = 0; + foreach (UASView* view, box->findChildren()) { - LinkInterface* link = i.next(); + if (view->uas == uas) + { + view->deleteLater(); + } + else + { + ++otherViews; + } + } + if (otherViews == 0) + { + // Delete the groupbox. + QMap::const_iterator i = linkToBoxMapping.constBegin(); + while (i != linkToBoxMapping.constEnd()) { + if (i.value() == box) + { + linkToBoxMapping.remove(i.key()); + } + ++i; + } + box->deleteLater(); - QGroupBox* box = linkToBoxMapping[link]; - if (box) + // And if no other QGroupBoxes are left, put the initial widget back. + int otherBoxes = 0; + foreach (const QGroupBox* otherBox, findChildren()) { - // 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); + if (otherBox != box) + { + ++otherBoxes; } } + if (otherBoxes == 0) + { + 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 58c5fafc6245600de4cbac0db494476fcd9058fc..fc1439e216896fe31a92fa1b4c1d2a89851d8f5a 100644 --- a/src/ui/uas/UASListWidget.h +++ b/src/ui/uas/UASListWidget.h @@ -33,6 +33,7 @@ This file is part of the QGROUNDCONTROL project #include #include +#include #include #include #include "UASInterface.h" @@ -54,9 +55,11 @@ public slots: void removeUAS(UASInterface* uas); protected: + // Keep a mapping from UASes to their GroupBox. Useful for determining when groupboxes are empty. + QMap uasToBoxMapping; // Keep a mapping from Links to GroupBoxes for adding new links. QMap linkToBoxMapping; - // Tie each view to their UAS object. + // Tie each view to their UAS object so they can be removed easily. QMap uasViews; QGCUnconnectedInfoWidget* uWidget; void changeEvent(QEvent *e); diff --git a/src/ui/uas/UASQuickView.cc b/src/ui/uas/UASQuickView.cc index 42dd9bc0899f10671019cec342e37aa1965cb849..226e156bdb620c131831afc7d2802e905b09b06a 100644 --- a/src/ui/uas/UASQuickView.cc +++ b/src/ui/uas/UASQuickView.cc @@ -17,61 +17,61 @@ UASQuickView::UASQuickView(QWidget *parent) : { - QAction *action = new QAction("latitude",this); + QAction *action = new QAction(tr("latitude"),this); action->setCheckable(true); action->setChecked(true); connect(action,SIGNAL(toggled(bool)),this,SLOT(actionTriggered(bool))); this->addAction(action); UASQuickViewItem *item = new UASQuickViewItem(this); - item->setTitle("latitude"); + item->setTitle(tr("latitude")); this->layout()->addWidget(item); uasPropertyToLabelMap["latitude"] = item; } { - QAction *action = new QAction("longitude",this); + QAction *action = new QAction(tr("longitude"),this); action->setCheckable(true); action->setChecked(true); connect(action,SIGNAL(toggled(bool)),this,SLOT(actionTriggered(bool))); this->addAction(action); UASQuickViewItem *item = new UASQuickViewItem(this); - item->setTitle("longitude"); + item->setTitle(tr("longitude")); this->layout()->addWidget(item); uasPropertyToLabelMap["longitude"] = item; } { - QAction *action = new QAction("altitude",this); + QAction *action = new QAction(tr("altitude"),this); action->setCheckable(true); action->setChecked(true); connect(action,SIGNAL(toggled(bool)),this,SLOT(actionTriggered(bool))); this->addAction(action); UASQuickViewItem *item = new UASQuickViewItem(this); - item->setTitle("altitude"); + item->setTitle(tr("altitude")); this->layout()->addWidget(item); uasPropertyToLabelMap["altitude"] = item; } { - QAction *action = new QAction("satelliteCount",this); + QAction *action = new QAction(tr("satelliteCount"),this); action->setCheckable(true); action->setChecked(true); connect(action,SIGNAL(toggled(bool)),this,SLOT(actionTriggered(bool))); this->addAction(action); UASQuickViewItem *item = new UASQuickViewItem(this); - item->setTitle("satelliteCount"); + item->setTitle(tr("satelliteCount")); this->layout()->addWidget(item); uasPropertyToLabelMap["satelliteCount"] = item; } { - QAction *action = new QAction("distToWaypoint",this); + QAction *action = new QAction(tr("distToWaypoint"),this); action->setCheckable(true); action->setChecked(true); connect(action,SIGNAL(toggled(bool)),this,SLOT(actionTriggered(bool))); this->addAction(action); UASQuickViewItem *item = new UASQuickViewItem(this); - item->setTitle("distToWaypoint"); + item->setTitle(tr("distToWaypoint")); this->layout()->addWidget(item); uasPropertyToLabelMap["distToWaypoint"] = item; } diff --git a/src/ui/uas/UASView.cc b/src/ui/uas/UASView.cc index df50d922a9a4f93b29d8ca9d8a43295aefe9d58e..7d238c55391462670a36be52e3484f1a0cc76684 100644 --- a/src/ui/uas/UASView.cc +++ b/src/ui/uas/UASView.cc @@ -43,48 +43,48 @@ This file is part of the PIXHAWK project #include UASView::UASView(UASInterface* uas, QWidget *parent) : - QWidget(parent), - startTime(0), - timeout(false), - iconIsRed(true), - disconnected(false), - timeRemaining(0), - chargeLevel(0), - uas(uas), - load(0), - state("UNKNOWN"), - stateDesc(tr("Unknown state")), - mode("MAV_MODE_UNKNOWN"), - thrust(0), - isActive(false), - x(0), - y(0), - z(0), - totalSpeed(0), - lat(0), - lon(0), - alt(0), - groundDistance(0), - localFrame(false), - globalFrameKnown(false), - removeAction(new QAction("Delete this system", this)), - renameAction(new QAction("Rename..", this)), - selectAction(new QAction("Control this system", this )), - hilAction(new QAction("HIL - Hardware in the Loop", this )), - selectAirframeAction(new QAction("Choose Airframe", this)), - setBatterySpecsAction(new QAction("Set Battery Options", this)), - lowPowerModeEnabled(true), - generalUpdateCount(0), - filterTime(0), - m_ui(new Ui::UASView) + QWidget(parent), + uas(uas), + startTime(0), + timeout(false), + iconIsRed(true), + disconnected(false), + timeRemaining(0), + chargeLevel(0), + load(0), + state("UNKNOWN"), + stateDesc(tr("Unknown state")), + mode("MAV_MODE_UNKNOWN"), + thrust(0), + isActive(false), + x(0), + y(0), + z(0), + totalSpeed(0), + lat(0), + lon(0), + alt(0), + groundDistance(0), + localFrame(false), + globalFrameKnown(false), + removeAction(new QAction(tr("Delete this system"), this)), + renameAction(new QAction(tr("Rename.."), this)), + selectAction(new QAction(tr("Control this system"), this)), + hilAction(new QAction(tr("HIL - Hardware in the Loop"), this)), + selectAirframeAction(new QAction(tr("Choose Airframe"), this)), + setBatterySpecsAction(new QAction(tr("Set Battery Options"), this)), + lowPowerModeEnabled(true), + generalUpdateCount(0), + filterTime(0), + m_ui(new Ui::UASView) { + m_ui->setupUi(this); + // FIXME XXX lowPowerModeEnabled = MainWindow::instance()->lowPowerModeEnabled(); hilAction->setCheckable(true); - m_ui->setupUi(this); - // Setup communication //connect(uas, SIGNAL(valueChanged(int,QString,double,quint64)), this, SLOT(receiveValue(int,QString,double,quint64))); connect(uas, SIGNAL(batteryChanged(UASInterface*, double, double, int)), this, SLOT(updateBattery(UASInterface*, double, double, int))); @@ -116,8 +116,8 @@ UASView::UASView(UASInterface* uas, QWidget *parent) : connect(m_ui->killButton, SIGNAL(clicked()), uas, SLOT(emergencyKILL())); connect(m_ui->shutdownButton, SIGNAL(clicked()), uas, SLOT(shutdown())); - // Allow to delete this widget - connect(removeAction, SIGNAL(triggered()), this, SLOT(prepareForDeletion())); + // Allow deleting this widget + connect(removeAction, SIGNAL(triggered()), this, SLOT(triggerUASDeletion())); connect(renameAction, SIGNAL(triggered()), this, SLOT(rename())); connect(selectAction, SIGNAL(triggered()), uas, SLOT(setSelected())); connect(hilAction, SIGNAL(triggered(bool)), this, SLOT(showHILUi())); @@ -170,9 +170,6 @@ UASView::UASView(UASInterface* uas, QWidget *parent) : UASView::~UASView() { delete m_ui; - delete removeAction; - delete renameAction; - delete selectAction; } void UASView::heartbeatTimeout(bool timeout, unsigned int ms) @@ -561,23 +558,14 @@ 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() +void UASView::triggerUASDeletion() { refreshTimer->stop(); UASManager::instance()->removeUAS(uas); - deleteLater(); } void UASView::refresh() { - //setUpdatesEnabled(false); - //setUpdatesEnabled(true); - //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 1bcdd4dbd6d441fedd2de3fb8b92f618aff9d543..15c427ece26b84462152650034302c8c7e243b6e 100644 --- a/src/ui/uas/UASView.h +++ b/src/ui/uas/UASView.h @@ -49,6 +49,7 @@ class UASView : public QWidget public: UASView(UASInterface* uas, QWidget *parent = 0); ~UASView(); + UASInterface* uas; public slots: /** @brief Update the name of the system */ @@ -65,8 +66,11 @@ 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(); + /** + * Request that the UASManager deletes this UAS. This doesn't delete this widget + * yet, it waits for the approprait uasDeleted signal. + */ + void triggerUASDeletion(); 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); @@ -103,7 +107,6 @@ protected: bool disconnected; int timeRemaining; float chargeLevel; - UASInterface* uas; float load; QString state; QString stateDesc;