QGCToolBar.cc 29 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
#include "SerialLink.h"
28 29
#include "QGCToolBar.h"
#include "UASManager.h"
lm's avatar
lm committed
30
#include "MainWindow.h"
31
#include "QGCApplication.h"
32 33 34

QGCToolBar::QGCToolBar(QWidget *parent) :
    QToolBar(parent),
35
    mav(NULL),
36
    userBaudChoice(false),
37
    userPortChoice(false),
lm's avatar
lm committed
38 39 40 41
    changed(true),
    batteryPercent(0),
    batteryVoltage(0),
    wpId(0),
42
    wpDistance(0),
43 44
    altitudeMSL(0),
    altitudeRel(0),
45
    systemArmed(false),
46
    currentLink(NULL),
47
    firstAction(NULL)
48
{
49
    setObjectName("QGCToolBar");
50
    setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
lm's avatar
lm committed
51

52 53
    // Do not load UI, wait for actions
}
lm's avatar
lm committed
54

55
void QGCToolBar::globalPositionChanged(UASInterface* uas, double lat, double lon, double altAMSL, double altWGS84, quint64 usec)
56 57 58 59
{
    Q_UNUSED(uas);
    Q_UNUSED(lat);
    Q_UNUSED(lon);
60
    Q_UNUSED(altWGS84);
61
    Q_UNUSED(usec);
62
    altitudeMSL = altAMSL;
63 64 65
    changed = true;
}

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

97 98
void QGCToolBar::createUI()
{
99 100 101 102 103 104
    // CREATE TOOLBAR ITEMS
    // Add internal actions
    // Add MAV widget
    symbolLabel = new QLabel(this);
    addWidget(symbolLabel);

105
    toolBarNameLabel = new QLabel(this);
106 107
    toolBarNameLabel->setToolTip(tr("Currently controlled vehicle"));
    toolBarNameLabel->setAlignment(Qt::AlignCenter);
108
    toolBarNameLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
109 110
    addWidget(toolBarNameLabel);

111
    toolBarTimeoutLabel = new QLabel(this);
112 113
    toolBarTimeoutLabel->setToolTip(tr("System timed out, interval since last message"));
    toolBarTimeoutLabel->setAlignment(Qt::AlignCenter);
114
    toolBarTimeoutLabel->setObjectName("toolBarTimeoutLabel");
115 116
    toolBarTimeoutLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
    toolBarTimeoutAction = addWidget(toolBarTimeoutLabel);
117

118
    toolBarSafetyLabel = new QLabel(this);
119 120 121 122
    toolBarSafetyLabel->setToolTip(tr("Vehicle safety state"));
    toolBarSafetyLabel->setAlignment(Qt::AlignCenter);
    addWidget(toolBarSafetyLabel);

123
    toolBarModeLabel = new QLabel(this);
124
    toolBarModeLabel->setToolTip(tr("Vehicle mode"));
125
    toolBarModeLabel->setObjectName("toolBarModeLabel");
126 127 128
    toolBarModeLabel->setAlignment(Qt::AlignCenter);
    addWidget(toolBarModeLabel);

129 130 131 132 133
//    toolBarStateLabel = new QLabel(this);
//    toolBarStateLabel->setToolTip(tr("Vehicle state"));
//    toolBarStateLabel->setObjectName("toolBarStateLabel");
//    toolBarStateLabel->setAlignment(Qt::AlignCenter);
//    addWidget(toolBarStateLabel);
134 135 136 137 138 139 140 141

    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");
142
    toolBarBatteryBar->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::MinimumExpanding);
Lorenz Meier's avatar
Lorenz Meier committed
143
    toolBarBatteryBarAction = addWidget(toolBarBatteryBar);
144

145
    toolBarBatteryVoltageLabel = new QLabel(this);
146
    toolBarBatteryVoltageLabel->setToolTip(tr("Battery voltage"));
147
    toolBarBatteryVoltageLabel->setObjectName("toolBarBatteryVoltageLabel");
148
    toolBarBatteryVoltageLabel->setAlignment(Qt::AlignCenter);
