QGCToolBar.cc 26.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
/*=====================================================================

QGroundControl Open Source Ground Control Station

(c) 2009 - 2011 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>

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 <http://www.gnu.org/licenses/>.

======================================================================*/

#include <QToolButton>
#include <QLabel>
26
#include <QSpacerItem>
27 28
#include <QSerialPortInfo>

29
#include "SettingsDialog.h"
30 31
#include "QGCToolBar.h"
#include "UASManager.h"
lm's avatar
lm committed
32
#include "MainWindow.h"
33
#include "QGCApplication.h"
34 35 36

QGCToolBar::QGCToolBar(QWidget *parent) :
    QToolBar(parent),
37
    mav(NULL),
lm's avatar
lm committed
38 39 40 41
    changed(true),
    batteryPercent(0),
    batteryVoltage(0),
    wpId(0),
42
    wpDistance(0),
43
    altitudeRel(0),
44
    systemArmed(false),
45
    currentLink(NULL),
46 47 48 49
    firstAction(NULL),
    _linkMgr(LinkManager::instance()),
    _linkCombo(NULL),
    _linkComboAction(NULL),
50 51
    _linksConnected(false),
    _linkSelected(false)
52
{
53
    setObjectName("QGCToolBar");
54
    setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
55 56 57
    connect(LinkManager::instance(), &LinkManager::linkConnected,            this, &QGCToolBar::_linkConnected);
    connect(LinkManager::instance(), &LinkManager::linkDisconnected,         this, &QGCToolBar::_linkDisconnected);
    connect(LinkManager::instance(), &LinkManager::linkConfigurationChanged, this, &QGCToolBar::_updateConfigurations);
58 59
}

60 61 62 63 64 65 66 67
void QGCToolBar::heartbeatTimeout(bool timeout, unsigned int ms)
{
    // set timeout label visible
    if (timeout)
    {
        // Alternate colors to increase visibility
        if ((ms / 1000) % 2 == 0)
        {
68
            toolBarTimeoutLabel->setStyleSheet(QString("QLabel {color: #000; background-color: #FF0037;}"));
69 70 71
        }
        else
        {
72
            toolBarTimeoutLabel->setStyleSheet(QString("QLabel {color: #FFF; background-color: #6B0017;}"));
73 74
        }
        toolBarTimeoutLabel->setText(tr("CONNECTION LOST: %1 s").arg((ms / 1000.0f), 2, 'f', 1, ' '));
75
        toolBarTimeoutAction->setVisible(true);
76
        toolBarMessageAction->setVisible(false);
Lorenz Meier's avatar
Lorenz Meier committed
77
        toolBarBatteryBarAction->setVisible(false);
78 79 80 81
    }
    else
    {
        // Check if loss text is present, reset once
82
        if (toolBarTimeoutAction->isVisible())
83
        {
84
            toolBarTimeoutAction->setVisible(false);
85
            toolBarMessageAction->setVisible(true);
Lorenz Meier's avatar
Lorenz Meier committed
86
            toolBarBatteryBarAction->setVisible(true);
87 88 89
        }
    }
}
lm's avatar
lm committed
90

