mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-16 10:25:36 +08:00
committed by
Mathew Sutcliffe
parent
1f2a88e502
commit
ab17dabd5b
54
samples/blackgui/main.cpp
Normal file
54
samples/blackgui/main.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#include "mainwindow.h"
|
||||
#include "blackmisc/blackmiscfreefunctions.h"
|
||||
#include <QApplication>
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
|
||||
/*!
|
||||
* \brief Main
|
||||
* \param argc
|
||||
* \param argv
|
||||
* \return
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// register
|
||||
BlackMisc::initResources();
|
||||
BlackMisc::registerMetadata();
|
||||
// BlackMisc::displayAllUserMetatypesTypes();
|
||||
|
||||
QFile file(":/translations/blackmisc_i18n_de.qm");
|
||||
qDebug() << (file.exists() ? "Found translations in resources" : "No translations in resources");
|
||||
QTranslator translator;
|
||||
translator.load("blackmisc_i18n_de", ":/translations/");
|
||||
|
||||
// app
|
||||
QApplication a(argc, argv);
|
||||
a.installTranslator(&translator);
|
||||
|
||||
// window
|
||||
MainWindow w;
|
||||
bool withDBus = false;
|
||||
|
||||
// Dialog to decide external or internal core
|
||||
QMessageBox msgBox;
|
||||
msgBox.setText("How to start the GUI");
|
||||
msgBox.setIcon(QMessageBox::Question);
|
||||
QPushButton *buttonNoDbus = msgBox.addButton("With core included", QMessageBox::AcceptRole);
|
||||
QPushButton *buttonDBus = msgBox.addButton("External core via DBus", QMessageBox::AcceptRole);
|
||||
QPushButton *buttonClose = msgBox.addButton("Close", QMessageBox::RejectRole);
|
||||
msgBox.setDefaultButton(buttonNoDbus);
|
||||
msgBox.exec();
|
||||
if (msgBox.clickedButton() == buttonDBus)
|
||||
withDBus = true;
|
||||
else if (msgBox.clickedButton() == buttonNoDbus)
|
||||
withDBus = false;
|
||||
else if (msgBox.clickedButton() == buttonClose)
|
||||
exit(4);
|
||||
msgBox.close();
|
||||
|
||||
// show window
|
||||
w.show();
|
||||
w.init(withDBus); // object is complete by now
|
||||
return a.exec();
|
||||
}
|
||||
397
samples/blackgui/mainwindow.cpp
Normal file
397
samples/blackgui/mainwindow.cpp
Normal file
@@ -0,0 +1,397 @@
|
||||
#include "mainwindow.h"
|
||||
#include "ui_mainwindow.h"
|
||||
#include "blackgui/atcstationlistmodel.h"
|
||||
#include "blackcore/dbus_server.h"
|
||||
#include "blackcore/context_network.h"
|
||||
|
||||
using namespace BlackCore;
|
||||
using namespace BlackMisc;
|
||||
using namespace BlackGui;
|
||||
using namespace BlackMisc::Network;
|
||||
using namespace BlackMisc::Aviation;
|
||||
using namespace BlackMisc::PhysicalQuantities;
|
||||
using namespace BlackMisc::Geo;
|
||||
using namespace BlackMisc::Settings;
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
MainWindow::MainWindow(QWidget *parent) :
|
||||
QMainWindow(parent), ui(new Ui::MainWindow),
|
||||
m_init(false), m_withDBus(true),
|
||||
m_dBusConnection("dummy"), m_coreRuntime(nullptr),
|
||||
m_atcListOnline(nullptr), m_atcListBooked(nullptr), m_trafficServerList(nullptr), m_aircraftsInRange(nullptr),
|
||||
m_contextNetwork(nullptr), m_contextSettings(nullptr),
|
||||
m_ownAircraft(),
|
||||
m_timerUpdateAtcStationsOnline(nullptr), m_timerUpdateAircraftsInRange(nullptr), m_timerContextWatchdog(nullptr), m_timerCollectedCockpitUpdates(nullptr)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Destructor
|
||||
*/
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
this->gracefulShutdown();
|
||||
delete ui;
|
||||
}
|
||||
|
||||
/*
|
||||
* Graceful shutdown
|
||||
*/
|
||||
void MainWindow::gracefulShutdown()
|
||||
{
|
||||
if (!this->m_init) return;
|
||||
this->m_init = false;
|
||||
|
||||
// if we have a context, we shut some things down
|
||||
if (this->m_contextNetworkAvailable)
|
||||
{
|
||||
this->m_contextNetwork->disconnectFromNetwork();
|
||||
}
|
||||
|
||||
if (this->m_timerUpdateAircraftsInRange)
|
||||
{
|
||||
this->m_timerUpdateAircraftsInRange->disconnect(this);
|
||||
this->m_timerUpdateAircraftsInRange->stop();
|
||||
}
|
||||
if (this->m_timerUpdateAtcStationsOnline)
|
||||
{
|
||||
this->m_timerUpdateAtcStationsOnline->disconnect(this);
|
||||
this->m_timerUpdateAtcStationsOnline->stop();
|
||||
}
|
||||
if (this->m_timerContextWatchdog)
|
||||
{
|
||||
this->m_timerContextWatchdog->disconnect(this);
|
||||
this->m_timerContextWatchdog->stop();
|
||||
}
|
||||
if (this->m_timerCollectedCockpitUpdates)
|
||||
{
|
||||
this->m_timerCollectedCockpitUpdates->disconnect(this);
|
||||
this->m_timerCollectedCockpitUpdates->stop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Select correct main page
|
||||
*/
|
||||
void MainWindow::setMainPage(bool start)
|
||||
{
|
||||
if (start)
|
||||
{
|
||||
this->ui->sw_MainMiddle->setCurrentIndex(0);
|
||||
return;
|
||||
}
|
||||
|
||||
QObject *sender = QObject::sender();
|
||||
if (sender == this->ui->pb_MainConnect || sender == this->ui->pb_MainStatus)
|
||||
this->ui->sw_MainMiddle->setCurrentIndex(0);
|
||||
else if (sender == this->ui->pb_MainAtc)
|
||||
this->ui->sw_MainMiddle->setCurrentIndex(1);
|
||||
else if (sender == this->ui->pb_MainAircrafts)
|
||||
this->ui->sw_MainMiddle->setCurrentIndex(2);
|
||||
else if (sender == this->ui->pb_MainCockpit)
|
||||
this->ui->sw_MainMiddle->setCurrentIndex(3);
|
||||
else if (sender == this->ui->pb_MainTextMessages)
|
||||
this->ui->sw_MainMiddle->setCurrentIndex(4);
|
||||
else if (sender == this->ui->pb_MainFlightplan)
|
||||
this->ui->sw_MainMiddle->setCurrentIndex(5);
|
||||
else if (sender == this->ui->pb_MainSettings)
|
||||
this->ui->sw_MainMiddle->setCurrentIndex(6);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read stations
|
||||
*/
|
||||
void MainWindow::reloadAtcStationsBooked()
|
||||
{
|
||||
if (!this->isContextNetworkAvailableCheck()) return;
|
||||
this->m_atcListBooked->update(this->m_contextNetwork->getAtcStationsBooked());
|
||||
this->ui->tv_AtcStationsBooked->resizeColumnsToContents();
|
||||
}
|
||||
|
||||
/*
|
||||
* Read stations
|
||||
*/
|
||||
void MainWindow::reloadAtcStationsOnline()
|
||||
{
|
||||
if (!this->isContextNetworkAvailableCheck()) return;
|
||||
this->m_atcListOnline->update(this->m_contextNetwork->getAtcStationsOnline());
|
||||
this->ui->tv_AtcStationsOnline->resizeColumnsToContents();
|
||||
}
|
||||
|
||||
/*
|
||||
* Read aircrafts
|
||||
*/
|
||||
void MainWindow::reloadAircraftsInRange()
|
||||
{
|
||||
if (!this->isContextNetworkAvailableCheck()) return;
|
||||
this->m_aircraftsInRange->update(this->m_contextNetwork->getAircraftsInRange());
|
||||
this->ui->tv_AircraftsInRange->resizeColumnsToContents();
|
||||
}
|
||||
|
||||
/*
|
||||
* Read own aircraft
|
||||
*/
|
||||
bool MainWindow::reloadOwnAircraft()
|
||||
{
|
||||
if (!this->isContextNetworkAvailableCheck()) return false;
|
||||
if (this->isCockpitUpdatePending()) return false;
|
||||
CAircraft loadedAircraft = this->m_contextNetwork->getOwnAircraft();
|
||||
if (loadedAircraft == this->m_ownAircraft) return false;
|
||||
|
||||
// changed aircraft
|
||||
this->m_ownAircraft = loadedAircraft;
|
||||
this->updateCockpitFromContext();
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Connect to Network
|
||||
*/
|
||||
void MainWindow::toggleNetworkConnection()
|
||||
{
|
||||
CStatusMessages msgs;
|
||||
if (!this->isContextNetworkAvailableCheck()) return;
|
||||
if (!this->m_contextNetwork->isConnected())
|
||||
{
|
||||
QString cs = this->ui->le_SettingsPlaneCallsign->text();
|
||||
if (cs.isEmpty())
|
||||
{
|
||||
this->displayStatusMessage(CStatusMessage::getValidationError("missing callsign"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Login is based on setting current server
|
||||
msgs = this->m_contextNetwork->connectToNetwork();
|
||||
}
|
||||
else
|
||||
{
|
||||
msgs = this->m_contextNetwork->disconnectFromNetwork();
|
||||
}
|
||||
if (!msgs.isEmpty()) this->displayStatusMessages(msgs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Is the network context available?
|
||||
*/
|
||||
bool MainWindow::isContextNetworkAvailableCheck()
|
||||
{
|
||||
if (this->m_contextNetworkAvailable) return true;
|
||||
this->displayStatusMessage(CStatusMessage(CStatusMessage::TypeCore, CStatusMessage::SeverityError, "Network context not available, no updates this time"));
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Display a status message
|
||||
*/
|
||||
void MainWindow::displayStatusMessage(const CStatusMessage &message)
|
||||
{
|
||||
this->ui->sb_MainStatusBar->showMessage(message.getMessage(), 3000);
|
||||
this->ui->te_StatusMessages->insertPlainText(message.toQString(true).append("\n"));
|
||||
}
|
||||
|
||||
/*
|
||||
* Display a status message
|
||||
*/
|
||||
void MainWindow::displayStatusMessages(const CStatusMessages &messages)
|
||||
{
|
||||
if (messages.isEmpty()) return;
|
||||
foreach(CStatusMessage msg, messages.getMessages())
|
||||
{
|
||||
this->displayStatusMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Menu clicked
|
||||
*/
|
||||
void MainWindow::menuClicked()
|
||||
{
|
||||
QObject *sender = QObject::sender();
|
||||
CStatusMessages msgs;
|
||||
if (sender == this->ui->menu_TestLocationsEDRY)
|
||||
{
|
||||
this->m_contextNetwork->updateOwnPosition(
|
||||
CCoordinateGeodetic(
|
||||
CLatitude::fromWgs84("N 049° 18' 17"),
|
||||
CLongitude::fromWgs84("E 008° 27' 05"),
|
||||
CLength(0, CLengthUnit::m())),
|
||||
CAltitude(312, CAltitude::MeanSeaLevel, CLengthUnit::ft())
|
||||
);
|
||||
}
|
||||
else if (sender == this->ui->menu_ReloadSettings)
|
||||
{
|
||||
this->reloadSettings();
|
||||
msgs.append(CStatusMessage::getInfoMessage("Settings reloaded"));
|
||||
}
|
||||
|
||||
if (!msgs.isEmpty()) this->displayStatusMessages(msgs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Connection terminated
|
||||
*/
|
||||
void MainWindow::connectionTerminated()
|
||||
{
|
||||
this->updateGuiStatusInformation();
|
||||
}
|
||||
|
||||
/*
|
||||
* Connection status changed
|
||||
*/
|
||||
void MainWindow::connectionStatusChanged(uint /** from **/, uint to)
|
||||
{
|
||||
// CContextNetwork::ConnectionStatus statusFrom = static_cast<CContextNetwork::ConnectionStatus>(from);
|
||||
CContextNetwork::ConnectionStatus statusTo = static_cast<CContextNetwork::ConnectionStatus>(to);
|
||||
|
||||
// always
|
||||
this->updateGuiStatusInformation();
|
||||
|
||||
if (statusTo == CContextNetwork::ConnectionStatusConnected)
|
||||
{
|
||||
QTimer::singleShot(5 * 1000, this, SLOT(reloadAircraftsInRange()));
|
||||
QTimer::singleShot(5 * 1000, this, SLOT(reloadAtcStationsOnline()));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Station selected
|
||||
*/
|
||||
void MainWindow::onlineAtcStationSelected(QModelIndex index)
|
||||
{
|
||||
this->ui->te_AtcStationsOnlineInfo->setText(""); // reset
|
||||
const CAtcStation stationClicked = this->m_atcListOnline->at(index);
|
||||
QString infoMessage;
|
||||
|
||||
if (stationClicked.hasAtis())
|
||||
{
|
||||
infoMessage.append(stationClicked.getAtis().getMessage());
|
||||
}
|
||||
if (stationClicked.hasMetar())
|
||||
{
|
||||
if (!infoMessage.isEmpty()) infoMessage.append("\n\n");
|
||||
infoMessage.append(stationClicked.getMetar().getMessage());
|
||||
}
|
||||
|
||||
this->ui->te_AtcStationsOnlineInfo->setText(infoMessage);
|
||||
}
|
||||
|
||||
/*
|
||||
* Timer event
|
||||
*/
|
||||
void MainWindow::updateTimer()
|
||||
{
|
||||
QObject *sender = QObject::sender();
|
||||
if (sender == this->m_timerUpdateAtcStationsOnline)
|
||||
{
|
||||
int t = this->ui->hs_AtcStationsOnline->value() * 1000;
|
||||
this->m_timerUpdateAtcStationsOnline->start(t);
|
||||
if (ui->tv_AtcStationsOnline->isVisible())
|
||||
this->reloadAtcStationsOnline();
|
||||
}
|
||||
if (sender == this->m_timerUpdateAircraftsInRange)
|
||||
{
|
||||
int t = this->ui->hs_AtcStationsOnline->value() * 1000;
|
||||
this->m_timerUpdateAircraftsInRange->start(t);
|
||||
if (ui->tv_AircraftsInRange->isVisible())
|
||||
this->reloadAircraftsInRange();
|
||||
}
|
||||
else if (sender == this->m_timerContextWatchdog)
|
||||
{
|
||||
qint64 t = QDateTime::currentMSecsSinceEpoch();
|
||||
m_contextNetworkAvailable = (this->m_contextNetwork->usingLocalObjects() || (this->m_contextNetwork->ping(t) == t));
|
||||
this->updateGuiStatusInformation();
|
||||
}
|
||||
|
||||
// own aircraft
|
||||
if (sender == this->m_timerUpdateAircraftsInRange || sender == this->m_timerUpdateAtcStationsOnline)
|
||||
{
|
||||
this->reloadOwnAircraft(); // regular updates
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get METAR
|
||||
*/
|
||||
void MainWindow::getMetar(const QString &airportIcaoCode)
|
||||
{
|
||||
if (!this->isContextNetworkAvailableCheck()) return;
|
||||
if (!this->m_contextNetwork->isConnected()) return;
|
||||
QString icao = airportIcaoCode.isEmpty() ? this->ui->le_AtcStationsOnlineMetar->text().trimmed().toUpper() : airportIcaoCode.trimmed().toUpper();
|
||||
this->ui->le_AtcStationsOnlineMetar->setText(icao);
|
||||
if (icao.length() != 4) return;
|
||||
CInformationMessage metar = this->m_contextNetwork->getMetar(icao);
|
||||
if (metar.getType() != CInformationMessage::METAR) return;
|
||||
if (metar.isEmpty()) return;
|
||||
this->ui->te_AtcStationsOnlineInfo->setText(metar.getMessage());
|
||||
}
|
||||
|
||||
/*
|
||||
* ATC station tab changed are changed
|
||||
*/
|
||||
void MainWindow::atcStationTabChanged(int /** tabIndex **/)
|
||||
{
|
||||
if (this->isContextNetworkAvailableCheck())
|
||||
{
|
||||
if (this->ui->tw_AtcStations->currentWidget() == this->ui->tb_AtcStationsBooked)
|
||||
{
|
||||
if (this->m_atcListBooked->rowCount() < 1)
|
||||
this->reloadAtcStationsBooked();
|
||||
}
|
||||
else if (this->ui->tw_AtcStations->currentWidget() == this->ui->tb_AtcStationsOnline)
|
||||
{
|
||||
this->reloadAtcStationsOnline();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Middle panel changed
|
||||
*/
|
||||
void MainWindow::middlePanelChanged(int /* index */)
|
||||
{
|
||||
if (this->isContextNetworkAvailableCheck())
|
||||
{
|
||||
// remark, ATC stations is handled by tab changed
|
||||
|
||||
if (this->ui->sw_MainMiddle->currentWidget() == this->ui->pg_AircraftsInRange)
|
||||
{
|
||||
if (this->m_aircraftsInRange->rowCount() < 1)
|
||||
this->reloadAircraftsInRange();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Update GUI
|
||||
*/
|
||||
void MainWindow::updateGuiStatusInformation()
|
||||
{
|
||||
if (this->m_contextNetworkAvailable)
|
||||
{
|
||||
const QString now = QDateTime::currentDateTimeUtc().toString("yyyy-MM-dd HH:mm:ss");
|
||||
this->ui->le_networkContextAvailable->setText(
|
||||
this->m_contextNetwork->usingLocalObjects() ? "local" :
|
||||
now);
|
||||
if (this->m_contextNetwork->isConnected())
|
||||
{
|
||||
this->ui->pb_MainConnect->setText("Disconnect");
|
||||
this->ui->pb_MainConnect->setStyleSheet("background-color: green");
|
||||
if (!this->ui->le_StatusNetworkConnected->text().startsWith("2"))
|
||||
this->ui->le_StatusNetworkConnected->setText(now);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->ui->pb_MainConnect->setText("Connect");
|
||||
this->ui->pb_MainConnect->setStyleSheet("background-color:");
|
||||
this->ui->le_StatusNetworkConnected->setText("Disconnected");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->ui->le_networkContextAvailable->setText("Not available");
|
||||
}
|
||||
}
|
||||
294
samples/blackgui/mainwindow.h
Normal file
294
samples/blackgui/mainwindow.h
Normal file
@@ -0,0 +1,294 @@
|
||||
#ifndef BLACKMISC_MAINWINDOW_H
|
||||
#define BLACKMISC_MAINWINDOW_H
|
||||
|
||||
// clash with struct interface in objbase.h used to happen
|
||||
#pragma push_macro("interface")
|
||||
#undef interface
|
||||
|
||||
#include "blackgui/atcstationlistmodel.h"
|
||||
#include "blackgui/serverlistmodel.h"
|
||||
#include "blackgui/aircraftlistmodel.h"
|
||||
#include "blackmisc/statusmessage.h"
|
||||
#include "blackmisc/nwtextmessage.h"
|
||||
#include "blackcore/context_network_interface.h"
|
||||
#include "blackcore/context_settings_interface.h"
|
||||
#include "blackcore/coreruntime.h"
|
||||
#include <QMainWindow>
|
||||
#include <QTextEdit>
|
||||
#include <QItemSelection>
|
||||
#include <QTimer>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief GUI
|
||||
*/
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/*!
|
||||
* \brief Constructor
|
||||
* \param parent
|
||||
*/
|
||||
explicit MainWindow(QWidget *parent = nullptr);
|
||||
|
||||
/*!
|
||||
* Destructor
|
||||
*/
|
||||
~MainWindow();
|
||||
|
||||
/*!
|
||||
* \brief Init data
|
||||
* \param withDBus
|
||||
*/
|
||||
void init(bool withDBus);
|
||||
|
||||
/*!
|
||||
* \brief Graceful shutdown
|
||||
*/
|
||||
void gracefulShutdown();
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
bool m_init;
|
||||
bool m_withDBus;
|
||||
bool m_contextNetworkAvailable;
|
||||
QDBusConnection m_dBusConnection;
|
||||
BlackCore::CCoreRuntime *m_coreRuntime; /*!< runtime, if working with local core */
|
||||
BlackGui::CAtcListModel *m_atcListOnline;
|
||||
BlackGui::CAtcListModel *m_atcListBooked;
|
||||
BlackGui::CServerListModel *m_trafficServerList;
|
||||
BlackGui::CAircraftListModel *m_aircraftsInRange;
|
||||
BlackCore::IContextNetwork *m_contextNetwork;
|
||||
BlackCore::IContextSettings *m_contextSettings;
|
||||
BlackMisc::Aviation::CAircraft m_ownAircraft;
|
||||
QTimer *m_timerUpdateAtcStationsOnline;
|
||||
QTimer *m_timerUpdateAircraftsInRange;
|
||||
QTimer *m_timerCollectedCockpitUpdates;
|
||||
QTimer *m_timerContextWatchdog;
|
||||
|
||||
/*!
|
||||
* \brief GUI status update
|
||||
*/
|
||||
void updateGuiStatusInformation();
|
||||
|
||||
/*!
|
||||
* \brief Update the selected server textboxs
|
||||
* \param server
|
||||
*/
|
||||
void updateGuiSelectedServerTextboxes(const BlackMisc::Network::CServer &server);
|
||||
|
||||
/*!
|
||||
* \brief Selected server from textboxes
|
||||
* \return
|
||||
*/
|
||||
BlackMisc::Network::CServer selectedServerFromTextboxes() const;
|
||||
|
||||
/*!
|
||||
* \brief 1st data reads
|
||||
*/
|
||||
void initialDataReads();
|
||||
|
||||
/*!
|
||||
* \brief Context network available check, otherwise status message
|
||||
* \return
|
||||
*/
|
||||
bool isContextNetworkAvailableCheck();
|
||||
|
||||
/*!
|
||||
* \brief Own cockpit, update from context
|
||||
*/
|
||||
void updateCockpitFromContext();
|
||||
|
||||
/*!
|
||||
* \brief Pending cockpit update operation
|
||||
* \return
|
||||
*/
|
||||
bool isCockpitUpdatePending() const;
|
||||
|
||||
/*!
|
||||
* \brief Add new text message tab
|
||||
* \param tabName
|
||||
* \return
|
||||
*/
|
||||
QWidget *addNewTextMessageTab(const QString &tabName);
|
||||
|
||||
/*!
|
||||
* \brief Find text message tab by name
|
||||
* \param name
|
||||
* \return
|
||||
*/
|
||||
QWidget *findTextMessageTabByName(const QString &name);
|
||||
|
||||
/*!
|
||||
* \brief Private channel text message
|
||||
* \param textMessage
|
||||
* \param sending
|
||||
*/
|
||||
void addPrivateChannelTextMessage(const BlackMisc::Network::CTextMessage &textMessage, bool sending = false);
|
||||
|
||||
/*!
|
||||
* \brief stub for sending a text message (eihter radio or private message)
|
||||
* \return
|
||||
*/
|
||||
BlackMisc::Network::CTextMessage getTextMessageStubForChannel();
|
||||
|
||||
private slots:
|
||||
|
||||
//
|
||||
// Data received related slots
|
||||
//
|
||||
|
||||
/*!
|
||||
* \brief Reload booked stations
|
||||
*/
|
||||
void reloadAtcStationsBooked();
|
||||
|
||||
/*!
|
||||
* \brief Reload online stations
|
||||
*/
|
||||
void reloadAtcStationsOnline();
|
||||
|
||||
/*!
|
||||
* \brief Reload aircrafts in range
|
||||
*/
|
||||
void reloadAircraftsInRange();
|
||||
|
||||
/*!
|
||||
* \brief Reload own aircraft
|
||||
* \return
|
||||
*/
|
||||
bool reloadOwnAircraft();
|
||||
|
||||
/*!
|
||||
* \brief Display status message
|
||||
* \param message
|
||||
*/
|
||||
void displayStatusMessage(const BlackMisc::CStatusMessage &message);
|
||||
|
||||
/*!
|
||||
* \brief Display status messages
|
||||
* \param messages
|
||||
*/
|
||||
void displayStatusMessages(const BlackMisc::CStatusMessages &messages);
|
||||
|
||||
/*!
|
||||
* \brief Connection status changed
|
||||
* \param from
|
||||
* \param to
|
||||
*/
|
||||
void connectionStatusChanged(uint from, uint to);
|
||||
|
||||
/*!
|
||||
* \brief Text messages received
|
||||
* \param messages
|
||||
* \param sending
|
||||
*/
|
||||
void textMessageReceived(const BlackMisc::Network::CTextMessageList &messages, bool sending = false);
|
||||
|
||||
/*!
|
||||
* \brief Reload settings
|
||||
*/
|
||||
void reloadSettings();
|
||||
|
||||
/*!
|
||||
* \brief Send cockpit updates
|
||||
*/
|
||||
void sendCockpitUpdates();
|
||||
|
||||
//
|
||||
// GUI related slots
|
||||
//
|
||||
|
||||
/*!
|
||||
* \brief Set the main page
|
||||
*/
|
||||
void setMainPage(bool start = false);
|
||||
|
||||
/*!
|
||||
* \brief Connect to network
|
||||
* \param userId
|
||||
* \param password
|
||||
*/
|
||||
void toggleNetworkConnection();
|
||||
|
||||
/*!
|
||||
* \brief Menu item clicked
|
||||
*/
|
||||
void menuClicked();
|
||||
|
||||
/*!
|
||||
* \brief Terminated connection
|
||||
*/
|
||||
void connectionTerminated();
|
||||
|
||||
/*!
|
||||
* \brief Network server selected
|
||||
* \param index
|
||||
*/
|
||||
void networkServerSelected(QModelIndex index);
|
||||
|
||||
/*!
|
||||
* \brief Online ATC station selected
|
||||
* \param index
|
||||
*/
|
||||
void onlineAtcStationSelected(QModelIndex index);
|
||||
|
||||
/*!
|
||||
* \brief Alter traffic server
|
||||
*/
|
||||
void alterTrafficServer();
|
||||
|
||||
/*!
|
||||
* \brief Network settings have been changed
|
||||
*/
|
||||
void changedNetworkSettings();
|
||||
|
||||
/*!
|
||||
* \brief Update timer
|
||||
*/
|
||||
void updateTimer();
|
||||
|
||||
/*!
|
||||
* \brief ATC station, tab changed, reload data
|
||||
* \param tabIndex
|
||||
*/
|
||||
void atcStationTabChanged(int tabIndex);
|
||||
|
||||
/*!
|
||||
* \brief Middle panel has changed, reload data
|
||||
* \param index
|
||||
*/
|
||||
void middlePanelChanged(int index);
|
||||
|
||||
/*!
|
||||
* \brief Command entered
|
||||
*/
|
||||
void commandEntered();
|
||||
|
||||
/*!
|
||||
* \brief Get METAR
|
||||
* \param airportIcaoCode
|
||||
*/
|
||||
void getMetar(const QString &airportIcaoCode = "");
|
||||
|
||||
/*!
|
||||
* \brief Close text message tab
|
||||
*/
|
||||
void closeTextMessageTab();
|
||||
|
||||
/*!
|
||||
* \brief Cockpit values changed
|
||||
*/
|
||||
void cockpitValuesChanged();
|
||||
|
||||
};
|
||||
|
||||
#pragma pop_macro("interface")
|
||||
|
||||
#endif // guard
|
||||
1736
samples/blackgui/mainwindow.ui
Normal file
1736
samples/blackgui/mainwindow.ui
Normal file
File diff suppressed because it is too large
Load Diff
131
samples/blackgui/mainwindow_cockpit.cpp
Normal file
131
samples/blackgui/mainwindow_cockpit.cpp
Normal file
@@ -0,0 +1,131 @@
|
||||
#include "mainwindow.h"
|
||||
#include "ui_mainwindow.h"
|
||||
#include "blackgui/atcstationlistmodel.h"
|
||||
#include "blackcore/dbus_server.h"
|
||||
#include "blackcore/context_network.h"
|
||||
|
||||
using namespace BlackCore;
|
||||
using namespace BlackMisc;
|
||||
using namespace BlackGui;
|
||||
using namespace BlackMisc::Network;
|
||||
using namespace BlackMisc::Aviation;
|
||||
using namespace BlackMisc::PhysicalQuantities;
|
||||
using namespace BlackMisc::Geo;
|
||||
using namespace BlackMisc::Settings;
|
||||
using namespace BlackMisc::Math;
|
||||
|
||||
/*
|
||||
* Cockpit values
|
||||
*/
|
||||
void MainWindow::cockpitValuesChanged()
|
||||
{
|
||||
Q_ASSERT(this->m_timerCollectedCockpitUpdates);
|
||||
this->m_timerCollectedCockpitUpdates->stop();
|
||||
this->m_timerCollectedCockpitUpdates->start(1000); // start
|
||||
this->m_timerCollectedCockpitUpdates->setSingleShot(true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Is pending update
|
||||
*/
|
||||
bool MainWindow::isCockpitUpdatePending() const
|
||||
{
|
||||
return (this->m_timerCollectedCockpitUpdates && this->m_timerCollectedCockpitUpdates->isActive());
|
||||
}
|
||||
|
||||
/*
|
||||
* Own cockpit
|
||||
*/
|
||||
void MainWindow::updateCockpitFromContext()
|
||||
{
|
||||
// update GUI elements
|
||||
// avoid unnecessary change events as far as possible
|
||||
const CComSystem com1 = this->m_ownAircraft.getCom1System();
|
||||
const CComSystem com2 = this->m_ownAircraft.getCom2System();
|
||||
const CTransponder transponder = this->m_ownAircraft.getTransponder();
|
||||
|
||||
double freq = com1.getFrequencyActive().valueRounded(3);
|
||||
if (freq != this->ui->ds_CockpitCom1Active->value())
|
||||
this->ui->ds_CockpitCom1Active->setValue(freq);
|
||||
|
||||
freq = com2.getFrequencyActive().valueRounded(3);
|
||||
if (freq != this->ui->ds_CockpitCom2Active->value())
|
||||
this->ui->ds_CockpitCom2Active->setValue(freq);
|
||||
|
||||
freq = com1.getFrequencyStandby().valueRounded(3);
|
||||
if (freq != this->ui->ds_CockpitCom1Standby->value())
|
||||
this->ui->ds_CockpitCom1Standby->setValue(freq);
|
||||
|
||||
freq = com2.getFrequencyStandby().valueRounded(3);
|
||||
if (freq != this->ui->ds_CockpitCom2Standby->value())
|
||||
this->ui->ds_CockpitCom2Standby->setValue(freq);
|
||||
|
||||
qint32 tc = transponder.getTransponderCode();
|
||||
if (tc != static_cast<qint32>(this->ui->ds_CockpitTransponder->value()))
|
||||
this->ui->ds_CockpitTransponder->setValue(tc);
|
||||
|
||||
QString tm = this->ui->cb_CockpitTransponderMode->currentText().trimmed().toUpper();
|
||||
switch (transponder.getTransponderMode())
|
||||
{
|
||||
case CTransponder::StateStandby:
|
||||
case CTransponder::ModeS:
|
||||
if (tm != "S")
|
||||
this->ui->cb_CockpitTransponderMode->setCurrentText("S");
|
||||
break;
|
||||
case CTransponder::ModeC:
|
||||
if (tm != "C")
|
||||
this->ui->cb_CockpitTransponderMode->setCurrentText("C");
|
||||
break;
|
||||
case CTransponder::StateIdent:
|
||||
if (tm != "I")
|
||||
this->ui->cb_CockpitTransponderMode->setCurrentText("I");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Send cockpit updates
|
||||
*/
|
||||
void MainWindow::sendCockpitUpdates()
|
||||
{
|
||||
CTransponder transponder = this->m_ownAircraft.getTransponder();
|
||||
CComSystem com1 = this->m_ownAircraft.getCom1System();
|
||||
CComSystem com2 = this->m_ownAircraft.getCom2System();
|
||||
|
||||
QString transponderCode = QString::number(qRound(this->ui->ds_CockpitTransponder->value()));
|
||||
if (CTransponder::isValidTransponderCode(transponderCode))
|
||||
{
|
||||
transponder.setTransponderCode(transponderCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->displayStatusMessage(CStatusMessage::getValidationError("Wrong transponder code"));
|
||||
return;
|
||||
}
|
||||
|
||||
QString tm = this->ui->cb_CockpitTransponderMode->currentText().toUpper();
|
||||
if (tm == "S")
|
||||
transponder.setTransponderMode(CTransponder::ModeS);
|
||||
else if (tm == "C")
|
||||
transponder.setTransponderMode(CTransponder::ModeC);
|
||||
else if (tm == "I")
|
||||
transponder.setTransponderMode(CTransponder::StateIdent);
|
||||
|
||||
com1.setFrequencyActiveMHz(this->ui->ds_CockpitCom1Active->value());
|
||||
com1.setFrequencyStandbyMHz(this->ui->ds_CockpitCom1Standby->value());
|
||||
com2.setFrequencyActiveMHz(this->ui->ds_CockpitCom2Active->value());
|
||||
com2.setFrequencyStandbyMHz(this->ui->ds_CockpitCom2Standby->value());
|
||||
|
||||
if (this->m_contextNetworkAvailable)
|
||||
{
|
||||
if (this->m_ownAircraft.getCom1System() != com1 ||
|
||||
this->m_ownAircraft.getCom2System() != com2 ||
|
||||
this->m_ownAircraft.getTransponder() != transponder)
|
||||
{
|
||||
this->m_contextNetwork->updateOwnCockpit(com1, com2, transponder);
|
||||
this->reloadOwnAircraft();
|
||||
}
|
||||
}
|
||||
}
|
||||
161
samples/blackgui/mainwindow_init.cpp
Normal file
161
samples/blackgui/mainwindow_init.cpp
Normal file
@@ -0,0 +1,161 @@
|
||||
#include "mainwindow.h"
|
||||
#include "ui_mainwindow.h"
|
||||
#include "blackgui/atcstationlistmodel.h"
|
||||
#include "blackcore/dbus_server.h"
|
||||
#include "blackcore/context_network.h"
|
||||
#include "blackcore/coreruntime.h"
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
using namespace BlackCore;
|
||||
using namespace BlackMisc;
|
||||
using namespace BlackGui;
|
||||
|
||||
|
||||
/*
|
||||
* Init data
|
||||
*/
|
||||
void MainWindow::init(bool withDBus)
|
||||
{
|
||||
if (this->m_init) return;
|
||||
this->m_init = true;
|
||||
this->m_withDBus = withDBus;
|
||||
|
||||
// init models, the delete allows to re-init
|
||||
if (this->m_atcListBooked != nullptr) this->m_atcListBooked->deleteLater();
|
||||
this->m_atcListBooked = new CAtcListModel(this);
|
||||
|
||||
if (this->m_atcListOnline != nullptr) this->m_atcListOnline->deleteLater();
|
||||
this->m_atcListOnline = new CAtcListModel(this);
|
||||
|
||||
if (this->m_trafficServerList != nullptr) this->m_trafficServerList->deleteLater();
|
||||
this->m_trafficServerList = new CServerListModel(this);
|
||||
|
||||
if (this->m_aircraftsInRange != nullptr) this->m_aircraftsInRange->deleteLater();
|
||||
this->m_aircraftsInRange = new CAircraftListModel(this);
|
||||
|
||||
// set sort order and models
|
||||
// enable first, otherwise order in the model will be reset
|
||||
this->ui->tv_AtcStationsOnline->setSortingEnabled(true);
|
||||
this->ui->tv_AtcStationsOnline->setModel(this->m_atcListOnline);
|
||||
if (this->m_atcListOnline->hasValidSortColumn())
|
||||
this->ui->tv_AtcStationsOnline->horizontalHeader()->setSortIndicator(this->m_atcListOnline->getSortColumn(), this->m_atcListOnline->getSortOrder());
|
||||
|
||||
this->m_atcListBooked->setSortColumnByPropertyIndex(BlackMisc::Aviation::CAtcStation::IndexBookedFrom);
|
||||
this->ui->tv_AtcStationsBooked->setSortingEnabled(true);
|
||||
this->ui->tv_AtcStationsBooked->setModel(this->m_atcListBooked);
|
||||
if (this->m_atcListBooked->hasValidSortColumn())
|
||||
this->ui->tv_AtcStationsBooked->horizontalHeader()->setSortIndicator(this->m_atcListBooked->getSortColumn(), this->m_atcListBooked->getSortOrder());
|
||||
|
||||
this->ui->tv_AircraftsInRange->setSortingEnabled(true);
|
||||
this->ui->tv_AircraftsInRange->setModel(this->m_aircraftsInRange);
|
||||
if (this->m_aircraftsInRange->hasValidSortColumn())
|
||||
this->ui->tv_AircraftsInRange->horizontalHeader()->setSortIndicator(this->m_aircraftsInRange->getSortColumn(), this->m_aircraftsInRange->getSortOrder());
|
||||
|
||||
this->ui->tv_SettingsTnServers->setModel(this->m_trafficServerList);
|
||||
|
||||
if (this->m_timerUpdateAircraftsInRange == nullptr) this->m_timerUpdateAircraftsInRange = new QTimer(this);
|
||||
if (this->m_timerUpdateAtcStationsOnline == nullptr) this->m_timerUpdateAtcStationsOnline = new QTimer(this);
|
||||
if (this->m_timerContextWatchdog == nullptr) this->m_timerContextWatchdog = new QTimer(this);
|
||||
if (this->m_timerCollectedCockpitUpdates == nullptr) this->m_timerCollectedCockpitUpdates = new QTimer(this);
|
||||
|
||||
// context
|
||||
if (this->m_withDBus)
|
||||
{
|
||||
this->m_dBusConnection = QDBusConnection::sessionBus();
|
||||
this->m_contextNetwork = new BlackCore::IContextNetwork(BlackCore::CDBusServer::ServiceName, this->m_dBusConnection, this);
|
||||
this->m_contextSettings = new BlackCore::IContextSettings(BlackCore::CDBusServer::ServiceName, this->m_dBusConnection, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->m_coreRuntime = new CCoreRuntime(false, this);
|
||||
this->m_contextNetwork = this->m_coreRuntime->getIContextNetwork();
|
||||
this->m_contextSettings = this->m_coreRuntime->getIContextSettings();
|
||||
}
|
||||
|
||||
// relay status messages
|
||||
bool connect;
|
||||
connect = this->connect(this->m_contextNetwork, SIGNAL(statusMessage(BlackMisc::CStatusMessage)),
|
||||
this, SLOT(displayStatusMessage(BlackMisc::CStatusMessage)));
|
||||
Q_ASSERT_X(connect, "init", "cannot connect status message");
|
||||
|
||||
connect = this->connect(this->m_contextNetwork, SIGNAL(connectionTerminated()),
|
||||
this, SLOT(connectionTerminated()));
|
||||
Q_ASSERT_X(connect, "init", "cannot connect terminating");
|
||||
|
||||
connect = this->connect(this->m_contextNetwork, SIGNAL(connectionStatusChanged(uint, uint)),
|
||||
this, SLOT(connectionStatusChanged(uint, uint)));
|
||||
Q_ASSERT_X(connect, "init", "cannot connect change connection status");
|
||||
|
||||
connect = this->connect(this->m_contextSettings, SIGNAL(changedNetworkSettings()),
|
||||
this, SLOT(changedNetworkSettings()));
|
||||
Q_ASSERT_X(connect, "init", "cannot connect change network status");
|
||||
|
||||
connect = this->connect(this->m_contextNetwork, SIGNAL(textMessagesReceived(BlackMisc::Network::CTextMessageList)),
|
||||
this, SLOT(textMessageReceived(BlackMisc::Network::CTextMessageList)));
|
||||
Q_ASSERT_X(connect, "init", "cannot connect text message received");
|
||||
|
||||
connect = this->connect(this->m_timerUpdateAircraftsInRange, SIGNAL(timeout()),
|
||||
this, SLOT(updateTimer()));
|
||||
Q_ASSERT_X(connect, "init", "cannot connect timer");
|
||||
|
||||
connect = this->connect(this->m_timerUpdateAtcStationsOnline, SIGNAL(timeout()),
|
||||
this, SLOT(updateTimer()));
|
||||
Q_ASSERT_X(connect, "init", "cannot connect timer");
|
||||
|
||||
connect = this->connect(this->m_timerContextWatchdog, SIGNAL(timeout()),
|
||||
this, SLOT(updateTimer()));
|
||||
Q_ASSERT_X(connect, "init", "cannot connect timer (watchdog)");
|
||||
|
||||
connect = this->connect(this->m_timerCollectedCockpitUpdates, SIGNAL(timeout()),
|
||||
this, SLOT(sendCockpitUpdates()));
|
||||
Q_ASSERT_X(connect, "init", "cannot connect timer (cockpit updates)");
|
||||
|
||||
//
|
||||
// GUI
|
||||
//
|
||||
connect = this->connect(this->ui->tw_AtcStations, SIGNAL(currentChanged(int)),
|
||||
this, SLOT(atcStationTabChanged(int)));
|
||||
Q_ASSERT_X(connect, "init", "cannot connect stations tab changed");
|
||||
|
||||
connect = this->connect(this->ui->sw_MainMiddle, SIGNAL(currentChanged(int)),
|
||||
this, SLOT(middlePanelChanged(int)));
|
||||
Q_ASSERT_X(connect, "init", "cannot connect middle panle changed");
|
||||
|
||||
|
||||
// start timers
|
||||
this->m_timerUpdateAircraftsInRange->start(10 * 1000);
|
||||
this->m_timerUpdateAtcStationsOnline->start(10 * 1000);
|
||||
this->m_timerContextWatchdog->start(2 * 1000);
|
||||
|
||||
// data
|
||||
this->initialDataReads();
|
||||
|
||||
// start screen
|
||||
this->setMainPage(true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Init data when started
|
||||
*/
|
||||
void MainWindow::initialDataReads()
|
||||
{
|
||||
qint64 t = QDateTime::currentMSecsSinceEpoch();
|
||||
m_contextNetworkAvailable = (this->m_contextNetwork->usingLocalObjects() || (this->m_contextNetwork->ping(t) == t));
|
||||
if (!this->m_contextNetworkAvailable)
|
||||
{
|
||||
this->displayStatusMessage(CStatusMessage(CStatusMessage::TypeCore, CStatusMessage::SeverityError,
|
||||
"No initial data read as network context is not available"));
|
||||
return;
|
||||
}
|
||||
|
||||
this->reloadSettings(); // init read
|
||||
this->reloadAtcStationsBooked(); // init read, to do this no traffic network required
|
||||
this->reloadOwnAircraft(); // init read, independent of traffic network
|
||||
|
||||
if (this->m_contextNetwork->isConnected())
|
||||
{
|
||||
// connection is already established
|
||||
this->reloadAircraftsInRange();
|
||||
this->updateGuiStatusInformation();
|
||||
}
|
||||
}
|
||||
114
samples/blackgui/mainwindow_settings.cpp
Normal file
114
samples/blackgui/mainwindow_settings.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
#include "mainwindow.h"
|
||||
#include "ui_mainwindow.h"
|
||||
#include "blackgui/atcstationlistmodel.h"
|
||||
#include "blackcore/dbus_server.h"
|
||||
#include "blackcore/context_network.h"
|
||||
|
||||
using namespace BlackCore;
|
||||
using namespace BlackMisc;
|
||||
using namespace BlackGui;
|
||||
using namespace BlackMisc::Network;
|
||||
using namespace BlackMisc::Aviation;
|
||||
using namespace BlackMisc::PhysicalQuantities;
|
||||
using namespace BlackMisc::Geo;
|
||||
using namespace BlackMisc::Settings;
|
||||
|
||||
/*
|
||||
* Reload settings
|
||||
*/
|
||||
void MainWindow::reloadSettings()
|
||||
{
|
||||
// local copy
|
||||
CSettingsNetwork nws = this->m_contextSettings->getNetworkSettings();
|
||||
|
||||
// update servers
|
||||
this->m_trafficServerList->setSelectedServer(nws.getCurrentNetworkServer());
|
||||
this->m_trafficServerList->update(nws.getTrafficNetworkServers());
|
||||
}
|
||||
|
||||
/*
|
||||
* Network has been selected
|
||||
*/
|
||||
void MainWindow::networkServerSelected(QModelIndex index)
|
||||
{
|
||||
const CServer clickedServer = this->m_trafficServerList->at(index);
|
||||
this->updateGuiSelectedServerTextboxes(clickedServer);
|
||||
}
|
||||
|
||||
/*
|
||||
* Alter server
|
||||
*/
|
||||
void MainWindow::alterTrafficServer()
|
||||
{
|
||||
CServer server = this->selectedServerFromTextboxes();
|
||||
if (!server.isValidForLogin())
|
||||
{
|
||||
const CStatusMessage validation = CStatusMessage::getValidationError("Wrong settings for server");
|
||||
this->displayStatusMessage(validation);
|
||||
return;
|
||||
}
|
||||
|
||||
const QString path = CSettingUtilities::appendPaths(IContextSettings::PathNetworkSettings(), CSettingsNetwork::PathTrafficServer());
|
||||
QObject *sender = QObject::sender();
|
||||
CStatusMessages msgs;
|
||||
if (sender == this->ui->pb_SettingsTnCurrentServer)
|
||||
{
|
||||
msgs = this->m_contextSettings->value(path, CSettingsNetwork::CmdSetCurrentServer(), server.toQVariant());
|
||||
}
|
||||
else if (sender == this->ui->pb_SettingsTnRemoveServer)
|
||||
{
|
||||
msgs = this->m_contextSettings->value(path, CSettingUtilities::CmdRemove(), server.toQVariant());
|
||||
}
|
||||
else if (sender == this->ui->pb_SettingsTnSaveServer)
|
||||
{
|
||||
msgs = this->m_contextSettings->value(path, CSettingUtilities::CmdUpdate(), server.toQVariant());
|
||||
}
|
||||
|
||||
// status messages
|
||||
this->displayStatusMessages(msgs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Network settings did changed
|
||||
*/
|
||||
void MainWindow::changedNetworkSettings()
|
||||
{
|
||||
this->reloadSettings();
|
||||
}
|
||||
|
||||
/*
|
||||
* Textboxes from server
|
||||
*/
|
||||
void MainWindow::updateGuiSelectedServerTextboxes(const CServer &server)
|
||||
{
|
||||
this->ui->le_SettingsTnCsName->setText(server.getName());
|
||||
this->ui->le_SettingsTnCsDescription->setText(server.getDescription());
|
||||
this->ui->le_SettingsTnCsAddress->setText(server.getAddress());
|
||||
this->ui->le_SettingsTnCsPort->setText(QString::number(server.getPort()));
|
||||
this->ui->le_SettingsTnCsRealname->setText(server.getUser().getRealname());
|
||||
this->ui->le_SettingsTnCsNetworkId->setText(server.getUser().getId());
|
||||
this->ui->le_SettingsTnCsPassword->setText(server.getUser().getPassword());
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Server settings from textboxes
|
||||
*/
|
||||
CServer MainWindow::selectedServerFromTextboxes() const
|
||||
{
|
||||
CServer server;
|
||||
bool portOk = false;
|
||||
server.setName(this->ui->le_SettingsTnCsName->text());
|
||||
server.setDescription(this->ui->le_SettingsTnCsDescription->text());
|
||||
server.setAddress(this->ui->le_SettingsTnCsAddress->text());
|
||||
server.setPort(this->ui->le_SettingsTnCsPort->text().toInt(&portOk));
|
||||
if (!portOk) server.setPort(-1);
|
||||
|
||||
CUser user;
|
||||
user.setRealname(this->ui->le_SettingsTnCsRealname->text());
|
||||
user.setId(this->ui->le_SettingsTnCsNetworkId->text());
|
||||
user.setPassword(this->ui->le_SettingsTnCsPassword->text());
|
||||
server.setUser(user);
|
||||
|
||||
return server;
|
||||
}
|
||||
269
samples/blackgui/mainwindow_textmessages.cpp
Normal file
269
samples/blackgui/mainwindow_textmessages.cpp
Normal file
@@ -0,0 +1,269 @@
|
||||
#include "mainwindow.h"
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
using namespace BlackCore;
|
||||
using namespace BlackMisc;
|
||||
using namespace BlackGui;
|
||||
using namespace BlackMisc::Network;
|
||||
using namespace BlackMisc::Aviation;
|
||||
using namespace BlackMisc::PhysicalQuantities;
|
||||
using namespace BlackMisc::Geo;
|
||||
using namespace BlackMisc::Settings;
|
||||
|
||||
/*
|
||||
* Text messages received
|
||||
*/
|
||||
void MainWindow::textMessageReceived(const CTextMessageList &messages, bool sending)
|
||||
{
|
||||
if (messages.isEmpty()) return;
|
||||
foreach(CTextMessage message, messages)
|
||||
{
|
||||
QString m = message.asString(true, true, "\t");
|
||||
this->ui->te_TextMessagesAll->append(m);
|
||||
|
||||
m = message.asString(true, false, "\t");
|
||||
if (message.isSendToUnicom()) this->ui->te_TextMessagesUnicom->append(m);
|
||||
|
||||
// check for own COM frequencies
|
||||
if (message.isRadioMessage())
|
||||
{
|
||||
if (message.isSendToFrequency(this->m_ownAircraft.getCom1System().getFrequencyActive()))
|
||||
this->ui->te_TextMessagesCOM1->append(m);
|
||||
if (message.isSendToFrequency(this->m_ownAircraft.getCom2System().getFrequencyActive()))
|
||||
this->ui->te_TextMessagesCOM2->append(m);
|
||||
}
|
||||
|
||||
// individual channel text messages
|
||||
if (message.isPrivateMessage()) this->addPrivateChannelTextMessage(message, sending);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add new text message tab
|
||||
*/
|
||||
QWidget *MainWindow::addNewTextMessageTab(const QString &tabName)
|
||||
{
|
||||
QWidget *newTab = new QWidget(this->ui->tw_TextMessages);
|
||||
QPushButton *closeButton = new QPushButton("Close", newTab);
|
||||
QVBoxLayout *layout = new QVBoxLayout(newTab);
|
||||
QTextEdit *textEdit = new QTextEdit(newTab);
|
||||
textEdit->setReadOnly(true);
|
||||
textEdit->setWordWrapMode(QTextOption::NoWrap);
|
||||
layout->addWidget(textEdit);
|
||||
layout->addWidget(closeButton);
|
||||
newTab->setLayout(layout);
|
||||
int index = this->ui->tw_TextMessages->addTab(newTab, tabName);
|
||||
this->connect(closeButton, SIGNAL(released()), this, SLOT(closeTextMessageTab()));
|
||||
this->ui->tw_TextMessages->setCurrentIndex(index);
|
||||
return newTab;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a private channel text message
|
||||
*/
|
||||
void MainWindow::addPrivateChannelTextMessage(const CTextMessage &textMessage, bool sending)
|
||||
{
|
||||
if (!textMessage.isPrivateMessage()) return;
|
||||
CCallsign cs = sending ? textMessage.getToCallsign() : textMessage.getFromCallsign();
|
||||
if (cs.isEmpty()) return;
|
||||
QWidget *tab = this->findTextMessageTabByName(cs.getStringAsSet());
|
||||
if (tab == nullptr) tab = this->findTextMessageTabByName(cs.asString());
|
||||
if (tab == nullptr) tab = this->addNewTextMessageTab(cs.getStringAsSet());
|
||||
Q_ASSERT(tab != nullptr);
|
||||
QTextEdit *textEdit = tab->findChild<QTextEdit *>();
|
||||
Q_ASSERT(textEdit != nullptr);
|
||||
if (textEdit == nullptr) return; // do not crash, though this situation could not happen
|
||||
textEdit->append(textMessage.asString(true, false, "\t"));
|
||||
}
|
||||
|
||||
/*
|
||||
* Message tab by name
|
||||
*/
|
||||
QWidget *MainWindow::findTextMessageTabByName(const QString &name)
|
||||
{
|
||||
if (name.isEmpty()) return nullptr;
|
||||
QString n = name.trimmed();
|
||||
for (int index = 0; index < this->ui->tw_TextMessages->count(); index++)
|
||||
{
|
||||
QString tabName = this->ui->tw_TextMessages->tabText(index);
|
||||
if (tabName.indexOf(n, 0, Qt::CaseInsensitive) < 0) continue;
|
||||
QWidget *tab = this->ui->tw_TextMessages->widget(index);
|
||||
return tab;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Selected tab text
|
||||
*/
|
||||
CTextMessage MainWindow::getTextMessageStubForChannel()
|
||||
{
|
||||
CTextMessage tm;
|
||||
int index = this->ui->tw_TextMessages->currentIndex();
|
||||
if (index < 0) return tm;
|
||||
if (index == this->ui->tw_TextMessages->indexOf(this->ui->tb_TextMessagesAll)) return tm;
|
||||
|
||||
// from
|
||||
tm.setFromCallsign(this->m_ownAircraft.getCallsign());
|
||||
|
||||
if (index == this->ui->tw_TextMessages->indexOf(this->ui->tb_TextMessagesCOM1) ||
|
||||
index == this->ui->tw_TextMessages->indexOf(this->ui->tb_TextMessagesCOM2) ||
|
||||
index == this->ui->tw_TextMessages->indexOf(this->ui->tb_TextMessagesUnicom))
|
||||
{
|
||||
// frequency text message
|
||||
if (index == this->ui->tw_TextMessages->indexOf(this->ui->tb_TextMessagesCOM1))
|
||||
{
|
||||
tm.setFrequency(this->m_ownAircraft.getCom1System().getFrequencyActive());
|
||||
}
|
||||
else if (index == this->ui->tw_TextMessages->indexOf(this->ui->tb_TextMessagesCOM2))
|
||||
{
|
||||
tm.setFrequency(this->m_ownAircraft.getCom2System().getFrequencyActive());
|
||||
}
|
||||
else if (index == this->ui->tw_TextMessages->indexOf(this->ui->tb_TextMessagesUnicom))
|
||||
{
|
||||
tm.setFrequency(CPhysicalQuantitiesConstants::FrequencyUnicom());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QString selectedTabText = this->ui->tw_TextMessages->tabText(index);
|
||||
bool isNumber;
|
||||
double frequency = selectedTabText.toDouble(&isNumber);
|
||||
if (isNumber)
|
||||
{
|
||||
CFrequency radioFrequency = CFrequency(frequency, CFrequencyUnit::MHz());
|
||||
if (CComSystem::isValidCivilAviationFrequency(radioFrequency))
|
||||
{
|
||||
tm.setFrequency(radioFrequency);
|
||||
}
|
||||
else
|
||||
{
|
||||
CCallsign toCallsign(selectedTabText);
|
||||
tm.setToCallsign(toCallsign);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CCallsign toCallsign(selectedTabText);
|
||||
tm.setToCallsign(toCallsign);
|
||||
}
|
||||
}
|
||||
return tm; // now valid message stub with receiver
|
||||
}
|
||||
|
||||
/*
|
||||
* Close message tab
|
||||
*/
|
||||
void MainWindow::closeTextMessageTab()
|
||||
{
|
||||
QObject *sender = QObject::sender();
|
||||
QWidget *parentWidget = qobject_cast<QWidget *>(sender->parent());
|
||||
int index = -1;
|
||||
|
||||
while (index < 0 && parentWidget)
|
||||
{
|
||||
index = this->ui->tw_TextMessages->indexOf(parentWidget);
|
||||
parentWidget = parentWidget->parentWidget();
|
||||
}
|
||||
if (index >= 0) this->ui->tw_TextMessages->removeTab(index);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Command entered
|
||||
*/
|
||||
void MainWindow::commandEntered()
|
||||
{
|
||||
// TODO: just a first draft of the command line parser
|
||||
// needs to be refactored, as soon as a first version works
|
||||
|
||||
QString cmdLine = this->ui->le_TextMessagesInput->text().simplified();
|
||||
if (cmdLine.isEmpty()) return;
|
||||
QList<QString> parts = cmdLine.toLower().split(' ');
|
||||
if (parts.length() < 1) return;
|
||||
QString cmd = parts[0].startsWith('.') ? parts[0].toLower() : "";
|
||||
if (cmd == ".m" || cmd == ".msg")
|
||||
{
|
||||
if (!this->m_contextNetwork->isConnected())
|
||||
{
|
||||
this->displayStatusMessage(CStatusMessage(CStatusMessage::TypeTrafficNetwork, CStatusMessage::SeverityError, "network needs to be connected"));
|
||||
return;
|
||||
}
|
||||
if (parts.length() < 3)
|
||||
{
|
||||
this->displayStatusMessage(CStatusMessage(CStatusMessage::TypeValidation, CStatusMessage::SeverityError, "incorrect message"));
|
||||
return;
|
||||
}
|
||||
QString p = parts[1].trimmed();
|
||||
|
||||
// select current tab by command
|
||||
if (p == "c1" || p == "com1")
|
||||
{
|
||||
this->ui->tw_TextMessages->setCurrentWidget(this->ui->tb_TextMessagesCOM1);
|
||||
}
|
||||
else if (p == "c2" || p == "com2")
|
||||
{
|
||||
this->ui->tw_TextMessages->setCurrentWidget(this->ui->tb_TextMessagesCOM2);
|
||||
}
|
||||
else if (p == "u" || p == "unicom" || p == "uni")
|
||||
{
|
||||
this->ui->tw_TextMessages->setCurrentWidget(this->ui->tb_TextMessagesUnicom);
|
||||
}
|
||||
else
|
||||
{
|
||||
QWidget *tab = this->findTextMessageTabByName(p.trimmed());
|
||||
if (tab == nullptr) tab = this->addNewTextMessageTab(p.trimmed().toUpper());
|
||||
this->ui->tw_TextMessages->setCurrentWidget(tab);
|
||||
}
|
||||
CTextMessage tm = this->getTextMessageStubForChannel();
|
||||
int index = cmdLine.indexOf(tm.getToCallsign().asString(), 0, Qt::CaseInsensitive);
|
||||
if (index < 0)
|
||||
{
|
||||
this->displayStatusMessage(
|
||||
CStatusMessage(CStatusMessage::TypeValidation, CStatusMessage::SeverityError,
|
||||
"incomplete message")
|
||||
);
|
||||
return;
|
||||
}
|
||||
QString msg(cmdLine.mid(index + tm.getToCallsign().asString().length() + 1));
|
||||
tm.setMessage(msg);
|
||||
if (tm.isEmpty()) return;
|
||||
if (!this->isContextNetworkAvailableCheck()) return;
|
||||
CTextMessageList tml(tm);
|
||||
this->m_contextNetwork->sendTextMessages(tml);
|
||||
this->textMessageReceived(tml, true);
|
||||
this->ui->le_TextMessagesInput->setText("");
|
||||
}
|
||||
else if (cmd.startsWith("."))
|
||||
{
|
||||
// dump CMDs
|
||||
}
|
||||
else
|
||||
{
|
||||
// single line, no command
|
||||
// just send
|
||||
if (!this->m_contextNetwork->isConnected())
|
||||
{
|
||||
this->displayStatusMessage(CStatusMessage(CStatusMessage::TypeTrafficNetwork, CStatusMessage::SeverityError, "network needs to be connected"));
|
||||
return;
|
||||
}
|
||||
|
||||
int index = this->ui->tw_TextMessages->currentIndex();
|
||||
if (index < 0 || index == this->ui->tw_TextMessages->indexOf(this->ui->tb_TextMessagesAll))
|
||||
{
|
||||
this->displayStatusMessage(CStatusMessage(CStatusMessage::TypeValidation, CStatusMessage::SeverityError, "incorrect channel"));
|
||||
}
|
||||
else
|
||||
{
|
||||
CTextMessage tm = this->getTextMessageStubForChannel();
|
||||
tm.setMessage(cmdLine);
|
||||
if (tm.isEmpty()) return;
|
||||
if (!this->isContextNetworkAvailableCheck()) return;
|
||||
CTextMessageList tml(tm);
|
||||
this->m_contextNetwork->sendTextMessages(tml);
|
||||
this->textMessageReceived(tml, true);
|
||||
this->ui->le_TextMessagesInput->setText("");
|
||||
}
|
||||
}
|
||||
}
|
||||
26
samples/blackgui/sample_blackgui.pro
Normal file
26
samples/blackgui/sample_blackgui.pro
Normal file
@@ -0,0 +1,26 @@
|
||||
include (../../externals.pri)
|
||||
|
||||
QT += core dbus gui network xml
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
|
||||
TARGET = sample_blackgui
|
||||
TEMPLATE = app
|
||||
|
||||
SOURCES += *.cpp
|
||||
HEADERS += *.h
|
||||
FORMS += *.ui
|
||||
CONFIG += c++11
|
||||
|
||||
DEPENDPATH += . ../../src/blackmisc ../../src/blackcore ../../src/blackgui
|
||||
INCLUDEPATH += . ../../src
|
||||
|
||||
LIBS += -L../../lib -lblackcore -lblackmisc -lblackgui
|
||||
LIBS += -lvatlib
|
||||
|
||||
win32:!win32-g++*: PRE_TARGETDEPS += ../../lib/blackmisc.lib \
|
||||
../../lib/blackcore.lib \
|
||||
../../lib/blackgui.lib
|
||||
|
||||
else: PRE_TARGETDEPS += ../../lib/libblackmisc.a \
|
||||
../../lib/libblackcore.a \
|
||||
../../lib/libblackgui.a
|
||||
Reference in New Issue
Block a user