Lorenz Meier's avatar
Lorenz Meier committed
149
    toolBarBatteryVoltageAction = addWidget(toolBarBatteryVoltageLabel);
150

151
    toolBarWpLabel = new QLabel(this);
152
    toolBarWpLabel->setToolTip(tr("Current waypoint"));
153
    toolBarWpLabel->setObjectName("toolBarWpLabel");
154
    toolBarWpLabel->setAlignment(Qt::AlignCenter);
155
    toolBarWpAction = addWidget(toolBarWpLabel);
156

157
    toolBarMessageLabel = new QLabel(this);
158
    toolBarMessageLabel->setToolTip(tr("Most recent system message"));
159
    toolBarMessageLabel->setObjectName("toolBarMessageLabel");
160
    toolBarMessageAction = addWidget(toolBarMessageLabel);
161 162 163 164 165

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

166 167 168
    portComboBox = new QComboBox(this);
    portComboBox->setToolTip(tr("Choose the COM port to use"));
    portComboBox->setEnabled(true);
169
    portComboBox->setMinimumWidth(100);
170
    toolBarPortAction = addWidget(portComboBox);
171 172 173 174

    baudcomboBox = new QComboBox(this);
    baudcomboBox->setToolTip(tr("Choose what baud rate to use"));
    baudcomboBox->setEnabled(true);
175 176 177 178 179 180 181 182 183 184 185
    baudcomboBox->setMinimumWidth(40);
    baudcomboBox->addItem("9600", 9600);
    baudcomboBox->addItem("14400", 14400);
    baudcomboBox->addItem("19200", 19200);
    baudcomboBox->addItem("38400", 38400);
    baudcomboBox->addItem("57600", 57600);
    baudcomboBox->addItem("115200", 115200);
    baudcomboBox->addItem("230400", 230400);
    baudcomboBox->addItem("460800", 460800);
    baudcomboBox->addItem("921600", 921600);
    baudcomboBox->setCurrentIndex(baudcomboBox->findData(57600));
186
    toolBarBaudAction = addWidget(baudcomboBox);
Lorenz Meier's avatar
Lorenz Meier committed
187 188
    connect(baudcomboBox, SIGNAL(activated(int)), this, SLOT(baudSelected(int)));
    connect(portComboBox, SIGNAL(activated(int)), this, SLOT(portSelected(int)));
189

190
    connectButton = new QPushButton(tr("Connect"), this);
191
    connectButton->setObjectName("connectButton");
192 193 194
    connectButton->setToolTip(tr("Connect wireless link to MAV"));
    connectButton->setCheckable(true);
    addWidget(connectButton);
195 196
    connect(connectButton, SIGNAL(clicked(bool)), this, SLOT(connectLink(bool)));

197 198
    resetToolbarUI();

lm's avatar
lm committed
199 200
    // DONE INITIALIZING BUTTONS

201 202 203
    // Set the toolbar to be updated every 2s
    connect(&updateViewTimer, SIGNAL(timeout()), this, SLOT(updateView()));

204
    // Configure the toolbar for the current default UAS
205 206
    setActiveUAS(UASManager::instance()->getActiveUAS());
    connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)), this, SLOT(setActiveUAS(UASInterface*)));
207 208 209
    // Update label if required
    if (LinkManager::instance()->getSerialLinks().count() < 1) {
        connectButton->setText(tr("New Serial Link"));
210 211
        toolBarPortAction->setVisible(false);
        toolBarBaudAction->setVisible(false);
212
    } else {
lm's avatar
lm committed
213

214
        QList<SerialLink*> links = LinkManager::instance()->getSerialLinks();
215

216 217 218 219
        foreach(SerialLink* slink, links)
        {
            addLink(slink);
        }
220 221
    }

222
    connect(LinkManager::instance(), SIGNAL(newLink(LinkInterface*)), this, SLOT(addLink(LinkInterface*)));
223
    connect(LinkManager::instance(), SIGNAL(linkDeleted(LinkInterface*)), this, SLOT(removeLink(LinkInterface*)));
224

225
    loadSettings();
Lorenz Meier's avatar
Lorenz Meier committed
226

227 228 229
    connect(&portBoxTimer, SIGNAL(timeout()), this, SLOT(updateComboBox()));
    portBoxTimer.start(500);