91 92
void QGCToolBar::createUI()
{
93 94 95 96 97 98
    // CREATE TOOLBAR ITEMS
    // Add internal actions
    // Add MAV widget
    symbolLabel = new QLabel(this);
    addWidget(symbolLabel);

99
    toolBarNameLabel = new QLabel(this);
100 101
    toolBarNameLabel->setToolTip(tr("Currently controlled vehicle"));
    toolBarNameLabel->setAlignment(Qt::AlignCenter);
102
    toolBarNameLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
103 104
    addWidget(toolBarNameLabel);

105
    toolBarTimeoutLabel = new QLabel(this);
106 107
    toolBarTimeoutLabel->setToolTip(tr("System timed out, interval since last message"));
    toolBarTimeoutLabel->setAlignment(Qt::AlignCenter);
108
    toolBarTimeoutLabel->setObjectName("toolBarTimeoutLabel");
109 110
    toolBarTimeoutLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
    toolBarTimeoutAction = addWidget(toolBarTimeoutLabel);
111

112
    toolBarSafetyLabel = new QLabel(this);
113 114 115 116
    toolBarSafetyLabel->setToolTip(tr("Vehicle safety state"));
    toolBarSafetyLabel->setAlignment(Qt::AlignCenter);
    addWidget(toolBarSafetyLabel);

117
    toolBarModeLabel = new QLabel(this);
118
    toolBarModeLabel->setToolTip(tr("Vehicle mode"));
119
    toolBarModeLabel->setObjectName("toolBarModeLabel");
120 121 122
    toolBarModeLabel->setAlignment(Qt::AlignCenter);
    addWidget(toolBarModeLabel);

123 124 125 126 127
//    toolBarStateLabel = new QLabel(this);
//    toolBarStateLabel->setToolTip(tr("Vehicle state"));
//    toolBarStateLabel->setObjectName("toolBarStateLabel");
//    toolBarStateLabel->setAlignment(Qt::AlignCenter);
//    addWidget(toolBarStateLabel);
128 129 130 131 132 133 134 135

    toolBarBatteryBar = new QProgressBar(this);
    toolBarBatteryBar->setMinimum(0);
    toolBarBatteryBar->setMaximum(100);
    toolBarBatteryBar->setMinimumWidth(20);
    toolBarBatteryBar->setMaximumWidth(100);
    toolBarBatteryBar->setToolTip(tr("Battery charge level"));
    toolBarBatteryBar->setObjectName("toolBarBatteryBar");
136
    toolBarBatteryBar->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::MinimumExpanding);
Lorenz Meier's avatar
Lorenz Meier committed
137
    toolBarBatteryBarAction = addWidget(toolBarBatteryBar);
138

139
    toolBarBatteryVoltageLabel = new QLabel(this);
140
    toolBarBatteryVoltageLabel->setToolTip(tr("Battery voltage"));
141
    toolBarBatteryVoltageLabel->setObjectName("toolBarBatteryVoltageLabel");
142
    toolBarBatteryVoltageLabel->setAlignment(Qt::AlignCenter);
Lorenz Meier's avatar
Lorenz Meier committed
143
    toolBarBatteryVoltageAction = addWidget(toolBarBatteryVoltageLabel);
144

145
    toolBarWpLabel = new QLabel(this);
146
    toolBarWpLabel->setToolTip(tr("Current waypoint"));
147
    toolBarWpLabel->setObjectName("toolBarWpLabel");
148
    toolBarWpLabel->setAlignment(Qt::AlignCenter);
149
    toolBarWpAction = addWidget(toolBarWpLabel);
150

151
    toolBarMessageLabel = new QLabel(this);
152
    toolBarMessageLabel->setToolTip(tr("Most recent system message"));
153
    toolBarMessageLabel->setObjectName("toolBarMessageLabel");
154
    toolBarMessageAction = addWidget(toolBarMessageLabel);
155 156 157 158 159

    QWidget* spacer = new QWidget();
    spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    addWidget(spacer);

160
    // Links to connect to
161 162 163 164
    _linkCombo = new QComboBox(this);
    connect(_linkCombo, SIGNAL(activated(int)), SLOT(_linkComboActivated(int)));
    _linkCombo->setToolTip(tr("Choose the link to use"));
    _linkCombo->setEnabled(true);
165
    _linkCombo->setMinimumWidth(160);
166
    _linkComboAction = addWidget(_linkCombo);
167
    _updateConfigurations();
168 169 170 171 172

    _connectButton = new QPushButton(tr("Connect"), this);
    _connectButton->setObjectName("connectButton");
    addWidget(_connectButton);
    connect(_connectButton, &QPushButton::clicked, this, &QGCToolBar::_connectButtonClicked);
173

174 175
    resetToolbarUI();

lm's avatar
lm committed
176 177
    // DONE INITIALIZING BUTTONS

178 179 180
    // Set the toolbar to be updated every 2s
    connect(&updateViewTimer, SIGNAL(timeout()), this, SLOT(updateView()));

181
    // Configure the toolbar for the current default UAS
182 183
    setActiveUAS(UASManager::instance()->getActiveUAS());
    connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)), this, SLOT(setActiveUAS(UASInterface*)));
lm's avatar
lm committed
184

185 186 187
    toolBarMessageAction->setVisible(false);
    toolBarBatteryBarAction->setVisible(false);

Lorenz Meier's avatar
Lorenz Meier committed
188
    changed = false;
189 190
}

191 192 193 194 195 196 197 198 199
/**
 * 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"));
200
    //toolBarTimeoutLabel->show();
201 202
    toolBarSafetyLabel->setText("----");
    toolBarModeLabel->setText("------");
203
//    toolBarStateLabel->setText("------");
204 205 206 207 208
    toolBarBatteryBar->setValue(0);
    toolBarBatteryBar->setDisabled(true);
    toolBarBatteryVoltageLabel->setText("xx.x V");
    toolBarWpLabel->setText("WP--");
    toolBarMessageLabel->clear();
209 210
    lastSystemMessage = "";
    lastSystemMessageTimeMs = 0;
211 212
    symbolLabel->setStyleSheet("");
    symbolLabel->clear();
213 214
    toolBarMessageAction->setVisible(false);
    toolBarBatteryBarAction->setVisible(false);
215 216
}

Lorenz Meier's avatar
Lorenz Meier committed
217
void QGCToolBar::setPerspectiveChangeActions(const QList<QAction*> &actions)
218
{
Lorenz Meier's avatar
Lorenz Meier committed
219 220
    if (actions.count() > 1)
    {
221
        group = new QButtonGroup(this);
Lorenz Meier's avatar
Lorenz Meier committed
222 223
        group->setExclusive(true);

224
        // Add the first button.
Lorenz Meier's avatar
Lorenz Meier committed
225
        QToolButton *first = new QToolButton(this);
226
        //first->setIcon(actions.first()->icon());
Lorenz Meier's avatar
Lorenz Meier committed
227 228 229 230
        first->setText(actions.first()->text());
        first->setToolTip(actions.first()->toolTip());
        first->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
        first->setCheckable(true);
231

Lorenz Meier's avatar
Lorenz Meier committed
232
        connect(first, SIGNAL(clicked(bool)), actions.first(), SIGNAL(triggered(bool)));
233
        connect(actions.first(),SIGNAL(triggered(bool)),first,SLOT(setChecked(bool)));
234

235
        first->setObjectName("firstAction");
236 237

        //first->setStyleSheet("QToolButton { min-height: 24px; max-height: 24px; min-width: 60px; color: #222222; background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #A2A3A4, stop: 1 #B6B7B8); margin-left: 8px; margin-right: 0px; padding-left: 4px; padding-right: 8px; border-radius: 0px; border : 0px solid blue; border-bottom-left-radius: 6px; border-top-left-radius: 6px; border-left: 1px solid #484848; border-top: 1px solid #484848; border-bottom: 1px solid #484848; } QToolButton:checked { background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #555555, stop: 1 #787878); color: #DDDDDD; }");
Lorenz Meier's avatar
Lorenz Meier committed
238 239 240
        addWidget(first);
        group->addButton(first);

241
        // Add all the middle buttons.
242
        for (int i = 1; i < actions.count(); i++)
Lorenz Meier's avatar
Lorenz Meier committed
243 244
        {
            QToolButton *btn = new QToolButton(this);
245
            //btn->setIcon(actions.at(i)->icon());
Lorenz Meier's avatar
Lorenz Meier committed
246 247 248 249 250
            btn->setText(actions.at(i)->text());
            btn->setToolTip(actions.at(i)->toolTip());
            btn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
            btn->setCheckable(true);
            connect(btn, SIGNAL(clicked(bool)), actions.at(i), SIGNAL(triggered(bool)));
251
            connect(actions.at(i),SIGNAL(triggered(bool)),btn,SLOT(setChecked(bool)));
Lorenz Meier's avatar
Lorenz Meier committed
252 253 254 255 256
            addWidget(btn);
            group->addButton(btn);
        }

        // Add last button
257
        advancedButton = new QToolButton(this);
258
        advancedButton->setIcon(QIcon(":/files/images/apps/utilities-system-monitor.svg"));
259
        advancedButton->setText(tr("More"));
260 261
        advancedButton->setToolTip(tr("Options for advanced users"));
        advancedButton->setCheckable(true);
262
        advancedButton->setObjectName("advancedButton");
263
        advancedButton->setPopupMode(QToolButton::InstantPopup);
264
        advancedButton->setToolButtonStyle(Qt::ToolButtonTextOnly);
265 266
        addWidget(advancedButton);
        group->addButton(advancedButton);
267
    } else {
Lorenz Meier's avatar
Lorenz Meier committed
268
        qDebug() << __FILE__ << __LINE__ << "Not enough perspective change actions provided";
269
    }
Lorenz Meier's avatar
Lorenz Meier committed
270

271
    // Add the "rest"
Lorenz Meier's avatar
Lorenz Meier committed
272
    createUI();
273 274
}

275 276 277 278 279 280 281 282 283 284 285 286 287
void QGCToolBar::setPerspectiveChangeAdvancedActions(const QList<QAction*> &actions)
{
    if (actions.count() > 1)
    {
        QMenu *menu = new QMenu(advancedButton);

        for (int i = 0; i < actions.count(); i++)
        {

            menu->addAction(actions.at(i));
        }

        advancedButton->setMenu(menu);
288
        connect(menu, SIGNAL(triggered(QAction*)), this, SLOT(advancedActivityTriggered(QAction*)));
289 290 291 292 293 294

    } else {
        qDebug() << __FILE__ << __LINE__ << "Not enough perspective change actions provided";
    }
}

295 296 297 298 299 300
void QGCToolBar::advancedActivityTriggered(QAction* action)
{
    if (action->isChecked())
        advancedButton->setChecked(true);
}

301 302
void QGCToolBar::setActiveUAS(UASInterface* active)
{
303
    // Do nothing if system is the same
304 305
    if (mav == active || active == NULL)
        return;
306

307
    // If switching UASes, disconnect the only one.
308 309 310 311 312 313
    if (mav)
    {
        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)));
        disconnect(mav, SIGNAL(systemTypeSet(UASInterface*,uint)), this, SLOT(setSystemType(UASInterface*,uint)));
LM's avatar
LM committed
314
        disconnect(mav, SIGNAL(textMessageReceived(int,int,int,QString)), this, SLOT(receiveTextMessage(int,int,int,QString)));
dongfang's avatar
dongfang committed
315
        disconnect(mav, SIGNAL(batteryChanged(UASInterface*, double, double, double,int)), this, SLOT(updateBatteryRemaining(UASInterface*, double, double, double, int)));
316
        disconnect(mav, SIGNAL(armingChanged(bool)), this, SLOT(updateArmingState(bool)));
317
        disconnect(mav, SIGNAL(heartbeatTimeout(bool, unsigned int)), this, SLOT(heartbeatTimeout(bool,unsigned int)));
318 319
        if (mav->getWaypointManager())
        {
320
            disconnect(mav->getWaypointManager(), SIGNAL(currentWaypointChanged(quint16)), this, SLOT(updateCurrentWaypoint(quint16)));
321 322
            disconnect(mav->getWaypointManager(), SIGNAL(waypointDistanceChanged(double)), this, SLOT(updateWaypointDistance(double)));
        }
323
    }
324 325 326 327 328
    else
    {
        // Only update the UI once a UAS has been selected.
        updateViewTimer.start(2000);
    }
329 330 331

    // Connect new system
    mav = active;
332
    if (mav)
333
    {
334 335 336 337 338
        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)));
339
        connect(mav, SIGNAL(batteryChanged(UASInterface*,double,double,double,int)), this, SLOT(updateBatteryRemaining(UASInterface*,double,double,double,int)));
340 341 342 343 344 345 346
        connect(mav, SIGNAL(armingChanged(bool)), this, SLOT(updateArmingState(bool)));
        connect(mav, SIGNAL(heartbeatTimeout(bool, unsigned int)), this, SLOT(heartbeatTimeout(bool,unsigned int)));
        if (mav->getWaypointManager())
        {
            connect(mav->getWaypointManager(), SIGNAL(currentWaypointChanged(quint16)), this, SLOT(updateCurrentWaypoint(quint16)));
            connect(mav->getWaypointManager(), SIGNAL(waypointDistanceChanged(double)), this, SLOT(updateWaypointDistance(double)));
        }
347

348 349 350
        // Update all values once
        systemName = mav->getUASName();
        systemArmed = mav->isArmed();
351
        toolBarNameLabel->setText(mav->getUASName().replace("MAV", ""));
352 353
        toolBarNameLabel->setStyleSheet(QString("QLabel {color: %1;}").arg(mav->getColor().name()));
        symbolLabel->setStyleSheet(QString("QWidget {background-color: %1;}").arg(mav->getColor().name()));
354 355 356 357 358
        QString shortMode = mav->getShortMode();
        shortMode = shortMode.replace("D|", "");
        shortMode = shortMode.replace("A|", "");
        toolBarModeLabel->setText(shortMode);
//        toolBarStateLabel->setText(mav->getShortState());
359 360 361
        toolBarTimeoutAction->setVisible(false);
        toolBarMessageLabel->clear();
        lastSystemMessageTimeMs = 0;
362 363 364 365 366
        toolBarBatteryBar->setEnabled(true);
        setSystemType(mav, mav->getSystemType());
    }
    else
    {
367 368 369 370 371
        updateViewTimer.stop();
        resetToolbarUI();
    }
}

372 373 374 375
void QGCToolBar::updateArmingState(bool armed)
{
    systemArmed = armed;
    changed = true;
Lorenz Meier's avatar
Lorenz Meier committed
376 377
    /* important, immediately update */
    updateView();