230 231 232
    toolBarMessageAction->setVisible(false);
    toolBarBatteryBarAction->setVisible(false);

Lorenz Meier's avatar
Lorenz Meier committed
233
    changed = false;
234 235
}

236 237 238 239 240 241 242 243 244
/**
 * 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"));
245
    //toolBarTimeoutLabel->show();
246 247
    toolBarSafetyLabel->setText("----");
    toolBarModeLabel->setText("------");
248
//    toolBarStateLabel->setText("------");
249 250 251 252 253
    toolBarBatteryBar->setValue(0);
    toolBarBatteryBar->setDisabled(true);
    toolBarBatteryVoltageLabel->setText("xx.x V");
    toolBarWpLabel->setText("WP--");
    toolBarMessageLabel->clear();
254 255
    lastSystemMessage = "";
    lastSystemMessageTimeMs = 0;
256 257
    symbolLabel->setStyleSheet("");
    symbolLabel->clear();
258 259
    toolBarMessageAction->setVisible(false);
    toolBarBatteryBarAction->setVisible(false);
260 261
}

262 263
void QGCToolBar::baudSelected(int index)
{
264
    Q_UNUSED(index);
265 266 267
    userBaudChoice = true;
}

268 269 270 271 272 273
void QGCToolBar::portSelected(int index)
{
    Q_UNUSED(index);
    userPortChoice = true;
}

Lorenz Meier's avatar
Lorenz Meier committed
274
void QGCToolBar::setPerspectiveChangeActions(const QList<QAction*> &actions)
275
{
Lorenz Meier's avatar
Lorenz Meier committed
276 277
    if (actions.count() > 1)
    {
278
        group = new QButtonGroup(this);
Lorenz Meier's avatar
Lorenz Meier committed
279 280
        group->setExclusive(true);

281
        // Add the first button.
Lorenz Meier's avatar
Lorenz Meier committed
282
        QToolButton *first = new QToolButton(this);
283
        //first->setIcon(actions.first()->icon());
Lorenz Meier's avatar
Lorenz Meier committed
284 285 286 287
        first->setText(actions.first()->text());
        first->setToolTip(actions.first()->toolTip());
        first->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
        first->setCheckable(true);
288

Lorenz Meier's avatar
Lorenz Meier committed
289
        connect(first, SIGNAL(clicked(bool)), actions.first(), SIGNAL(triggered(bool)));
290
        connect(actions.first(),SIGNAL(triggered(bool)),first,SLOT(setChecked(bool)));
291

292
        first->setObjectName("firstAction");
293 294

        //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
295 296 297
        addWidget(first);
        group->addButton(first);

298
        // Add all the middle buttons.
299
        for (int i = 1; i < actions.count(); i++)
Lorenz Meier's avatar
Lorenz Meier committed
300 301
        {
            QToolButton *btn = new QToolButton(this);
302
            //btn->setIcon(actions.at(i)->icon());
Lorenz Meier's avatar
Lorenz Meier committed
303 304 305 306 307
            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)));
308
            connect(actions.at(i),SIGNAL(triggered(bool)),btn,SLOT(setChecked(bool)));
Lorenz Meier's avatar
Lorenz Meier committed
309 310 311 312 313
            addWidget(btn);
            group->addButton(btn);
        }

        // Add last button
314
        advancedButton = new QToolButton(this);
315
        advancedButton->setIcon(QIcon(":/files/images/apps/utilities-system-monitor.svg"));
316
        advancedButton->setText(tr("More"));
317 318
        advancedButton->setToolTip(tr("Options for advanced users"));
        advancedButton->setCheckable(true);
319
        advancedButton->setObjectName("advancedButton");
320
        advancedButton->setPopupMode(QToolButton::InstantPopup);
321
        advancedButton->setToolButtonStyle(Qt::ToolButtonTextOnly);
322 323
        addWidget(advancedButton);
        group->addButton(advancedButton);
324
    } else {
Lorenz Meier's avatar
Lorenz Meier committed
325
        qDebug() << __FILE__ << __LINE__ << "Not enough perspective change actions provided";
326
    }
Lorenz Meier's avatar
Lorenz Meier committed
327

328
    // Add the "rest"
Lorenz Meier's avatar
Lorenz Meier committed
329
    createUI();
330 331
}

332 333 334 335 336 337 338 339 340 341 342 343 344
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);
345
        connect(menu, SIGNAL(triggered(QAction*)), this, SLOT(advancedActivityTriggered(QAction*)));
346 347 348 349 350 351

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

352 353 354 355 356 357
void QGCToolBar::advancedActivityTriggered(QAction* action)
{
    if (action->isChecked())
        advancedButton->setChecked(true);
}

358 359
void QGCToolBar::setActiveUAS(UASInterface* active)
{
360
    // Do nothing if system is the same
361 362
    if (mav == active || active == NULL)
        return;
363

364
    // If switching UASes, disconnect the only one.
365 366 367 368 369 370
    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
371
        disconnect(mav, SIGNAL(textMessageReceived(int,int,int,QString)), this, SLOT(receiveTextMessage(int,int,int,QString)));
dongfang's avatar
dongfang committed
372
        disconnect(mav, SIGNAL(batteryChanged(UASInterface*, double, double, double,int)), this, SLOT(updateBatteryRemaining(UASInterface*, double, double, double, int)));
373
        disconnect(mav, SIGNAL(armingChanged(bool)), this, SLOT(updateArmingState(bool)));
374
        disconnect(mav, SIGNAL(heartbeatTimeout(bool, unsigned int)), this, SLOT(heartbeatTimeout(bool,unsigned int)));
375
        disconnect(active, SIGNAL(globalPositionChanged(UASInterface*,double,double,double,double,quint64)), this, SLOT(globalPositionChanged(UASInterface*,double,double,double,double,quint64)));
376 377
        if (mav->getWaypointManager())
        {
378
            disconnect(mav->getWaypointManager(), SIGNAL(currentWaypointChanged(quint16)), this, SLOT(updateCurrentWaypoint(quint16)));
379 380
            disconnect(mav->getWaypointManager(), SIGNAL(waypointDistanceChanged(double)), this, SLOT(updateWaypointDistance(double)));
        }
381
    }
382 383 384 385 386
    else
    {
        // Only update the UI once a UAS has been selected.
        updateViewTimer.start(2000);
    }
387 388 389

    // Connect new system
    mav = active;
390
    if (mav)
391
    {
392 393 394 395 396
        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)));
397
        connect(mav, SIGNAL(batteryChanged(UASInterface*,double,double,double,int)), this, SLOT(updateBatteryRemaining(UASInterface*,double,double,double,int)));
398 399
        connect(mav, SIGNAL(armingChanged(bool)), this, SLOT(updateArmingState(bool)));
        connect(mav, SIGNAL(heartbeatTimeout(bool, unsigned int)), this, SLOT(heartbeatTimeout(bool,unsigned int)));
400
        connect(mav, SIGNAL(globalPositionChanged(UASInterface*,double,double,double,double,quint64)), this, SLOT(globalPositionChanged(UASInterface*,double,double,double,double,quint64)));
401 402 403 404 405
        if (mav->getWaypointManager())
        {
            connect(mav->getWaypointManager(), SIGNAL(currentWaypointChanged(quint16)), this, SLOT(updateCurrentWaypoint(quint16)));
            connect(mav->getWaypointManager(), SIGNAL(waypointDistanceChanged(double)), this, SLOT(updateWaypointDistance(double)));
        }
406

407 408 409
        // Update all values once
        systemName = mav->getUASName();
        systemArmed = mav->isArmed();
410
        toolBarNameLabel->setText(mav->getUASName().replace("MAV", ""));
411 412
        toolBarNameLabel->setStyleSheet(QString("QLabel {color: %1;}").arg(mav->getColor().name()));
        symbolLabel->setStyleSheet(QString("QWidget {background-color: %1;}").arg(mav->getColor().name()));
413 414 415 416 417
        QString shortMode = mav->getShortMode();
        shortMode = shortMode.replace("D|", "");
        shortMode = shortMode.replace("A|", "");
        toolBarModeLabel->setText(shortMode);
//        toolBarStateLabel->setText(mav->getShortState());
418 419 420
        toolBarTimeoutAction->setVisible(false);
        toolBarMessageLabel->clear();
        lastSystemMessageTimeMs = 0;
421 422 423 424 425
        toolBarBatteryBar->setEnabled(true);
        setSystemType(mav, mav->getSystemType());
    }
    else
    {
426 427 428 429 430
        updateViewTimer.stop();
        resetToolbarUI();
    }
}

431 432 433 434
void QGCToolBar::updateArmingState(bool armed)
{
    systemArmed = armed;
    changed = true;
Lorenz Meier's avatar
Lorenz Meier committed
435 436
    /* important, immediately update */
    updateView();