378 379
}

lm's avatar
lm committed
380 381 382
void QGCToolBar::updateView()
{
    if (!changed) return;
383
    if (toolBarWpAction->isVisible())
384 385
        toolBarWpLabel->setText(tr("WP%1").arg(wpId));

386
    if (toolBarBatteryBarAction->isVisible()) {
387 388 389
        toolBarBatteryBar->setValue(batteryPercent);

        if (batteryPercent < 30 && toolBarBatteryBar->value() >= 30) {
390 391 392
            toolBarBatteryBar->setStyleSheet(qgcApp()->styleIsDark() ?
                                             "QProgressBar {color: #000} QProgressBar QProgressBar::chunk { background-color: #0F0}" :
                                             "QProgressBar {color: #FFF} QProgressBar::chunk { background-color: #008000}");
393
        } else if (batteryPercent >= 30 && toolBarBatteryBar->value() < 30){
394 395 396
            toolBarBatteryBar->setStyleSheet(qgcApp()->styleIsDark() ?
                                             "QProgressBar {color: #000} QProgressBar QProgressBar::chunk { background-color: #FF0}" :
                                             "QProgressBar {color: #FFF} QProgressBar::chunk { background-color: #808000}");
397
        }
398

399 400
    }
    if (toolBarBatteryVoltageLabel->isVisible()) {
401
    toolBarBatteryVoltageLabel->setText(tr("%1 V").arg(batteryVoltage, 4, 'f', 1, ' '));
Lorenz Meier's avatar
Lorenz Meier committed
402 403
    }

404 405

//    toolBarStateLabel->setText(QString("%1").arg(state));
406 407 408
    if (mode.size() > 0) {
        toolBarModeLabel->setText(QString("%1").arg(mode));
    }
lm's avatar
lm committed
409
    toolBarNameLabel->setText(systemName);
410
    // expire after 15 seconds
411

412
    if (toolBarMessageAction->isVisible()) {
413 414 415 416 417
        if (QGC::groundTimeMilliseconds() - lastSystemMessageTimeMs < 15000) {
            toolBarMessageLabel->setText(QString("%1").arg(lastSystemMessage));
        } else {
            toolBarMessageLabel->clear();
        }
418
    }
419

420
    // Display the system armed state with a red-on-yellow background if armed or green text if safe.
421 422
    if (systemArmed)
    {
423
        toolBarSafetyLabel->setStyleSheet(QString("QLabel {color: %1; background-color: %2; font-size: 15pt;}").arg(QGC::colorRed.name()).arg(QGC::colorYellow.name()));
424 425 426 427
        toolBarSafetyLabel->setText(tr("ARMED"));
    }
    else
    {
428 429 430
        toolBarSafetyLabel->setStyleSheet(qgcApp()->styleIsDark() ?
                                          "QLabel {color: #14C814; font-size: 15pt;}" :
                                          "QLabel {color: #0D820D; font-size: 15pt;}");
Lorenz Meier's avatar
Lorenz Meier committed
431
        toolBarSafetyLabel->setText(tr("DISARMED"));
432 433
    }

lm's avatar
lm committed
434
    changed = false;
lm's avatar
lm committed
435 436
}