437 438
}

lm's avatar
lm committed
439 440 441
void QGCToolBar::updateView()
{
    if (!changed) return;
442
    if (toolBarWpAction->isVisible())
443 444
        toolBarWpLabel->setText(tr("WP%1").arg(wpId));

445
    if (toolBarBatteryBarAction->isVisible()) {
446 447 448
        toolBarBatteryBar->setValue(batteryPercent);

        if (batteryPercent < 30 && toolBarBatteryBar->value() >= 30) {
449 450 451
            toolBarBatteryBar->setStyleSheet(qgcApp()->styleIsDark() ?
                                             "QProgressBar {color: #000} QProgressBar QProgressBar::chunk { background-color: #0F0}" :
                                             "QProgressBar {color: #FFF} QProgressBar::chunk { background-color: #008000}");
452
        } else if (batteryPercent >= 30 && toolBarBatteryBar->value() < 30){
453 454 455
            toolBarBatteryBar->setStyleSheet(qgcApp()->styleIsDark() ?
                                             "QProgressBar {color: #000} QProgressBar QProgressBar::chunk { background-color: #FF0}" :
                                             "QProgressBar {color: #FFF} QProgressBar::chunk { background-color: #808000}");
456
        }
457

458 459 460
    }
    if (toolBarBatteryVoltageLabel->isVisible()) {
	toolBarBatteryVoltageLabel->setText(tr("%1 V").arg(batteryVoltage, 4, 'f', 1, ' '));
Lorenz Meier's avatar
Lorenz Meier committed
461 462
    }

463 464

//    toolBarStateLabel->setText(QString("%1").arg(state));
465 466 467
    if (mode.size() > 0) {
        toolBarModeLabel->setText(QString("%1").arg(mode));
    }
lm's avatar
lm committed
468
    toolBarNameLabel->setText(systemName);
469
    // expire after 15 seconds
470

471
    if (toolBarMessageAction->isVisible()) {
472 473 474 475 476
        if (QGC::groundTimeMilliseconds() - lastSystemMessageTimeMs < 15000) {
            toolBarMessageLabel->setText(QString("%1").arg(lastSystemMessage));
        } else {
            toolBarMessageLabel->clear();
        }
477
    }
478

479
    // Display the system armed state with a red-on-yellow background if armed or green text if safe.
480 481
    if (systemArmed)
    {
482
        toolBarSafetyLabel->setStyleSheet(QString("QLabel {color: %1; background-color: %2; font-size: 15pt;}").arg(QGC::colorRed.name()).arg(QGC::colorYellow.name()));
483 484 485 486
        toolBarSafetyLabel->setText(tr("ARMED"));
    }
    else
    {
487 488 489
        toolBarSafetyLabel->setStyleSheet(qgcApp()->styleIsDark() ?
                                          "QLabel {color: #14C814; font-size: 15pt;}" :
                                          "QLabel {color: #0D820D; font-size: 15pt;}");
Lorenz Meier's avatar
Lorenz Meier committed
490
        toolBarSafetyLabel->setText(tr("DISARMED"));
491 492
    }

lm's avatar
lm committed
493
    changed = false;
lm's avatar
lm committed
494 495
}

496 497
void QGCToolBar::updateWaypointDistance(double distance)
{
lm's avatar
lm committed
498 499
    if (wpDistance != distance) changed = true;
    wpDistance = distance;
500 501 502 503
}

void QGCToolBar::updateCurrentWaypoint(quint16 id)
{
lm's avatar
lm committed
504
    if (wpId != id) changed = true;
lm's avatar
lm committed
505
    wpId = id;
506 507
}

dongfang's avatar
dongfang committed
508
void QGCToolBar::updateBatteryRemaining(UASInterface* uas, double voltage, double current, double percent, int seconds)
LM's avatar
LM committed
509
{
510 511
    Q_UNUSED(uas);
    Q_UNUSED(seconds);
512
    Q_UNUSED(current);
513

lm's avatar
lm committed
514
    if (batteryPercent != percent || batteryVoltage != voltage) changed = true;
lm's avatar
lm committed
515 516
    batteryPercent = percent;
    batteryVoltage = voltage;
LM's avatar
LM committed
517 518
}

519 520 521 522
void QGCToolBar::updateState(UASInterface* system, QString name, QString description)
{
    Q_UNUSED(system);
    Q_UNUSED(description);
lm's avatar
lm committed
523
    if (state != name) changed = true;
lm's avatar
lm committed
524
    state = name;
Lorenz Meier's avatar
Lorenz Meier committed
525 526
    /* important, immediately update */
    updateView();
527 528 529 530 531 532
}