437 438
void QGCToolBar::updateWaypointDistance(double distance)
{
lm's avatar
lm committed
439 440
    if (wpDistance != distance) changed = true;
    wpDistance = distance;
441 442 443 444
}

void QGCToolBar::updateCurrentWaypoint(quint16 id)
{
lm's avatar
lm committed
445
    if (wpId != id) changed = true;
lm's avatar
lm committed
446
    wpId = id;
447 448
}

dongfang's avatar
dongfang committed
449
void QGCToolBar::updateBatteryRemaining(UASInterface* uas, double voltage, double current, double percent, int seconds)
LM's avatar
LM committed
450
{
451 452
    Q_UNUSED(uas);
    Q_UNUSED(seconds);
453
    Q_UNUSED(current);
454

lm's avatar
lm committed
455
    if (batteryPercent != percent || batteryVoltage != voltage) changed = true;
lm's avatar
lm committed
456 457
    batteryPercent = percent;
    batteryVoltage = voltage;
LM's avatar
LM committed
458 459
}

460 461 462 463
void QGCToolBar::updateState(UASInterface* system, QString name, QString description)
{
    Q_UNUSED(system);
    Q_UNUSED(description);
lm's avatar
lm committed
464
    if (state != name) changed = true;
lm's avatar
lm committed
465
    state = name;
Lorenz Meier's avatar
Lorenz Meier committed
466 467
    /* important, immediately update */
    updateView();
468 469 470 471 472 473
}