void QGCToolBar::updateMode(int system, QString name, QString description)
{
    Q_UNUSED(system);
    Q_UNUSED(description);
533 534 535 536 537 538 539 540 541 542
    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
543 544
    /* important, immediately update */
    updateView();
545 546 547 548
}

void QGCToolBar::updateName(const QString& name)
{
Lorenz Meier's avatar
Lorenz Meier committed
549 550 551 552
    if (systemName != name)
    {
        changed = true;
    }
lm's avatar
lm committed
553
    systemName = name;
554 555 556 557 558 559 560 561 562 563 564 565
}

/**
 * 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);
566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626
    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));
627 628
}

LM's avatar
LM committed
629 630 631 632 633
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
634
    if (lastSystemMessage != text) changed = true;
lm's avatar
lm committed
635
    lastSystemMessage = text;
636
    lastSystemMessageTimeMs = QGC::groundTimeMilliseconds();
LM's avatar
LM committed
637 638
}

639 640
void QGCToolBar::addLink(LinkInterface* link)
{
641 642 643 644 645
    // Accept only serial links as current link
    SerialLink* serial = qobject_cast<SerialLink*>(link);

    if (serial && !currentLink)
    {
646 647
        toolBarPortAction->setVisible(true);
        toolBarBaudAction->setVisible(true);
648

649
        currentLink = link;
650 651
        connect(currentLink, &LinkInterface::connected, this, &QGCToolBar::_linkConnected);
        _updateLinkState(link->isConnected());
652 653 654 655

        qDebug() << "ADD LINK";

        updateComboBox();
656 657 658 659 660 661 662
    }
}

void QGCToolBar::removeLink(LinkInterface* link)
{
    if (link == currentLink) {
        currentLink = NULL;
663 664 665 666 667 668 669 670 671

        // Try to get a new serial link
        foreach (SerialLink* s, LinkManager::instance()->getSerialLinks())
        {
            addLink(s);
        }

        // Update GUI according to scan result
        if (currentLink) {
672
            _updateLinkState(currentLink->isConnected());
673
        } else {
674 675 676
            connectButton->setText(tr("New Serial Link"));
            portComboBox->hide();
            baudcomboBox->hide();
677 678
        }
    }
679 680 681 682
    updateComboBox();
}
void QGCToolBar::updateComboBox()
{
683
    if (currentLink && !currentLink->isConnected())
684
    {
Lorenz Meier's avatar
Lorenz Meier committed
685 686 687 688
        // Do not update if not visible
        if (!portComboBox->isVisible())
            return;

689 690
        SerialLink *slink = qobject_cast<SerialLink*>(currentLink);
        QList<QString> portlist = slink->getCurrentPorts();
691 692 693 694 695 696
        foreach (QString port, portlist)
        {
            if (portComboBox->findText(port) == -1)
            {
                portComboBox->addItem(port, port);
            }
697 698
        }

699 700
        if (!userPortChoice) {
            if (slink->getPortName().trimmed().length() > 0)
701
            {
702 703 704 705 706
                int portIndex = portComboBox->findData(slink->getPortName());
                if (portIndex >= 0) {
                    portComboBox->setCurrentIndex(portIndex);
                    portComboBox->setEditText(slink->getPortName());
                }
707 708 709
            }
            else
            {
710 711 712 713 714 715 716 717
                if (portlist.length() > 0)
                {
                    portComboBox->setEditText(portlist.last());
                }
                else
                {
                    portComboBox->setEditText(tr("No serial port found"));
                }
718
            }
719
        }
720 721 722

        if (!userBaudChoice) {
            int index = baudcomboBox->findData(slink->getBaudRate());
723
            if (index >= 0)
724 725
                baudcomboBox->setCurrentIndex(index);
        }
726
    }
727 728
}

729 730 731 732 733 734 735 736 737 738 739
void QGCToolBar::_linkConnected(void)
{
    _updateLinkState(true);
}

void QGCToolBar::_linkDisconnected(void)
{
    _updateLinkState(false);
}

void QGCToolBar::_updateLinkState(bool connected)
740
{
741
    Q_UNUSED(connected);
742
    if (currentLink && currentLink->isConnected() && portComboBox->isVisible())
743 744 745 746 747
    {
        connectButton->setText(tr("Disconnect"));
        connectButton->blockSignals(true);
        connectButton->setChecked(true);
        connectButton->blockSignals(false);
748 749 750 751
        toolBarPortAction->setVisible(false);
        toolBarBaudAction->setVisible(false);
        toolBarMessageAction->setVisible(true);
        toolBarWpAction->setVisible(true);
752 753 754 755 756 757 758
    }
    else
    {
        connectButton->setText(tr("Connect"));
        connectButton->blockSignals(true);
        connectButton->setChecked(false);
        connectButton->blockSignals(false);
759 760 761 762
        toolBarPortAction->setVisible(true);
        toolBarBaudAction->setVisible(true);
        toolBarMessageAction->setVisible(false);
        toolBarWpAction->setVisible(false);
763 764 765
    }
}

766
void QGCToolBar::connectLink(bool connectLink)
767
{
768 769 770
    LinkManager* linkMgr = LinkManager::instance();
    Q_ASSERT(linkMgr);
    
771
    // No serial port yet present
772
    if (connectLink && linkMgr->getSerialLinks().count() == 0) {
773
        MainWindow::instance()->addLink();
774
        currentLink = linkMgr->getLinks().last();
775
    } else if (connectLink) {
776
        SerialLink *link = qobject_cast<SerialLink*>(currentLink);
777 778
        
        if (link) {
779
            link->setPortName(portComboBox->itemData(portComboBox->currentIndex()).toString().trimmed());
780 781
            int baud = baudcomboBox->currentText().toInt();
            link->setBaudRate(baud);
782
            connect(link, &LinkInterface::connected, this, &QGCToolBar::_linkConnected);
783
            linkMgr->connectLink(link);
784
        }
785
    } else if (!connectLink && currentLink) {
786
        linkMgr->disconnectLink(currentLink);
787
        disconnect(currentLink, &LinkInterface::connected, this, &QGCToolBar::_linkConnected);
788 789 790
    }

    if (currentLink) {
791
        _updateLinkState(currentLink->isConnected());
792 793 794
    }
}

795 796 797 798 799 800 801 802 803 804 805 806 807 808 809

void QGCToolBar::loadSettings()
{
    QSettings settings;
    settings.beginGroup("QGC_TOOLBAR");
    settings.endGroup();
}

void QGCToolBar::storeSettings()
{
    QSettings settings;
    settings.beginGroup("QGC_TOOLBAR");
    settings.endGroup();
}

810 811
void QGCToolBar::clearStatusString()
{
Lorenz Meier's avatar
Lorenz Meier committed
812 813 814 815 816
    if (toolBarMessageLabel->text().length() > 0)
    {
        lastSystemMessage = "";
        changed = true;
    }
817 818
}

819 820
QGCToolBar::~QGCToolBar()
{
821
    storeSettings();
822
}