void QGCToolBar::updateMode(int system, QString name, QString description)
{
    Q_UNUSED(system);
    Q_UNUSED(description);
474 475 476 477 478 479 480 481 482 483
    if (name.size() == 0) {
        qDebug() << "EMPTY MODE, RETURN";
    }

    QString shortMode = name;
    shortMode = shortMode.replace("D|", "");
    shortMode = shortMode.replace("A|", "");

    if (mode != shortMode) changed = true;
    mode = shortMode;
Lorenz Meier's avatar
Lorenz Meier committed
484 485
    /* important, immediately update */
    updateView();
486 487 488 489
}

void QGCToolBar::updateName(const QString& name)
{
Lorenz Meier's avatar
Lorenz Meier committed
490 491 492 493
    if (systemName != name)
    {
        changed = true;
    }
lm's avatar
lm committed
494
    systemName = name;
495 496 497 498 499 500 501 502 503 504 505 506
}

/**
 * The current system type is represented through the system icon.
 *
 * @param uas Source system, has to be the same as this->uas
 * @param systemType type ID, following the MAVLink system type conventions
 * @see http://pixhawk.ethz.ch/software/mavlink
 */
void QGCToolBar::setSystemType(UASInterface* uas, unsigned int systemType)
{
    Q_UNUSED(uas);
507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567
    QPixmap newPixmap;
    switch (systemType) {
    case MAV_TYPE_GENERIC:
        newPixmap = QPixmap(":/files/images/mavs/generic.svg");
        break;
    case MAV_TYPE_FIXED_WING:
        newPixmap = QPixmap(":/files/images/mavs/fixed-wing.svg");
        break;
    case MAV_TYPE_QUADROTOR:
        newPixmap = QPixmap(":/files/images/mavs/quadrotor.svg");
        break;
    case MAV_TYPE_COAXIAL:
        newPixmap = QPixmap(":/files/images/mavs/coaxial.svg");
        break;
    case MAV_TYPE_HELICOPTER:
        newPixmap = QPixmap(":/files/images/mavs/helicopter.svg");
        break;
    case MAV_TYPE_ANTENNA_TRACKER:
        newPixmap = QPixmap(":/files/images/mavs/antenna-tracker.svg");
        break;
    case MAV_TYPE_GCS:
        newPixmap = QPixmap(":files/images/mavs/groundstation.svg");
        break;
    case MAV_TYPE_AIRSHIP:
        newPixmap = QPixmap(":files/images/mavs/airship.svg");
        break;
    case MAV_TYPE_FREE_BALLOON:
        newPixmap = QPixmap(":files/images/mavs/free-balloon.svg");
        break;
    case MAV_TYPE_ROCKET:
        newPixmap = QPixmap(":files/images/mavs/rocket.svg");
        break;
    case MAV_TYPE_GROUND_ROVER:
        newPixmap = QPixmap(":files/images/mavs/ground-rover.svg");
        break;
    case MAV_TYPE_SURFACE_BOAT:
        newPixmap = QPixmap(":files/images/mavs/surface-boat.svg");
        break;
    case MAV_TYPE_SUBMARINE:
        newPixmap = QPixmap(":files/images/mavs/submarine.svg");
        break;
    case MAV_TYPE_HEXAROTOR:
        newPixmap = QPixmap(":files/images/mavs/hexarotor.svg");
        break;
    case MAV_TYPE_OCTOROTOR:
        newPixmap = QPixmap(":files/images/mavs/octorotor.svg");
        break;
    case MAV_TYPE_TRICOPTER:
        newPixmap = QPixmap(":files/images/mavs/tricopter.svg");
        break;
    case MAV_TYPE_FLAPPING_WING:
        newPixmap = QPixmap(":files/images/mavs/flapping-wing.svg");
        break;
    case MAV_TYPE_KITE:
        newPixmap = QPixmap(":files/images/mavs/kite.svg");
        break;
    default:
        newPixmap = QPixmap(":/files/images/mavs/unknown.svg");
        break;
    }
    symbolLabel->setPixmap(newPixmap.scaledToHeight(24));
568 569
}

LM's avatar
LM committed
570 571 572 573 574
void QGCToolBar::receiveTextMessage(int uasid, int componentid, int severity, QString text)
{
    Q_UNUSED(uasid);
    Q_UNUSED(componentid);
    Q_UNUSED(severity);
lm's avatar
lm committed
575
    if (lastSystemMessage != text) changed = true;
lm's avatar
lm committed
576
    lastSystemMessage = text;
577
    lastSystemMessageTimeMs = QGC::groundTimeMilliseconds();
LM's avatar
LM committed
578 579
}

580
void QGCToolBar::_linkConnected(LinkInterface* link)
581
{
582 583
    Q_UNUSED(link);
    _updateConnectButton();
584 585
}

586
void QGCToolBar::_linkDisconnected(LinkInterface* link)
587
{
588 589
    Q_UNUSED(link);
    _updateConnectButton();
590 591
}

592
void QGCToolBar::_updateConnectButton(void)
593
{
594 595 596 597 598 599 600 601 602 603 604
    QMenu* menu = new QMenu(this);
    // If there are multiple connected links add/update the connect button menu
    int connectedCount = 0;
    QList<LinkInterface*> links = _linkMgr->getLinks();
    foreach(LinkInterface* link, links) {
        if (link->isConnected()) {
            connectedCount++;
            QAction* action = menu->addAction(link->getName());
            action->setData(QVariant::fromValue((void*)link));
            connect(action, &QAction::triggered, this, &QGCToolBar::_disconnectFromMenu);
        }
605
    }
606 607 608 609 610
    // Remove old menu
    QMenu* oldMenu = _connectButton->menu();
    _connectButton->setMenu(NULL);
    if (oldMenu) {
        oldMenu->deleteLater();
611
    }
612 613 614 615 616 617 618 619 620 621 622
    // Add new menu if needed
    if (connectedCount > 1) {
        _connectButton->setMenu(menu);
    } else {
        delete menu;
    }
    _linksConnected = connectedCount != 0;
    _connectButton->setText(_linksConnected ? tr("Disconnect") : tr("Connect"));
    _linkComboAction->setVisible(!_linksConnected);
    toolBarMessageAction->setVisible(_linksConnected);
    toolBarWpAction->setVisible(_linksConnected);
623 624
}

625
void QGCToolBar::_connectButtonClicked(bool checked)
626
{
627 628 629 630 631 632 633 634 635 636 637 638 639 640 641
    Q_UNUSED(checked);
    if (_linksConnected) {
        // Disconnect
        // Should be just one connected link, disconnect it
        int connectedCount = 0;
        LinkInterface* connectedLink = NULL;
        QList<LinkInterface*> links = _linkMgr->getLinks();
        foreach(LinkInterface* link, links) {
            if (link->isConnected()) {
                connectedCount++;
                connectedLink = link;
            }
        }
        Q_ASSERT(connectedCount == 1);
        Q_ASSERT(connectedLink);
642 643
        // TODO The link is "disconnected" but not deleted. On subsequent connections,
        // new links are created. Why's that?
644 645
        _linkMgr->disconnectLink(connectedLink);
    } else {
646 647
        // We don't want the combo box updating under our feet
        _linkMgr->suspendConfigurationUpdates(true);
648
        // Connect
649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666
        int valid = _linkCombo->currentData().toInt();
        // Is this a valid option?
        if(valid == 1) {
            // Get the configuration name
            QString confName = _linkCombo->currentText();
            // Create a link for it
            LinkInterface* link = _linkMgr->createLink(confName);
            if(link) {
                // Connect it
                _linkMgr->connectLink(link);
                // Save last used connection
                MainWindow::instance()->saveLastUsedConnection(confName);
            }
            _linkMgr->suspendConfigurationUpdates(false);
        // Else, it must be Manage Links
        } else if(valid == 0) {
            _linkMgr->suspendConfigurationUpdates(false);
            MainWindow::instance()->manageLinks();
667
        }
668 669 670
    }
}

671
void QGCToolBar::_disconnectFromMenu(bool checked)
672
{
673 674 675 676 677 678
    Q_UNUSED(checked);
    QAction* action = qobject_cast<QAction*>(sender());
    Q_ASSERT(action);
    LinkInterface* link = (LinkInterface*)(action->data().value<void *>());
    Q_ASSERT(link);
    _linkMgr->disconnectLink(link);
679 680
}

681 682
void QGCToolBar::clearStatusString()
{
Lorenz Meier's avatar
Lorenz Meier committed
683 684 685 686 687
    if (toolBarMessageLabel->text().length() > 0)
    {
        lastSystemMessage = "";
        changed = true;
    }
688 689
}

690
void QGCToolBar::_linkComboActivated(int index)
691
{
692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723
    int type = _linkCombo->itemData(index).toInt();
    // Check if we should "Manage Connections"
    if(type == 0) {
        MainWindow::instance()->manageLinks();
    } else {
        _linkSelected = true;
    }
}

void QGCToolBar::_updateConfigurations()
{
    bool resetSelected = false;
    QString selected = _linkCombo->currentText();
    _linkCombo->clear();
    _linkCombo->addItem("Manage Links", 0);
    QList<LinkConfiguration*> configs = LinkManager::instance()->getLinkConfigurationList();
    foreach(LinkConfiguration* conf, configs) {
        if(conf) {
            _linkCombo->addItem(conf->name(), 1);
            if(!_linkSelected && conf->isPreferred()) {
                selected = conf->name();
                resetSelected = true;
            }
        }
    }
    int index = _linkCombo->findText(selected);
    if(index >= 0) {
        _linkCombo->setCurrentIndex(index);
    }
    if(resetSelected) {
        _linkSelected = false;
    }
724
}