From ab17dabd5b45f901d7f4c4091a1c4573a10c5898 Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Thu, 2 Jan 2014 02:22:13 +0000 Subject: [PATCH] samples and tests for all kbatclist branch changes refs #81 --- client.pro | 7 +- samples/blackcore/main.cpp | 28 + .../readme.txt | 5 +- samples/blackcore/sample_blackcore.pro | 27 + samples/blackcore/tool.cpp | 90 + samples/blackcore/tool.h | 51 + samples/blackgui/main.cpp | 54 + samples/blackgui/mainwindow.cpp | 397 ++++ samples/blackgui/mainwindow.h | 294 +++ samples/blackgui/mainwindow.ui | 1736 +++++++++++++++++ samples/blackgui/mainwindow_cockpit.cpp | 131 ++ samples/blackgui/mainwindow_init.cpp | 161 ++ samples/blackgui/mainwindow_settings.cpp | 114 ++ samples/blackgui/mainwindow_textmessages.cpp | 269 +++ samples/blackgui/sample_blackgui.pro | 26 + samples/blackmisc/main.cpp | 27 + .../sample_blackmisc.pro} | 2 +- samples/blackmisc/sampleschangeobject.cpp | 79 + samples/blackmisc/sampleschangeobject.h | 24 + samples/blackmisc/samplescontainer.cpp | 63 + samples/blackmisc/samplescontainer.h | 24 + samples/blackmisc/samplesmetadata.cpp | 30 + samples/blackmisc/samplesmetadata.h | 24 + .../BlackMiscTest.Datacontext.xml | 36 + .../BlackMiscTest.Testservice.xml | 114 ++ samples/blackmiscdbus/datacontext.cpp | 39 + samples/blackmiscdbus/datacontext.h | 193 ++ samples/blackmiscdbus/dummysignalslot.cpp | 20 + samples/blackmiscdbus/dummysignalslot.h | 43 + samples/blackmiscdbus/main.cpp | 116 ++ samples/blackmiscdbus/readme.txt | 13 + .../blackmiscdbus/sample_blackmisc_dbus.pro | 30 + samples/blackmiscdbus/servicetool.cpp | 689 +++++++ samples/blackmiscdbus/servicetool.h | 120 ++ samples/blackmiscdbus/testservice.cpp | 253 +++ samples/blackmiscdbus/testservice.h | 230 +++ .../sample_quantities_aviation.pro | 22 + .../blackmiscquantities/samplesaviation.cpp | 35 + .../BlackMiscTest.Testservice.xml | 53 - samples/blackmiscquantities_dbus/main.cpp | 176 -- .../sample_quantities_avionics_dbus.pro | 29 - .../blackmiscquantities_dbus/testservice.cpp | 124 -- .../blackmiscquantities_dbus/testservice.h | 137 -- .../testservicetool.cpp | 32 - .../testservicetool.h | 55 - samples/blackmiscvectorgeo/samplesgeo.cpp | 7 + tests/blackcore/test_blackcore.pro | 2 +- tests/blackcore/testblackcoremain.cpp | 5 - tests/blackcore/testblackcoremain.h | 1 + tests/blackcore/testnetwork.cpp | 23 +- tests/blackmisc/testaviation.cpp | 67 + tests/blackmisc/testaviation.h | 17 +- tests/blackmisc/testblackmiscmain.cpp | 7 + tests/blackmisc/testblackmiscmain.h | 4 - tests/blackmisc/testphysicalquantities.cpp | 367 ++-- tests/blackmisc/testvariantandmap.cpp | 78 + tests/blackmisc/testvariantandmap.h | 44 + tests/blackmisc/testvectormatrix.cpp | 120 +- 58 files changed, 6084 insertions(+), 880 deletions(-) create mode 100644 samples/blackcore/main.cpp rename samples/{blackmiscquantities_dbus => blackcore}/readme.txt (65%) create mode 100644 samples/blackcore/sample_blackcore.pro create mode 100644 samples/blackcore/tool.cpp create mode 100644 samples/blackcore/tool.h create mode 100644 samples/blackgui/main.cpp create mode 100644 samples/blackgui/mainwindow.cpp create mode 100644 samples/blackgui/mainwindow.h create mode 100644 samples/blackgui/mainwindow.ui create mode 100644 samples/blackgui/mainwindow_cockpit.cpp create mode 100644 samples/blackgui/mainwindow_init.cpp create mode 100644 samples/blackgui/mainwindow_settings.cpp create mode 100644 samples/blackgui/mainwindow_textmessages.cpp create mode 100644 samples/blackgui/sample_blackgui.pro create mode 100644 samples/blackmisc/main.cpp rename samples/{blackmiscquantities/sample_quantities_avionics.pro => blackmisc/sample_blackmisc.pro} (91%) create mode 100644 samples/blackmisc/sampleschangeobject.cpp create mode 100644 samples/blackmisc/sampleschangeobject.h create mode 100644 samples/blackmisc/samplescontainer.cpp create mode 100644 samples/blackmisc/samplescontainer.h create mode 100644 samples/blackmisc/samplesmetadata.cpp create mode 100644 samples/blackmisc/samplesmetadata.h create mode 100644 samples/blackmiscdbus/BlackMiscTest.Datacontext.xml create mode 100644 samples/blackmiscdbus/BlackMiscTest.Testservice.xml create mode 100644 samples/blackmiscdbus/datacontext.cpp create mode 100644 samples/blackmiscdbus/datacontext.h create mode 100644 samples/blackmiscdbus/dummysignalslot.cpp create mode 100644 samples/blackmiscdbus/dummysignalslot.h create mode 100644 samples/blackmiscdbus/main.cpp create mode 100644 samples/blackmiscdbus/readme.txt create mode 100644 samples/blackmiscdbus/sample_blackmisc_dbus.pro create mode 100644 samples/blackmiscdbus/servicetool.cpp create mode 100644 samples/blackmiscdbus/servicetool.h create mode 100644 samples/blackmiscdbus/testservice.cpp create mode 100644 samples/blackmiscdbus/testservice.h create mode 100644 samples/blackmiscquantities/sample_quantities_aviation.pro delete mode 100644 samples/blackmiscquantities_dbus/BlackMiscTest.Testservice.xml delete mode 100644 samples/blackmiscquantities_dbus/main.cpp delete mode 100644 samples/blackmiscquantities_dbus/sample_quantities_avionics_dbus.pro delete mode 100644 samples/blackmiscquantities_dbus/testservice.cpp delete mode 100644 samples/blackmiscquantities_dbus/testservice.h delete mode 100644 samples/blackmiscquantities_dbus/testservicetool.cpp delete mode 100644 samples/blackmiscquantities_dbus/testservicetool.h create mode 100644 tests/blackmisc/testvariantandmap.cpp create mode 100644 tests/blackmisc/testvariantandmap.h diff --git a/client.pro b/client.pro index 1c72388c1..829a9ad3f 100644 --- a/client.pro +++ b/client.pro @@ -47,8 +47,11 @@ equals(WITH_SAMPLES, ON) { SUBDIRS += samples/plugin/sample_plugin.pro SUBDIRS += samples/pluginmgr/sample_pluginmgr.pro SUBDIRS += samples/blackmiscvectorgeo/sample_vector_geo.pro - SUBDIRS += samples/blackmiscquantities/sample_quantities_avionics.pro - SUBDIRS += samples/blackmiscquantities_dbus/sample_quantities_avionics_dbus.pro + SUBDIRS += samples/blackmiscquantities/sample_quantities_aviation.pro + SUBDIRS += samples/blackmiscdbus/sample_blackmisc_dbus.pro + SUBDIRS += samples/blackgui/sample_blackgui.pro + SUBDIRS += samples/blackcore/sample_blackcore.pro + SUBDIRS += samples/blackmisc/sample_blackmisc.pro } equals(WITH_UNITTESTS, ON) { diff --git a/samples/blackcore/main.cpp b/samples/blackcore/main.cpp new file mode 100644 index 000000000..b1a14f68b --- /dev/null +++ b/samples/blackcore/main.cpp @@ -0,0 +1,28 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "blackcore/coreruntime.h" +#include "blackmisc/blackmiscfreefunctions.h" +#include "tool.h" +#include + + +/*! + * DBus tests, tests marshalling / unmarshalling of many value classes. + * Forks two processes and sends data via DBus among them. + */ +int main(int argc, char *argv[]) +{ + // metadata are registered in runtime + QCoreApplication a(argc, argv); + BlackCore::CCoreRuntime *core = new BlackCore::CCoreRuntime(true, &a); + + QtConcurrent::run(BlackMiscTest::Tool::serverLoop, core); // QFuture future + qDebug() << "Server event loop, pid:" << BlackMiscTest::Tool::getPid(); + + // loop + return a.exec(); + +} diff --git a/samples/blackmiscquantities_dbus/readme.txt b/samples/blackcore/readme.txt similarity index 65% rename from samples/blackmiscquantities_dbus/readme.txt rename to samples/blackcore/readme.txt index 6c74d5ca4..c2254ea4e 100644 --- a/samples/blackmiscquantities_dbus/readme.txt +++ b/samples/blackcore/readme.txt @@ -2,9 +2,12 @@ Starting: dbus-daemon.exe --session - blocks CMD (sometimes daemon continues to run when pressing CTRL/C) - does not start without directory session.d, i.e. ..\Qt\Qt5.1.0DBus\qtbase\etc\dbus-1\session.d +!!! The includes are set in the qmake file, there are the header files +!!! which are used in the interface qdbuscpp2xml testservice.h -x blackmisc_cpp2xml.dll -o BlackMiscTest.Testservice.xml +qdbuscpp2xml datacontext.h -x blackmisc_cpp2xml.dll -o BlackMiscTest.Datacontext.xml Set search path for plugins: env.var. QT_PLUGIN_PATH -Done automatically, but if required manually +Done automatically (qmake), but if required manually Interface: qdbusxml2cpp blackbus.testservice.xml -p itestservice Adaptor: qdbusxml2cpp blackbus.testservice.xml -a atestservice diff --git a/samples/blackcore/sample_blackcore.pro b/samples/blackcore/sample_blackcore.pro new file mode 100644 index 000000000..7168d02fa --- /dev/null +++ b/samples/blackcore/sample_blackcore.pro @@ -0,0 +1,27 @@ +include (../../externals.pri) + +QT += core dbus network xml + +TARGET = sample_blackcore +TEMPLATE = app + +CONFIG += console c++11 +CONFIG -= app_bundle + +DEPENDPATH += . ../../src/blackmisc ../../src/blackcore +INCLUDEPATH += . ../../src + +LIBS += -L../../lib -lblackcore -lblackmisc +LIBS += -lvatlib + +win32:!win32-g++*: PRE_TARGETDEPS += ../../lib/blackmisc.lib \ + ../../lib/blackcore.lib +else: PRE_TARGETDEPS += ../../lib/libblackmisc.a \ + ../../lib/libblackcore.a + +DESTDIR = ../../bin + +HEADERS += *.h +SOURCES += *.cpp + +OTHER_FILES += readme.txt diff --git a/samples/blackcore/tool.cpp b/samples/blackcore/tool.cpp new file mode 100644 index 000000000..3fc610c0f --- /dev/null +++ b/samples/blackcore/tool.cpp @@ -0,0 +1,90 @@ +#include "tool.h" +#include "blackcore/coreruntime.h" +#include "blackmisc/valuemap.h" +#include +#include +#include +#include + +using namespace BlackCore; +using namespace BlackMisc::PhysicalQuantities; +using namespace BlackMisc::Aviation; + +namespace BlackMiscTest +{ + + /* + * Start a new process + */ + QProcess *Tool::startNewProcess(const QString &executable, const QStringList &arguments, QObject *parent) + { + QProcess *process = new QProcess(parent); + process->startDetached(executable, arguments); + return process; + } + + /* + * Send data to testservice, this sends data to the slots on the server + */ + void Tool::serverLoop(const BlackCore::CCoreRuntime *core) + { + QThread::sleep(3); // let the client connect + qDebug() << "Running on server here" << Tool::getPid(); + + // + // Server loop + // + QTextStream qtin(stdin); + QString line; + while (line != "x") + { + const BlackCore::IContextNetwork *networkContext = core->getIContextNetwork(); + + // display current status + qDebug() << "-------------"; + qDebug() << "ATC booked"; + qDebug() << networkContext->getAtcStationsBooked().toQString(); + qDebug() << "-------------"; + qDebug() << "ATC online"; + qDebug() << networkContext->getAtcStationsOnline().toQString(); + + // next round? Server + qDebug() << "-------------"; + qDebug() << "Connected with network: " << networkContext->isConnected(); + + qDebug() << "-------------"; + qDebug() << "Key x to exit"; + qDebug() << "1 .. ATC booked"; + qDebug() << "2 .. ATC online"; + qDebug() << "3 .. Aircrafts in range"; + qDebug() << "4 .. my aircraft"; + + line = qtin.readLine(); + + if (line.startsWith("1")) + { + qDebug() << "-------------"; + qDebug() << "ATC booked"; + qDebug() << networkContext->getAtcStationsBooked().toFormattedQString(); + } + else if (line.startsWith("2")) + { + qDebug() << "-------------"; + qDebug() << "ATC online"; + qDebug() << networkContext->getAtcStationsOnline().toFormattedQString(); + } + else if (line.startsWith("3")) + { + qDebug() << "-------------"; + qDebug() << "aircrafts in range"; + qDebug() << networkContext->getAircraftsInRange().toFormattedQString(); + } + else if (line.startsWith("4")) + { + qDebug() << "-------------"; + qDebug() << "my aircraft"; + qDebug() << networkContext->getOwnAircraft(); + } + } + } +} // namespace diff --git a/samples/blackcore/tool.h b/samples/blackcore/tool.h new file mode 100644 index 000000000..bad475696 --- /dev/null +++ b/samples/blackcore/tool.h @@ -0,0 +1,51 @@ +#ifndef BLACKMISCTEST_Tool_H +#define BLACKMISCTEST_Tool_H + +#include "blackcore/coreruntime.h" +#include +#include +#include + +namespace BlackMiscTest +{ + + /*! + * \brief Supporting functions for running the tests + */ + class Tool + { + private: + /*! + * \brief Constructor + */ + Tool() {} + + public: + /*! + * \brief Get process id + * \return + */ + static qint64 getPid() + { + return QCoreApplication::applicationPid(); + } + + /*! + * \brief Start a new process + * \param executable + * \param arguments + * \param parent + * \return + */ + static QProcess *startNewProcess(const QString &executable, const QStringList &arguments = QStringList(), QObject *parent = 0); + + /*! + * \brief Server loop + * \param core + */ + static void serverLoop(const BlackCore::CCoreRuntime *core); + }; + +} // namespace + +#endif // guard diff --git a/samples/blackgui/main.cpp b/samples/blackgui/main.cpp new file mode 100644 index 000000000..d0ba96589 --- /dev/null +++ b/samples/blackgui/main.cpp @@ -0,0 +1,54 @@ +#include "mainwindow.h" +#include "blackmisc/blackmiscfreefunctions.h" +#include +#include +#include + +/*! + * \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(); +} diff --git a/samples/blackgui/mainwindow.cpp b/samples/blackgui/mainwindow.cpp new file mode 100644 index 000000000..8945cc7cb --- /dev/null +++ b/samples/blackgui/mainwindow.cpp @@ -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(from); + CContextNetwork::ConnectionStatus statusTo = static_cast(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"); + } +} diff --git a/samples/blackgui/mainwindow.h b/samples/blackgui/mainwindow.h new file mode 100644 index 000000000..f2d99c202 --- /dev/null +++ b/samples/blackgui/mainwindow.h @@ -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 +#include +#include +#include + +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 diff --git a/samples/blackgui/mainwindow.ui b/samples/blackgui/mainwindow.ui new file mode 100644 index 000000000..1d5f7a040 --- /dev/null +++ b/samples/blackgui/mainwindow.ui @@ -0,0 +1,1736 @@ + + + MainWindow + + + + 0 + 0 + 600 + 541 + + + + + 0 + 0 + + + + Black GUI + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + + + 0 + + + 0 + + + + + 10 + + + QLayout::SetMinimumSize + + + 0 + + + 5 + + + + + + 0 + 0 + + + + + 60 + 23 + + + + Connect + + + + + + + + 60 + 16777215 + + + + Status + + + + + + + + 60 + 16777215 + + + + ATC + + + + + + + + 60 + 16777215 + + + + Aircrafts + + + + + + + + 60 + 16777215 + + + + Mappings + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + 0 + + + + + + 0 + 0 + + + + 3 + + + + + + + + + Network connected + + + + + + + true + + + + + + + Network context + + + + + + + true + + + + + + + + + QPlainTextEdit::NoWrap + + + true + + + + + + + + + 0 + 0 + + + + + 2 + + + 0 + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + 0 + + + + In range + + + + 2 + + + 2 + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + true + + + false + + + + + + + + 0 + 0 + + + + + 16777215 + 110 + + + + Info (ATIS, METAR, ...) + + + + 0 + + + 0 + + + 0 + + + 0 + + + 2 + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 100 + + + + + + + + + 0 + 0 + + + + + 16777215 + 25 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 2 + + + QLayout::SetDefaultConstraint + + + 2 + + + 0 + + + 2 + + + 0 + + + + + + 80 + 20 + + + + + 16777215 + 20 + + + + 5 + + + 30 + + + 5 + + + 10 + + + Qt::Horizontal + + + QSlider::TicksAbove + + + 5 + + + + + + + + 60 + 16777215 + + + + + + + 5 + + + + + + + Load METAR + + + + + + + + 20 + 20 + + + + Reload ATIS + + + + + + + + + + + Bookings + + + + 0 + + + QLayout::SetMaximumSize + + + 0 + + + + + true + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + true + + + false + + + + + + + + + Reload + + + + + + + + + + + + + + + + + false + + + + + + + + 0 + 0 + + + + + 16777215 + 25 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 2 + + + QLayout::SetDefaultConstraint + + + 2 + + + 0 + + + 2 + + + 0 + + + + + + 80 + 20 + + + + + 16777215 + 20 + + + + 5 + + + 30 + + + 5 + + + 10 + + + Qt::Horizontal + + + QSlider::TicksAbove + + + 5 + + + + + + + + + + + + + + 3 + + + + + false + + + 3 + + + 118.000000000000000 + + + 136.000000000000000 + + + 0.250000000000000 + + + 118.250000000000000 + + + + + + + 0 + + + 7777.000000000000000 + + + 7000.000000000000000 + + + + + + + + 75 + 16777215 + + + + 3 + + + 118.000000000000000 + + + 136.000000000000000 + + + 0.250000000000000 + + + 118.000000000000000 + + + + + + + + 12 + + + + COM 2 + + + + + + + + 12 + + + + Transponder + + + + + + + + 12 + + + + COM 1 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 50 + 16777215 + + + + + S + + + + + C + + + + + I + + + + + + + + + 75 + 0 + + + + + 16777215 + 16777215 + + + + 3 + + + 118.000000000000000 + + + 136.000000000000000 + + + 0.250000000000000 + + + 119.000000000000000 + + + + + + + 3 + + + 118.000000000000000 + + + 136.000000000000000 + + + 0.250000000000000 + + + 119.250000000000000 + + + + + + + + + + + + + 0 + + + + All + + + + + + QTextEdit::NoWrap + + + true + + + 10 + + + + + + + + UNICOM + + + + + + QTextEdit::NoWrap + + + true + + + 10 + + + + + + + + COM 1 + + + + + + QTextEdit::NoWrap + + + true + + + 10 + + + + + + + + COM 2 + + + + + + QTextEdit::NoWrap + + + true + + + 10 + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + + + + + + + + + + + 0 + + + 0 + + + + + + + 0 + + + 0 + + + + + 0 + + + + Traffic Network + + + + 2 + + + 1 + + + + + QAbstractItemView::AnyKeyPressed|QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + false + + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + 6 + + + + + Name + + + + + + + + + + + + + + Description + + + + + + + + + + Address + + + + + + + + + + Port + + + + + + + 5 + + + + + + + Real name + + + + + + + + + + + + + + Id: + + + + + + + + + + + + + + Password + + + + + + + + + + 32 + + + QLineEdit::Password + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Save + + + + + + + Remove + + + + + + + Current server + + + + + + + + + + + Whatsoever + + + + + + + + Callsign + + + + + + + BLACK + + + + + + + + + + + + + + + + + + + 10 + + + QLayout::SetFixedSize + + + 5 + + + + + + 0 + 0 + + + + + 60 + 16777215 + + + + Qt::LeftToRight + + + Settings + + + + + + + + 60 + 16777215 + + + + Cockpit + + + + + + + + 60 + 16777215 + + + + Weather + + + + + + + + 60 + 16777215 + + + + Text/Chat + + + + + + + + 60 + 16777215 + + + + Flightplan + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + 0 + 0 + 600 + 21 + + + + + Test + + + + Set plane positions + + + + + + + + Reload + + + + + + + + + + + TopToolBarArea + + + false + + + + + + Position EDDF + + + + + Position EDDM + + + + + Position EDRY + + + + + Reload settings + + + + + + + + pb_MainAtc + released() + MainWindow + setMainPage() + + + 47 + 132 + + + 4 + 278 + + + + + pb_MainSettings + released() + MainWindow + setMainPage() + + + 569 + 50 + + + 599 + 251 + + + + + pb_MainConnect + released() + MainWindow + setMainPage() + + + 70 + 66 + + + 4 + 209 + + + + + pb_MainFlightplan + released() + MainWindow + setMainPage() + + + 588 + 198 + + + 299 + 199 + + + + + pb_MainCockpit + released() + MainWindow + setMainPage() + + + 580 + 99 + + + 299 + 199 + + + + + pb_MainConnect + released() + MainWindow + toggleNetworkConnection() + + + 22 + 50 + + + 0 + 37 + + + + + menu_TestLocationsEDRY + triggered() + MainWindow + menuClicked() + + + -1 + -1 + + + 299 + 199 + + + + + menu_ReloadSettings + triggered() + MainWindow + menuClicked() + + + -1 + -1 + + + 299 + 238 + + + + + pb_MainAircrafts + released() + MainWindow + setMainPage() + + + 16 + 158 + + + 0 + 137 + + + + + tv_SettingsTnServers + clicked(QModelIndex) + MainWindow + networkServerSelected(QModelIndex) + + + 175 + 52 + + + 265 + 36 + + + + + pb_SettingsTnSaveServer + released() + MainWindow + alterTrafficServer() + + + 109 + 74 + + + -4 + 459 + + + + + pb_SettingsTnRemoveServer + released() + MainWindow + alterTrafficServer() + + + 137 + 74 + + + -10 + 491 + + + + + pb_SettingsTnCurrentServer + released() + MainWindow + alterTrafficServer() + + + 165 + 74 + + + -17 + 436 + + + + + pb_ReloadAtcStationsBooked + released() + MainWindow + reloadAtcStationsBooked() + + + 178 + 110 + + + 2 + 509 + + + + + tv_AtcStationsOnline + clicked(QModelIndex) + MainWindow + onlineAtcStationSelected(QModelIndex) + + + 253 + 116 + + + -1 + 392 + + + + + pb_MainStatus + released() + MainWindow + setMainPage() + + + 19 + 98 + + + -8 + 101 + + + + + pb_MainTextMessages + released() + MainWindow + setMainPage() + + + 588 + 165 + + + -8 + 169 + + + + + pb_MainWeather + released() + MainWindow + setMainPage() + + + 588 + 132 + + + -26 + 118 + + + + + le_TextMessagesInput + returnPressed() + MainWindow + commandEntered() + + + 176 + 73 + + + 4 + 569 + + + + + pushButton + released() + MainWindow + getMetar() + + + 374 + 491 + + + 20 + 431 + + + + + le_AtcStationsOnlineMetar + returnPressed() + MainWindow + getMetar() + + + 338 + 491 + + + 341 + 515 + + + + + ds_CockpitCom1Active + editingFinished() + MainWindow + cockpitValuesChanged() + + + 370 + 55 + + + 337 + -8 + + + + + ds_CockpitCom1Standby + editingFinished() + MainWindow + cockpitValuesChanged() + + + 463 + 64 + + + 412 + -8 + + + + + ds_CockpitCom2Active + editingFinished() + MainWindow + cockpitValuesChanged() + + + 379 + 88 + + + 253 + -17 + + + + + ds_CockpitCom2Standby + editingFinished() + MainWindow + cockpitValuesChanged() + + + 478 + 85 + + + 481 + -17 + + + + + cb_CockpitTransponderMode + currentIndexChanged(QString) + MainWindow + cockpitValuesChanged() + + + 454 + 109 + + + 436 + -2 + + + + + ds_CockpitTransponder + editingFinished() + MainWindow + cockpitValuesChanged() + + + 385 + 103 + + + 1 + 127 + + + + + + setMainPage() + toggleNetworkConnection() + menuClicked() + networkServerSelected(QModelIndex) + alterTrafficServer() + reloadAtcStationsBooked() + onlineAtcStationSelected(QModelIndex) + commandEntered() + getMetar() + cockpitValuesChanged() + + diff --git a/samples/blackgui/mainwindow_cockpit.cpp b/samples/blackgui/mainwindow_cockpit.cpp new file mode 100644 index 000000000..041e910bd --- /dev/null +++ b/samples/blackgui/mainwindow_cockpit.cpp @@ -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(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(); + } + } +} diff --git a/samples/blackgui/mainwindow_init.cpp b/samples/blackgui/mainwindow_init.cpp new file mode 100644 index 000000000..405be394c --- /dev/null +++ b/samples/blackgui/mainwindow_init.cpp @@ -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 + +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(); + } +} diff --git a/samples/blackgui/mainwindow_settings.cpp b/samples/blackgui/mainwindow_settings.cpp new file mode 100644 index 000000000..eb3d6acfa --- /dev/null +++ b/samples/blackgui/mainwindow_settings.cpp @@ -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; +} diff --git a/samples/blackgui/mainwindow_textmessages.cpp b/samples/blackgui/mainwindow_textmessages.cpp new file mode 100644 index 000000000..35e3825d0 --- /dev/null +++ b/samples/blackgui/mainwindow_textmessages.cpp @@ -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(); + 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(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 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(""); + } + } +} diff --git a/samples/blackgui/sample_blackgui.pro b/samples/blackgui/sample_blackgui.pro new file mode 100644 index 000000000..f6d92e3a5 --- /dev/null +++ b/samples/blackgui/sample_blackgui.pro @@ -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 diff --git a/samples/blackmisc/main.cpp b/samples/blackmisc/main.cpp new file mode 100644 index 000000000..f2d101e72 --- /dev/null +++ b/samples/blackmisc/main.cpp @@ -0,0 +1,27 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include +#include "sampleschangeobject.h" +#include "samplesmetadata.h" +#include "samplescontainer.h" +#include "blackmisc/blackmiscfreefunctions.h" +#include "blackmisc/pqallquantities.h" + +using namespace BlackMisc; +using namespace BlackMiscTest; + +/*! + * Sample tests + */ +int main(int argc, char *argv[]) +{ + BlackMisc::initResources(); + QCoreApplication a(argc, argv); + CSamplesChangeObject::samples(); + CSamplesContainer::samples(); + CSamplesMetadata::samples(); + return a.exec(); +} diff --git a/samples/blackmiscquantities/sample_quantities_avionics.pro b/samples/blackmisc/sample_blackmisc.pro similarity index 91% rename from samples/blackmiscquantities/sample_quantities_avionics.pro rename to samples/blackmisc/sample_blackmisc.pro index 698e25923..1fb359439 100644 --- a/samples/blackmiscquantities/sample_quantities_avionics.pro +++ b/samples/blackmisc/sample_blackmisc.pro @@ -1,6 +1,6 @@ QT += core dbus -TARGET = sample_quantities_avionics +TARGET = sample_blackmisc TEMPLATE = app CONFIG += console c++11 diff --git a/samples/blackmisc/sampleschangeobject.cpp b/samples/blackmisc/sampleschangeobject.cpp new file mode 100644 index 000000000..49c0be8e1 --- /dev/null +++ b/samples/blackmisc/sampleschangeobject.cpp @@ -0,0 +1,79 @@ +/* Copyright (C) 2013 VATSIM Community / contributors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "sampleschangeobject.h" +#include "blackmisc/pqconstants.h" +#include "blackmisc/avheading.h" +#include "blackmisc/aviocomsystem.h" +#include "blackmisc/avionavsystem.h" +#include "blackmisc/aviotransponder.h" +#include "blackmisc/avatcstationlist.h" +#include "blackmisc/valuemap.h" +#include "blackmisc/predicates.h" +#include "blackmisc/blackmiscfreefunctions.h" +#include + +using namespace BlackMisc; +using namespace BlackMisc::Aviation; +using namespace BlackMisc::PhysicalQuantities; +using namespace BlackMisc::Geo; +using namespace BlackMisc::Network; + +namespace BlackMiscTest +{ + + /* + * Samples + */ + int CSamplesChangeObject::samples() + { + // ATC station + QDateTime dtFrom = QDateTime::currentDateTimeUtc(); + QDateTime dtUntil = dtFrom.addSecs(60 * 60.0); // 1 hour + QDateTime dtFrom2 = dtUntil; + QDateTime dtUntil2 = dtUntil.addSecs(60 * 60.0); + CCoordinateGeodetic geoPos = + CCoordinateGeodetic::fromWgs84("48° 21′ 13″ N", "11° 47′ 09″ E", CLength(1487, CLengthUnit::ft())); + CAtcStation station1(CCallsign("eddm_twr"), CUser("123456", "Joe Doe"), + CFrequency(118.7, CFrequencyUnit::MHz()), + geoPos, CLength(50, CLengthUnit::km()), false, dtFrom, dtUntil); + CAtcStation station2(station1); + CAtcStation station3(CCallsign("eddm_app"), CUser("654321", "Jen Doe"), + CFrequency(120.7, CFrequencyUnit::MHz()), + geoPos, CLength(100, CLengthUnit::km()), false, dtFrom2, dtUntil2); + + // ATC List + CAtcStationList atcList; + atcList.push_back(station1); + atcList.push_back(station2); + atcList.push_back(station3); + atcList.push_back(station1); + atcList.push_back(station2); + atcList.push_back(station3); + qDebug() << "-- before update"; + qDebug() << atcList.toQString(); + + // put Jane in the tower + CValueMap newController; + newController.addValue(CAtcStation::IndexController, QVariant::fromValue(CUser("112233", "Jane Doe"))); + atcList.applyIf( + BlackMisc::Predicates::MemberEqual(&CAtcStation::getCallsign, CCallsign("eddm_twr")), + newController); + qDebug() << "-- after update via predicates"; + qDebug() << atcList.toQString(); + + // now Jane's time is over + CValueMap anotherController; + anotherController.addValue(CAtcStation::IndexController, QVariant::fromValue(CUser("445566", "Fuzzy"))); + atcList.applyIf(newController, anotherController); + + qDebug() << "-- after update via value map"; + qDebug() << atcList.toQString(); + + qDebug() << "-----------------------------------------------"; + return 0; + } + +} // namespace diff --git a/samples/blackmisc/sampleschangeobject.h b/samples/blackmisc/sampleschangeobject.h new file mode 100644 index 000000000..93347df35 --- /dev/null +++ b/samples/blackmisc/sampleschangeobject.h @@ -0,0 +1,24 @@ +/* Copyright (C) 2013 VATSIM Community / contributors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef BLACKMISCTEST_SAMPLESCHANGEDATA_H +#define BLACKMISCTEST_SAMPLESCHANGEDATA_H + +namespace BlackMiscTest { + +/*! + * \brief Samples for metadata + */ +class CSamplesChangeObject +{ +public: + /*! + * \brief Run the samples + */ + static int samples(); +}; +} // namespace + +#endif diff --git a/samples/blackmisc/samplescontainer.cpp b/samples/blackmisc/samplescontainer.cpp new file mode 100644 index 000000000..928cad89a --- /dev/null +++ b/samples/blackmisc/samplescontainer.cpp @@ -0,0 +1,63 @@ +/* Copyright (C) 2013 VATSIM Community / contributors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "samplescontainer.h" +#include "blackmisc/blackmiscfreefunctions.h" +#include "blackmisc/avatcstationlist.h" +#include +#include + +using namespace BlackMisc::Aviation; +using namespace BlackMisc::PhysicalQuantities; +using namespace BlackMisc::Geo; +using namespace BlackMisc::Network; + +namespace BlackMiscTest +{ + + /* + * Samples + */ + int CSamplesContainer::samples() + { + // ATC stations + QDateTime dtFrom = QDateTime::currentDateTimeUtc(); + QDateTime dtUntil = dtFrom.addSecs(60 * 60.0); // 1 hour + QDateTime dtFrom2 = dtUntil; + QDateTime dtUntil2 = dtUntil.addSecs(60 * 60.0); + CCoordinateGeodetic geoPos = + CCoordinateGeodetic::fromWgs84("48° 21′ 13″ N", "11° 47′ 09″ E", CLength(1487, CLengthUnit::ft())); + CAtcStation station1(CCallsign("eddm_twr"), CUser("123456", "Joe Doe"), + CFrequency(118.7, CFrequencyUnit::MHz()), + geoPos, CLength(50, CLengthUnit::km()), false, dtFrom, dtUntil); + CAtcStation station2(station1); + CAtcStation station3(CCallsign("eddm_app"), CUser("654321", "Jen Doe"), + CFrequency(120.7, CFrequencyUnit::MHz()), + geoPos, CLength(100, CLengthUnit::km()), false, dtFrom2, dtUntil2); + + // ATC List + CAtcStationList atcList; + atcList.push_back(station1); + atcList.push_back(station2); + atcList.push_back(station3); + atcList.push_back(station1); + atcList.push_back(station2); + atcList.push_back(station3); + qDebug() << "-- list:"; + qDebug() << atcList.toQString(); + + CAtcStationList atcListFind = atcList.findBy(&CAtcStation::getCallsign, "eddm_twr", &CAtcStation::getFrequency, CFrequency(118.7, CFrequencyUnit::MHz())); + qDebug() << "-- find by:"; + qDebug() << atcListFind.toQString(); + + CAtcStationList atcListSort = atcList.sortedBy(&CAtcStation::getBookedFromUtc, &CAtcStation::getCallsign, &CAtcStation::getControllerRealname); + qDebug() << "-- sort by:"; + qDebug() << atcListSort.toQString(); + + qDebug() << "-----------------------------------------------"; + return 0; + } + +} // namespace diff --git a/samples/blackmisc/samplescontainer.h b/samples/blackmisc/samplescontainer.h new file mode 100644 index 000000000..f0ac7099e --- /dev/null +++ b/samples/blackmisc/samplescontainer.h @@ -0,0 +1,24 @@ +/* Copyright (C) 2013 VATSIM Community / contributors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef BLACKMISCTEST_SAMPLESCONTAINER_H +#define BLACKMISCTEST_SAMPLESCONTAINER_H + +namespace BlackMiscTest { + +/*! + * \brief Samples for our containers + */ +class CSamplesContainer +{ +public: + /*! + * \brief Run the samples + */ + static int samples(); +}; +} // namespace + +#endif diff --git a/samples/blackmisc/samplesmetadata.cpp b/samples/blackmisc/samplesmetadata.cpp new file mode 100644 index 000000000..c82dea999 --- /dev/null +++ b/samples/blackmisc/samplesmetadata.cpp @@ -0,0 +1,30 @@ +/* Copyright (C) 2013 VATSIM Community / contributors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "samplesmetadata.h" +#include "blackmisc/blackmiscfreefunctions.h" +#include "blackmisc/avatcstationlist.h" +#include +#include + +using namespace BlackMisc::Aviation; +using namespace BlackMisc::PhysicalQuantities; +using namespace BlackMisc::Geo; +using namespace BlackMisc::Network; + +namespace BlackMiscTest +{ + + /* + * Samples + */ + int CSamplesMetadata::samples() + { + BlackMisc::registerMetadata(); + BlackMisc::displayAllUserMetatypesTypes(); + return 0; + } + +} // namespace diff --git a/samples/blackmisc/samplesmetadata.h b/samples/blackmisc/samplesmetadata.h new file mode 100644 index 000000000..3def8e2ce --- /dev/null +++ b/samples/blackmisc/samplesmetadata.h @@ -0,0 +1,24 @@ +/* Copyright (C) 2013 VATSIM Community / contributors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef BLACKMISCTEST_SAMPLESMETADATA_H +#define BLACKMISCTEST_SAMPLESMETADATA_H + +namespace BlackMiscTest { + +/*! + * \brief Samples for metadata + */ +class CSamplesMetadata +{ +public: + /*! + * \brief Run the samples + */ + static int samples(); +}; +} // namespace + +#endif diff --git a/samples/blackmiscdbus/BlackMiscTest.Datacontext.xml b/samples/blackmiscdbus/BlackMiscTest.Datacontext.xml new file mode 100644 index 000000000..3eeae1bf7 --- /dev/null +++ b/samples/blackmiscdbus/BlackMiscTest.Datacontext.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/blackmiscdbus/BlackMiscTest.Testservice.xml b/samples/blackmiscdbus/BlackMiscTest.Testservice.xml new file mode 100644 index 000000000..3ab70f5c0 --- /dev/null +++ b/samples/blackmiscdbus/BlackMiscTest.Testservice.xml @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/blackmiscdbus/datacontext.cpp b/samples/blackmiscdbus/datacontext.cpp new file mode 100644 index 000000000..255eaa527 --- /dev/null +++ b/samples/blackmiscdbus/datacontext.cpp @@ -0,0 +1,39 @@ +#include "datacontext.h" + +namespace BlackMiscTest +{ + + const QString CDataContext::ServiceName = QString(BLACKMISCKTEST_DATACONTEXT_INTERFACENAME); + const QString CDataContext::ServicePath = QString(BLACKMISCKTEST_DATACONTEXT_SERVICEPATH); + + /* + * Init this context + */ + CDataContext::CDataContext(BlackCore::CDBusServer *server) + { + // 1. Register with the server + server->addObject(CDataContext::ServicePath, this); + + // 2. Next I would wire all signals and slots of this context + // belonging together + } + + /* + * FooSlot + */ + void CDataContext::fooSlot(const QString &baz) + { + qDebug() << "foo slot" << baz; + } + + + /* + * FooSlot + * \return + */ + QString CDataContext::fooSlotRet(const QString &baz) + { + qDebug() << "foo slot" << baz; + return baz; + } +} diff --git a/samples/blackmiscdbus/datacontext.h b/samples/blackmiscdbus/datacontext.h new file mode 100644 index 000000000..4c8f97376 --- /dev/null +++ b/samples/blackmiscdbus/datacontext.h @@ -0,0 +1,193 @@ +#ifndef BLACKMISCTEST_DATACONTEXTCORE_H +#define BLACKMISCTEST_DATACONTEXTCORE_H + +#include "blackcore/dbus_server.h" +#include "blackmisc/avallclasses.h" +#include + +#define BLACKMISCKTEST_DATACONTEXT_INTERFACENAME "blackmisctest.datacontext" +#define BLACKMISCKTEST_DATACONTEXT_SERVICEPATH "/datacontext" + +namespace BlackMiscTest +{ + + /*! + * \brief A poor man's Data context running in the core + */ + class CDataContext : public QObject + { + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", BLACKMISCKTEST_DATACONTEXT_INTERFACENAME) + Q_PROPERTY(BlackMisc::Aviation::CAtcStationList qpAtcOnlineList READ onlineControllers WRITE setOnlineControllers) + Q_PROPERTY(BlackMisc::Aviation::CAtcStationList qpAtcBookedList READ bookedControllers WRITE setBookedControllers) + Q_PROPERTY(QStringList qpFooStrings READ fooStrings) + + // no property for Foo, which is just meant to be local only + + Q_SIGNALS: + void fooSignal(const QString &message); + + public: + static const QString ServiceName; + static const QString ServicePath; + + private: + BlackMisc::Aviation::CAtcStationList m_atcOnline; + BlackMisc::Aviation::CAtcStationList m_atcBooked; + QString m_foo; + QStringList m_fooStrings; + + public slots: + + /*! + * \brief FooSlot + * \param baz + */ + void fooSlot(const QString &baz); // generated interface methods are "const &QString", so this must match + + /*! + * \brief FooSlotRet, with return value + * \param baz + * \return + */ + QString fooSlotRet(const QString &baz); + + /*! + * \brief Update booked controllers + * \param condition + * \param values + */ + void updateBookedControllers(const BlackMisc::CValueMap &condition, const BlackMisc::CValueMap &values) + { + qDebug() << Q_FUNC_INFO; + qDebug() << " condition" << condition; + qDebug() << " values" << values; + m_atcBooked.applyIf(condition, values); + } + + /*! + * \brief Update online controllers + * \param condition + * \param values + */ + void updateOnlineControllers(const BlackMisc::CValueMap &condition, const BlackMisc::CValueMap &values) + { + qDebug() << Q_FUNC_INFO; + qDebug() << " condition" << condition; + qDebug() << " values" << values; + m_atcOnline.applyIf(condition, values); + } + + public: + /*! + * \brief Default constructor + */ + CDataContext(QObject *parent = 0) : QObject(parent) {} + + /*! + * \brief ctor for Qt meta system + * \param other + */ + CDataContext(const CDataContext &other) : + QObject(), m_atcOnline(other.m_atcOnline), m_atcBooked(other.m_atcBooked), m_foo(other.m_foo), m_fooStrings(other.fooStrings()) + { + // void + } + + /*! + * \brief With link to server + * \param server + */ + CDataContext(BlackCore::CDBusServer *server); + + /*! + * \brief The "central" ATC list with online ATC controllers + * \return + */ + BlackMisc::Aviation::CAtcStationList &onlineControllers() + { + qDebug() << Q_FUNC_INFO; + return m_atcOnline; + } + + /*! + * \brief The "central" ATC list with online ATC controllers + * \return + */ + const BlackMisc::Aviation::CAtcStationList &onlineControllers() const + { + return m_atcOnline; + } + + /*! + * \brief Another ATC list, maybe all booked controllers + * \return + */ + const BlackMisc::Aviation::CAtcStationList &bookedControllers() const + { + qDebug() << Q_FUNC_INFO; + return m_atcBooked; + } + + /*! + * \brief Replace value by new values, but keep object itself intact + * \param newValues + */ + void setBookedControllers(const BlackMisc::Aviation::CAtcStationList &newValues) + { + // problem concurrent updates + qDebug() << Q_FUNC_INFO; + this->m_atcBooked = newValues; + } + + /*! + * \brief Replace value by new values, but keep object itself intact + * \param newValues + */ + void setOnlineControllers(const BlackMisc::Aviation::CAtcStationList &newValues) + { + // problem concurrent updates + qDebug() << Q_FUNC_INFO; + this->m_atcOnline = newValues; + } + + /*! + * \brief Some property which would be local only + * \return + */ + const QString &foo() const + { + qDebug() << Q_FUNC_INFO; + return m_foo; + } + + /*! + * \brief Some foo strings + * \return + */ + const QStringList &fooStrings() const + { + qDebug() << Q_FUNC_INFO; + return m_fooStrings; + } + + /*! + * \brief Set n foo strings + * \param number + */ + void setFooStrings(int number) + { + this->m_fooStrings.clear(); + for (int i = 0; i < number; i++) + { + QString foo("I am foo "); + foo.append(QString::number(i)); + this->m_fooStrings.append(foo); + } + } + + }; +} +Q_DECLARE_METATYPE(BlackMiscTest::CDataContext) + +#endif // guard diff --git a/samples/blackmiscdbus/dummysignalslot.cpp b/samples/blackmiscdbus/dummysignalslot.cpp new file mode 100644 index 000000000..f7a39c630 --- /dev/null +++ b/samples/blackmiscdbus/dummysignalslot.cpp @@ -0,0 +1,20 @@ +#include "dummysignalslot.h" + +namespace BlackMiscTest +{ + + /* + * Constructor + */ + CDummySignalSlot::CDummySignalSlot(const QString &name, QObject *parent) : QObject(parent), m_name(name) + {} + + /* + * Dummy slot + */ + void CDummySignalSlot::slotCDummy(const QString &saySomething) + { + qDebug() << Q_FUNC_INFO << "name:" << this->m_name << "received:" << saySomething; + } + +} diff --git a/samples/blackmiscdbus/dummysignalslot.h b/samples/blackmiscdbus/dummysignalslot.h new file mode 100644 index 000000000..8ce74ee59 --- /dev/null +++ b/samples/blackmiscdbus/dummysignalslot.h @@ -0,0 +1,43 @@ +#ifndef BLACKMISCTEST_DUMMYSIGNALSLOT_H +#define BLACKMISCTEST_DUMMYSIGNALSLOT_H + +#include +#include +#include + +namespace BlackMiscTest +{ + + /*! + * \brief Dummy class to hook a signal or slot + */ + class CDummySignalSlot : public QObject + { + Q_OBJECT + + public: + /*! + * \brief CDummySignalSlot + * \param parent + */ + CDummySignalSlot(const QString &name, QObject *parent = 0); + + signals: + /*! + * \brief Test signal + * \param saySomething + */ + void signalCDummy(const QString &saySomething); + public slots: + /*! + * \brief Test slot + * \param saySomething + */ + void slotCDummy(const QString &saySomething); + + private: + QString m_name; + + }; +} +#endif // BLACKMISCTEST_DUMMYSIGNALSLOT_H diff --git a/samples/blackmiscdbus/main.cpp b/samples/blackmiscdbus/main.cpp new file mode 100644 index 000000000..84edf08e4 --- /dev/null +++ b/samples/blackmiscdbus/main.cpp @@ -0,0 +1,116 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "blackmisc/blackmiscfreefunctions.h" +#include "servicetool.h" +#include "blackcore/dbus_server.h" +#include +#include +#include +#include +#include + +/*! + * DBus tests, tests marshalling / unmarshalling of many value classes. + * Forks two processes and sends data via DBus among them. + */ +int main(int argc, char *argv[]) +{ + // of course the code here is containing too many lines, but as it + // is just for testing, I did not split it up + + BlackMisc::registerMetadata(); + QCoreApplication a(argc, argv); + + // trying to get the arguments into a list + QStringList cmdlineArgs = QCoreApplication::arguments(); + if (cmdlineArgs.length() < 1) + { + qFatal("Missing name of executable"); + return 1; + } + + // some runtime settings + const QString executable = QString(cmdlineArgs.at(0)); // used as command to fork myself + const bool clientFlag = cmdlineArgs.contains("client", Qt::CaseInsensitive); + const bool useSessionBusForServer = cmdlineArgs.contains("session", Qt::CaseInsensitive); // flag for session bus + QString address(useSessionBusForServer ? "session" : "tcp:host=192.168.0.133,port=45000"); // testing with real transfer + // loopback 127.0.0.1 + + // Create a Testservice instance and register it with the session bus only if + // the service isn't already available. + if (!clientFlag) + { + // Configure tests + qDebug() << "1 .. Run testservice to test data transfer" << address; + qDebug() << "1sb. Run testservice via session bus"; + qDebug() << "2 .. Data context example (via TCP)" << address; + qDebug() << "2sb. Data context example (via session bus)"; + qDebug() << "3 .. Data context example, only server (via TCP)" << address; + qDebug() << "3sb. Data context example, only server (via session bus)"; + + qDebug() << "x .. Bye"; + QTextStream qtin(stdin); + QString mode = qtin.readLine().toLower(); + bool startServer = !mode.startsWith('3'); + if (mode.contains("sb", Qt::CaseInsensitive)) address = "session"; + if (mode.startsWith("1")) + { + mode = "testservice"; + } + else if (mode.startsWith('2') || mode.startsWith('3')) + { + mode = "context"; + } + else + { + return 0; + } + + // I know I am in the "server process here", so I can safely create a CDBusServer + // this runs in the original process and can be directly debugged + BlackCore::CDBusServer *dBusServer = new BlackCore::CDBusServer(useSessionBusForServer ? "session" : address); + qDebug() << "server" << dBusServer->address() << "connected:" << dBusServer->isConnected(); + + // start client process + QStringList args; + args << "client"; + args << mode; + if (address == "session") args << address; + + if (startServer) BlackMiscTest::ServiceTool::startNewProcess(executable, args, &a); + + // run tests + if (mode == "testservice") + { + BlackMiscTest::ServiceTool::dataTransferTestServer(dBusServer); + } + else if (mode == "context") + { + BlackMiscTest::ServiceTool::contextTestServer(dBusServer); + } + + // loop + return a.exec(); + } + else + { + // 2nd Process !!! Running on the client's side + // This runs in a second process, hence cannot be directly debugged within Qt Creators + + // run tests + if (cmdlineArgs.contains("testservice", Qt::CaseInsensitive)) + { + BlackMiscTest::ServiceTool::dataTransferTestClient(address); + } + else if (cmdlineArgs.contains("context", Qt::CaseInsensitive)) + { + BlackMiscTest::ServiceTool::contextTestClient(address); + } + + // loop + return a.exec(); + } +} diff --git a/samples/blackmiscdbus/readme.txt b/samples/blackmiscdbus/readme.txt new file mode 100644 index 000000000..c2254ea4e --- /dev/null +++ b/samples/blackmiscdbus/readme.txt @@ -0,0 +1,13 @@ +Starting: dbus-daemon.exe --session +- blocks CMD (sometimes daemon continues to run when pressing CTRL/C) +- does not start without directory session.d, i.e. ..\Qt\Qt5.1.0DBus\qtbase\etc\dbus-1\session.d + +!!! The includes are set in the qmake file, there are the header files +!!! which are used in the interface +qdbuscpp2xml testservice.h -x blackmisc_cpp2xml.dll -o BlackMiscTest.Testservice.xml +qdbuscpp2xml datacontext.h -x blackmisc_cpp2xml.dll -o BlackMiscTest.Datacontext.xml +Set search path for plugins: env.var. QT_PLUGIN_PATH + +Done automatically (qmake), but if required manually +Interface: qdbusxml2cpp blackbus.testservice.xml -p itestservice +Adaptor: qdbusxml2cpp blackbus.testservice.xml -a atestservice diff --git a/samples/blackmiscdbus/sample_blackmisc_dbus.pro b/samples/blackmiscdbus/sample_blackmisc_dbus.pro new file mode 100644 index 000000000..095aea866 --- /dev/null +++ b/samples/blackmiscdbus/sample_blackmisc_dbus.pro @@ -0,0 +1,30 @@ +QT += core dbus + +TARGET = sample_blackmisc_dbus +TEMPLATE = app + +CONFIG += console c++11 +CONFIG -= app_bundle + +# Causes nmake to run qdbusxml2cpp to automatically generate the dbus adaptor and interface classes, +# then automatically adds them to the sources to compile +DBUS_ADAPTORS += BlackMiscTest.Testservice.xml BlackMiscTest.Datacontext.xml +DBUS_INTERFACES += BlackMiscTest.Testservice.xml BlackMiscTest.Datacontext.xml +QDBUSXML2CPP_INTERFACE_HEADER_FLAGS = -i blackmisc/blackmiscfreefunctions.h -i blackmisc/blackmiscallvalueclasses.h +QDBUSXML2CPP_ADAPTOR_HEADER_FLAGS = -i blackmisc/blackmiscfreefunctions.h -i blackmisc/blackmiscallvalueclasses.h + +DEPENDPATH += . ../../src/blackmisc ../../src/blackcore +INCLUDEPATH += . ../../src + +LIBS += -L../../lib -lblackcore -lblackmisc +win32:!win32-g++*: PRE_TARGETDEPS += ../../lib/blackmisc.lib \ + ../../lib/blackcore.lib +else: PRE_TARGETDEPS += ../../lib/libblackmisc.a \ + ../../lib/libblackcore.a + +DESTDIR = ../../bin + +HEADERS += *.h +SOURCES += *.cpp + +OTHER_FILES += readme.txt BlackMiscTest.Testservice.xml BlackMiscTest.Datacontext.xml diff --git a/samples/blackmiscdbus/servicetool.cpp b/samples/blackmiscdbus/servicetool.cpp new file mode 100644 index 000000000..b12759976 --- /dev/null +++ b/samples/blackmiscdbus/servicetool.cpp @@ -0,0 +1,689 @@ +#include "servicetool.h" +#include "testservice.h" +#include "testservice_adaptor.h" +#include "testservice_interface.h" +#include "datacontext.h" +#include "datacontext_interface.h" +#include "datacontext_adaptor.h" +#include "blackcore/dbus_server.h" +#include "blackmisc/valuemap.h" +#include "blackmisc/nwserver.h" +#include +#include +#include +#include +#include + +using namespace BlackMisc; +using namespace BlackMisc::PhysicalQuantities; +using namespace BlackMisc::Aviation; +using namespace BlackMisc::Math; +using namespace BlackMisc::Geo; +using namespace BlackMisc::Network; +using namespace BlackMiscTest; + +namespace BlackMiscTest +{ + + /* + * Start a new process + */ + QProcess *ServiceTool::startNewProcess(const QString &executable, const QStringList &arguments, QObject *parent) + { + QProcess *process = new QProcess(parent); + process->startDetached(executable, arguments); + return process; + } + + /* + * Display DBus arguments + */ + void ServiceTool::displayQDBusArgument(const QDBusArgument &arg, qint32 level) + { + arg.beginArray(); + QVariant qv; + QString indent(level * 2, ' '); + + while (!arg.atEnd()) + { + QDBusArgument::ElementType type = arg.currentType(); + QString signature = arg.currentSignature(); + qv = arg.asVariant(); // this advances in the stream + if (qv.canConvert()) + { + qDebug() << indent << type << "signature" << signature; + ServiceTool::displayQDBusArgument(qv.value(), level + 1); + } + else + { + qDebug() << indent << "type:" << type << "signature" << signature << "value" << qv; + } + } + arg.endArray(); + } + + /* + * Server side on testserver + */ + void ServiceTool::dataTransferTestServer(BlackCore::CDBusServer *dBusServer) + { + QDBusConnection sessionBusConnection = QDBusConnection::sessionBus(); + if (sessionBusConnection.interface()->isServiceRegistered(Testservice::ServiceName)) + { + qFatal("Testservice already registed on session bus"); + } + + // as this is the receiver side, the slots can be debugged too + Testservice *testservice = ServiceTool::registerTestservice(sessionBusConnection, QCoreApplication::instance()); + dBusServer->addObject(Testservice::ServicePath, testservice); + } + + /* + * Client side on testserver + */ + void ServiceTool::dataTransferTestClient(const QString &address) + { + // send data via session + QDBusConnection sessionBusConnection = QDBusConnection::sessionBus(); + qDebug() << "------------ sending via session bus" << sessionBusConnection.name(); + ServiceTool::sendDataToTestservice(sessionBusConnection); + + // send data as P2P to server (this can be session bus, too, but usually is P2P) + QDBusConnection p2pConnection = address == "session" ? + QDBusConnection::sessionBus() : + QDBusConnection::connectToPeer(address, "p2pConnection"); + qDebug() << "server connection has interface?" << p2pConnection.interface(); // returns 0 with server and a real interface with session bus + qDebug() << "------------ sending via P2P server " << p2pConnection.name(); + ServiceTool::sendDataToTestservice(p2pConnection); + } + + /* + * Context data transfer test server + */ + void ServiceTool::contextTestServer(BlackCore::CDBusServer *dBusServer) + { + // init data context + CDataContext *dataContext = new CDataContext(dBusServer); + + // create a object which can be connected to signals / slots + CDummySignalSlot *serverSignalSlot = new CDummySignalSlot("server", QCoreApplication::instance()); + + // Adaptor based on context objext + DatacontextAdaptor *dataContextAdaptor = new DatacontextAdaptor(dataContext); // needs to be created in same thread + + // Run server loop: + // This happens in a different thread, because server needs event loop for + // its signal and slots + QtConcurrent::run(ServiceTool::serverLoop, dBusServer, dataContext, dataContextAdaptor, serverSignalSlot); // QFuture future + qDebug() << "Server event loop, pid:" << ServiceTool::getPid(); + } + + /* + * Context data transfer test client + */ + void ServiceTool::contextTestClient(const QString &address) + { + // create a object which can be connected to signals / slots + CDummySignalSlot *clientSignalSlot = new CDummySignalSlot("client", QCoreApplication::instance()); + + // connection + QDBusConnection p2pConnection = address == "session" ? + QDBusConnection::sessionBus() : + QDBusConnection::connectToPeer(address, "p2pConnection"); + + // run client loop + QtConcurrent::run(ServiceTool::clientLoop, p2pConnection, clientSignalSlot); // QFuture future + qDebug() << "Client event loop, pid:" << ServiceTool::getPid(); + } + + /* + * Get callsign + */ + CCallsign ServiceTool::getRandomCallsign() + { + static QList callsigns; + if (callsigns.isEmpty()) + { + callsigns << CCallsign("EDDM_TWR"); + callsigns << CCallsign("EDDM_APP"); + callsigns << CCallsign("EDDM_GND"); + callsigns << CCallsign("EDDF_TWR"); + callsigns << CCallsign("EDDF_APP"); + callsigns << CCallsign("EDDF_GND"); + } + int i = (rand() % (6)); + CCallsign cs = callsigns.at(i); + return cs; + } + + /* + * Stations + */ + CAtcStationList ServiceTool::getStations(qint32 number) + { + BlackMisc::Aviation::CAtcStationList list; + for (int i = 0; i < number; i++) + { + BlackMisc::Aviation::CAtcStation s; + s.setCallsign(QString::number(i)); + s.setFrequency(BlackMisc::PhysicalQuantities::CFrequency(i, BlackMisc::PhysicalQuantities::CFrequencyUnit::MHz())); + s.setController(CUser(QString::number(i), "FooBar", "", "")); + s.setOnline(i % 2 == 0 ? true : false); + s.setPosition(CCoordinateGeodetic(i, i, i)); + list.push_back(s); + } + return list; + + } + + /* + * Register testservice (server side) + */ + Testservice *ServiceTool::registerTestservice(QDBusConnection &connection, QObject *parent) + { + Testservice *pTestservice = new Testservice(parent); // just a QObject with signals / slots and Q_CLASSINFO("D-Bus Interface", some service name) + TestserviceAdaptor *pTestserviceAdaptor = new TestserviceAdaptor(pTestservice); + + if (!connection.registerService(Testservice::ServiceName)) + { + QDBusError err = connection.lastError(); + qWarning() << err.message(); + qWarning() << "Started dbus-daemon.exe --session (Windows)?"; + qWarning() << "Created directory session.d (e.g. ../Qt/Qt5.1.0Vatsim/5.1.0-32/qtbase/etc/dbus-1/session.d)?"; + qWarning() << "See https://dev.vatsim-germany.org/projects/vatpilotclient/wiki/DBusExample#Running-the-example"; + qFatal("Could not register service!"); + } + + if (!connection.registerObject(Testservice::ServicePath, pTestservice)) + { + qFatal("Could not register service object!"); + } + + qDebug() << "Registration running as pid:" << ServiceTool::getPid(); + if (pTestservice) qDebug() << "Service registered"; + if (pTestserviceAdaptor) qDebug() << "Adaptor object registered"; + + QString service; // service not needed + if (connection.connect( + service, Testservice::ServicePath, Testservice::ServiceName, + "sendStringMessage", pTestservice, SLOT(receiveStringMessage(const QString &)))) + { + qDebug() << "Connected object with bus sendStringMessage"; + } + else + { + qFatal("Cannot connect service with DBus"); + } + return pTestservice; + } + + /* + * Send data to testservice, this sends data to the slots on the server + */ + void ServiceTool::sendDataToTestservice(const QDBusConnection &connection) + { + // on the client's side + BlackmisctestTestserviceInterface testserviceInterface(Testservice::ServiceName, Testservice::ServicePath, connection); + + CSpeed speed(200, BlackMisc::PhysicalQuantities::CSpeedUnit::km_h()); + CAltitude al(1000, CAltitude::MeanSeaLevel, CLengthUnit::ft()); + bool loop = true; + + while (loop) + { + QDBusMessage m = QDBusMessage::createSignal( + Testservice::ServicePath, Testservice::ServiceName, + "sendStringMessage"); + + // The << operator is used to add the parameters for the slot + QDateTime dtnow = QDateTime::currentDateTimeUtc(); + QString msg = QString("Message from %1 at %2").arg(ServiceTool::getPid()).arg(dtnow.toString("MM/dd/yyyy @ hh:mm:ss")); + m << msg; + + // We send this as a non-replying message. This is used for sending errors, replys, signals, + // and method calls (slots) that don't return + if (connection.send(m)) + { + qDebug() << "Send via low level method" << m; + } + + // same as interface message + // but call the slot + testserviceInterface.receiveStringMessage(msg); + qDebug() << "Send string via interface" << msg; + + // a list + QList list; + list << 1.0 << 2.0 << 3.0; + testserviceInterface.receiveList(list); + qDebug() << "Send list via interface" << list; + + // PQs + testserviceInterface.receiveSpeed(speed); + qDebug() << "Send speed via interface" << speed; + + speed.switchUnit(CSpeedUnit::kts()); + testserviceInterface.receiveSpeed(speed); + qDebug() << "Send speed via interface" << speed; + QThread::msleep(2500); + speed.switchUnit(CSpeedUnit::km_h()); + speed.addValueSameUnit(1.0); + + // Network + CServer trafficServer("fooserver", "a foo server", "localhost", 1234, + CUser("112233", "Some real name", "email@xyz.com", "secret")); + QVariant tsqv = QVariant::fromValue(trafficServer); + QDBusVariant tsv(tsqv); + testserviceInterface.receiveVariant(tsv, tsqv.userType()); + qDebug() << "Send server via interface and variant" << trafficServer << tsqv.userType(); + + // Aviation + CComSystem comSystem = CComSystem("DBUS COM1", CPhysicalQuantitiesConstants::FrequencyInternationalAirDistress(), CPhysicalQuantitiesConstants::FrequencyUnicom()); + testserviceInterface.receiveComUnit(comSystem); + qDebug() << "Send COM via interface" << comSystem; + + QVariant qvAl = QVariant::fromValue(al); + QDBusVariant qv(qvAl); + testserviceInterface.receiveVariant(qv, qvAl.userType()); + testserviceInterface.receiveAltitude(al); + qDebug() << "Send altitude via interface and variant" << al << qvAl.userType(); + al.addValueSameUnit(1); + + CTransponder transponder("transponder", 7000, CTransponder::ModeC); + testserviceInterface.receiveTransponder(transponder); + qDebug() << "Send transponder via interface" << transponder; + + CTrack track(123.45, CTrack::Magnetic, CAngleUnit::deg()); + testserviceInterface.receiveTrack(track); + qDebug() << "Send track via interface" << track; + + CLength len(33, CLengthUnit::m()); + testserviceInterface.receiveLength(len); + qDebug() << "Send length via interface" << len; + + CAltitude alt(44, CAltitude::MeanSeaLevel, CLengthUnit::m()); + testserviceInterface.receiveLength(alt); + qDebug() << "Send altitude via interface" << alt; + + CCallsign callsign("d-ambz"); + testserviceInterface.receiveCallsign(callsign); + qDebug() << "Send callsign via interface" << callsign; + CCoordinateGeodetic geoPos = CCoordinateGeodetic::fromWgs84("48° 21′ 13″ N", "11° 47′ 09″ E", CLength(1487, CLengthUnit::ft())); // Munich + CAtcStation station(CCallsign("eddm_twr"), CUser("123456", "Joe Doe"), + CFrequency(118.7, CFrequencyUnit::MHz()), + geoPos, CLength(50, CLengthUnit::km())); + + testserviceInterface.receiveAtcStation(station); + qDebug() << "Send ATC station via interface" << station; + + station = testserviceInterface.pingAtcStation(station); + qDebug() << "Pinged ATC station via interface" << station; + + CAtcStationList AtcStationList; + AtcStationList.push_back(station); + AtcStationList.push_back(station); + AtcStationList.push_back(station); + AtcStationList = testserviceInterface.pingAtcStationList(AtcStationList); + qDebug() << "Pinged ATC stations list via interface" << AtcStationList.size() << AtcStationList; + + AtcStationList = ServiceTool::getStations(10); + qDebug() << "Pinged ATC stations list via interface" << AtcStationList.size() << AtcStationList; + + // test variant lists with different types wrapped in QVariant + QVariantList qvList; + qvList << QVariant::fromValue(len); + qvList << QVariant::fromValue(alt); + QList lengthsV; + lengthsV.append(QVariant::fromValue(len)); + lengthsV.append(QVariant::fromValue(alt)); + testserviceInterface.receiveLengthsQvl(qvList); + qDebug() << "Send lengths via interface as QListVariant:"; + testserviceInterface.receiveLengthsQl(lengthsV); + qDebug() << "Send lengths via interface as QList:"; + foreach(QVariant lv, qvList) + { + qDebug() << " " << "Send length in list:" << BlackMisc::qVariantToString(lv); + } + QThread::msleep(2500); + + // Math + CMatrix3x3 m33; + m33.setCellIndex(); + testserviceInterface.receiveMatrix(m33); + qDebug() << "Send matrix" << m33; + + // Geo + // EDDF: 50° 2′ 0″ N, 8° 34′ 14″ E, 100m MSL + geoPos = CCoordinateGeodetic::fromWgs84("50° 2′ 1″ 23 N", "8° 34′ 14″ E", CLength(111, CLengthUnit::m())); + testserviceInterface.receiveGeoPosition(geoPos); + qDebug() << "Send geo position" << geoPos; + + // Value map + CValueMap valueMap; + valueMap.addValue(1, 111.222); + valueMap.addValue(2, callsign); + valueMap.addValue(3, alt); + valueMap.addValue(4, track); + valueMap.addValue(5, QDateTime::currentDateTime().addDays(1)); + valueMap.addValue(6, QString("foobar")); + testserviceInterface.receiveValueMap(valueMap); + qDebug() << "Send value map" << valueMap; + + // Performance tools + QThread::msleep(2500); + qDebug() << "--- PERFORMANCE testing"; + QElapsedTimer timer; + timer.start(); + for (int i = 0; i < 10; i++) + { + CSpeed speedDummy(i, CSpeedUnit::km_h()); + speedDummy = testserviceInterface.getSpeed(); + } + qint64 t10 = timer.nsecsElapsed() / 1000000; // ms + timer.restart(); + for (int i = 0; i < 100; i++) + { + CSpeed speedDummy(i, CSpeedUnit::km_h()); + speedDummy = testserviceInterface.getSpeed(); + } + qint64 t100 = timer.nsecsElapsed() / 1000000; // ms + timer.restart(); + for (int i = 0; i < 1000; i++) + { + CSpeed speedDummy(i, CSpeedUnit::km_h()); + speedDummy = testserviceInterface.getSpeed(); + } + qint64 t1000 = timer.nsecsElapsed() / 1000000; // ms + timer.invalidate(); + qDebug() << "Reading speed objects 10/100/1000 in ms:" << t10 << t100 << t1000; + + timer.start(); + for (int i = 0; i < 10; i++) + { + CAtcStation stationDummy(QString::number(i)); + stationDummy = testserviceInterface.getAtcStation(); + } + t10 = timer.nsecsElapsed() / 1000000; // ms + timer.restart(); + for (int i = 0; i < 100; i++) + { + CAtcStation stationDummy(QString::number(i)); + stationDummy = testserviceInterface.getAtcStation(); + } + t100 = timer.nsecsElapsed() / 1000000; // ms + timer.restart(); + for (int i = 0; i < 1000; i++) + { + CAtcStation stationDummy(QString::number(i)); + stationDummy = testserviceInterface.getAtcStation(); + } + t1000 = timer.nsecsElapsed() / 1000000; // ms + qDebug() << "Reading station objects 10/100/1000 in ms:" << t10 << t100 << t1000; + + timer.restart(); + AtcStationList = testserviceInterface.getAtcStationList(10); + if (AtcStationList.size() != 10) qDebug() << "wrong list size" << AtcStationList.size(); + t10 = timer.nsecsElapsed() / 1000000; // ms + QThread::msleep(1000); + + timer.restart(); + AtcStationList = testserviceInterface.getAtcStationList(100); + if (AtcStationList.size() != 100) qDebug() << "wrong list size" << AtcStationList.size(); + t100 = timer.nsecsElapsed() / 1000000; // ms + QThread::msleep(1000); + + timer.restart(); + AtcStationList = testserviceInterface.getAtcStationList(1000); + if (AtcStationList.size() != 1000) qDebug() << "wrong list size" << AtcStationList.size(); + t1000 = timer.nsecsElapsed() / 1000000; // ms + + qDebug() << "Reading station list 10/100/1000 in ms:" << t10 << t100 << t1000; + timer.invalidate(); + + timer.restart(); + QList objectPaths = testserviceInterface.getObjectPaths(10); + if (objectPaths.size() != 10) qDebug() << "wrong list size" << objectPaths.size(); + t10 = timer.nsecsElapsed() / 1000000; // ms + + timer.restart(); + objectPaths = testserviceInterface.getObjectPaths(100); + if (objectPaths.size() != 100) qDebug() << "wrong list size" << objectPaths.size(); + t100 = timer.nsecsElapsed() / 1000000; // ms + + timer.restart(); + objectPaths = testserviceInterface.getObjectPaths(1000); + if (objectPaths.size() != 1000) qDebug() << "wrong list size" << objectPaths.size(); + t1000 = timer.nsecsElapsed() / 1000000; // ms + + qDebug() << "Reading paths list 10/100/1000 in ms:" << t10 << t100 << t1000; + timer.invalidate(); + + // next round? + qDebug() << "Key ....... x to exit, pid:" << ServiceTool::getPid(); + int ch = getchar(); + if (ch == 'x') loop = false; + } + } + + /* + * Send data to testservice, this sends data to the slots on the server + */ + void ServiceTool::serverLoop(BlackCore::CDBusServer *server, CDataContext *dataContext, DatacontextAdaptor *dataContextAdaptor, CDummySignalSlot *dummySignalSlot) + { + QThread::msleep(3 * 1000); // let the client conncect + qDebug() << "Running on server here" << ServiceTool::getPid(); + CCoordinateGeodetic geoPos = CCoordinateGeodetic::fromWgs84("48° 21′ 13″ N", "11° 47′ 09″ E", CLength(1487, CLengthUnit::ft())); // Munich + CAtcStation station(CCallsign("eddm_twr"), CUser("123456", "Server"), + CFrequency(118.7, CFrequencyUnit::MHz()), + geoPos, CLength(50, CLengthUnit::km())); + CAtcStationList stationList; + QTextStream qtin(stdin); + QString line; + + // we can hook up signal slot + if (QObject::connect(dataContext, SIGNAL(fooSignal(QString)), + dummySignalSlot, SLOT(slotCDummy(QString)))) + { + qDebug() << "Hooked up foo signal"; + } + else + { + qDebug() << "Hook up of foo signal failed!!!"; + } + + // + // Server loop + // + while (line != "x") + { + // set a random callsign + station.setCallsign(ServiceTool::getRandomCallsign()); + + // do what we got to do + if (line == "1") + { + stationList.push_back(station); + dataContextAdaptor->setQpAtcOnlineList(stationList); + dataContextAdaptor->setQpAtcBookedList(stationList); + } + else if (line == "2") + { + stationList.push_back(station); + dataContext->setBookedControllers(stationList); + dataContext->setOnlineControllers(stationList); + } + else if (line.startsWith("3")) + { + int end = (line == "3l") ? 1000 : 1; + for (int i = 0; i < end; i++) + { + station.setCallsign(ServiceTool::getRandomCallsign()); + dataContext->onlineControllers().push_back(station); // non const version + } + } + else if (line == "4") + { + // Signal sending is not transparent + qDebug() << "emit foo signal as Qt signal"; + emit dataContext->fooSignal(QDateTime::currentDateTime().toString()); + // emit dataContextAdaptor->fooSignal(QDateTime::currentDateTime().toString()); + } + else if (line == "5") + { + QDBusMessage signal = QDBusMessage::createSignal( + CDataContext::ServicePath, + CDataContext::ServiceName, + "fooSignal"); + signal << QDateTime::currentDateTime().toString(); // parameter + + // With server use the server's connection which is only available once a connection has been established + // otherwise use the given connection which allows to use this method with session/system bus + QDBusConnection serverConnection = server->getDbusConnections().first(); + if (serverConnection.send(signal)) + { + qDebug() << "emit foo signal as DBus signal on server connection " << serverConnection.name(); + } + else + { + qDebug() << "some issue with DBus signal on server connection" << serverConnection.name(); + } + } + else if (line == "6") + { + dataContext->setFooStrings(1000); + } + + // display current status + qDebug() << "-------------"; + qDebug() << "ATC booked"; + qDebug() << dataContext->bookedControllers().toQString(); + qDebug() << "-------------"; + qDebug() << "ATC online"; + qDebug() << dataContext->onlineControllers().toQString(); + qDebug() << "-------------"; + qDebug() << "Foos"; + qDebug() << dataContext->fooStrings(); + qDebug() << "-------------"; + + // next round? Server + qDebug() << "Key x to exit"; + qDebug() << "1 .. new list via property on adaptor"; + qDebug() << "2 .. new list via context"; + qDebug() << "3 .. append 1 to online controllers in context"; // add to reference + qDebug() << "3l . append 1000 to context"; + qDebug() << "4 .. send Foo signal as Qt signal"; + qDebug() << "5 .. send Foo signal as DBus signal"; + qDebug() << "6 .. set 1000 Foo objects"; + + line = qtin.readLine(); + } + } + + /* + * Send data to testservice, this sends data to the slots on the server + */ + void ServiceTool::clientLoop(QDBusConnection &connection, CDummySignalSlot *dummyObjectSignalSlot) + { + // Service name does not matter when using P2P, it is only required using session/system bus + // Using a literal here ("foo"), crashes the app + BlackmisctestDatacontextInterface dataContextInterface(BlackCore::CDBusServer::ServiceName, CDataContext::ServicePath, connection); + if (dummyObjectSignalSlot) + { + const QString signalName("fooSignal"); + if (connection.connect(BlackCore::CDBusServer::ServiceName, CDataContext::ServicePath, CDataContext::ServiceName, signalName, dummyObjectSignalSlot, SLOT(slotCDummy(QString)))) + { + qDebug() << "Hooked up foo signal on connection"; + } + else + { + qDebug() << "Hook up of foo signal failed on connection!!!"; + } + + + // we can hook up signal slot + if (dataContextInterface.connect(&dataContextInterface, SIGNAL(fooSignal(QString)), + dummyObjectSignalSlot, SLOT(slotCDummy(QString)))) + { + qDebug() << "Hooked up foo signal on interface"; + } + else + { + qDebug() << "Hook up of foo signal failed on interface!!!"; + } + } + + qDebug() << "Running on client here, pid:" << ServiceTool::getPid(); + CCoordinateGeodetic geoPos = CCoordinateGeodetic::fromWgs84("48° 21′ 13″ N", "11° 47′ 09″ E", CLength(1487, CLengthUnit::ft())); // Munich + CAtcStation station(CCallsign("eddm_twr"), CUser("654321", "client"), + CFrequency(118.7, CFrequencyUnit::MHz()), + geoPos, CLength(50, CLengthUnit::km())); + QTextStream qtin(stdin); + QString line; + + // + // Server loop + // + while (line != "x") + { + // set a random callsign + station.setCallsign(ServiceTool::getRandomCallsign()); + + // do what we got to do + if (line == "1") + { + // retrieves all stations, add one, and sends them back + CAtcStationList stations = dataContextInterface.qpAtcBookedList(); + stations.push_back(station); + dataContextInterface.setQpAtcBookedList(stations); + + stations = dataContextInterface.qpAtcOnlineList(); + stations.push_back(station); + dataContextInterface.setQpAtcOnlineList(stations); + } + else if (line == "3") + { + // this will not change anything + dataContextInterface.qpAtcBookedList().push_back(station); + dataContextInterface.qpAtcOnlineList().push_back(station); + } + else if (line == "5") + { + emit dataContextInterface.fooSignal("Directly called on interface on client"); + } + else if (line.startsWith("7") && line.length() > 1) + { + CCallsign callsign(line.mid(1)); + CValueMap condition; + condition.addValue(CAtcStation::IndexCallsign, callsign); + CValueMap value; + value.addValue(CAtcStation::IndexBookedFrom, QDateTime::currentDateTimeUtc().addDays(1)); + value.addValue(CAtcStation::IndexBookedUntil, QDateTime::currentDateTimeUtc().addDays(2)); + qDebug() << " condition" << condition; + qDebug() << " values" << value; + qint32 c = dataContextInterface.updateOnlineControllers(condition, value); + qDebug() << c << "values changed in online controllers"; + } + + // display current status + qDebug() << "-------------"; + qDebug() << "ATC booked"; + qDebug() << dataContextInterface.qpAtcBookedList().toQString(); // as property + qDebug() << "-------------"; + qDebug() << "ATC online"; + qDebug() << dataContextInterface.qpAtcOnlineList().toQString(); // as property + qDebug() << "-------------"; + qDebug() << "Foos"; + qDebug() << dataContextInterface.qpFooStrings(); + qDebug() << "-------------"; + + // next round? Client + qDebug() << "Key x to exit"; + qDebug() << "1 .. add new list via property on interface"; + qDebug() << "3 .. append 1 to controllers in context (no expected to change anything)"; // add to reference + qDebug() << "5 .. foo signal directly on interface"; + qDebug() << "7x . 7, update if, e.g. 7EDDM_TWR"; + + line = qtin.readLine(); + } + } +} // namespace diff --git a/samples/blackmiscdbus/servicetool.h b/samples/blackmiscdbus/servicetool.h new file mode 100644 index 000000000..4f80ce8a0 --- /dev/null +++ b/samples/blackmiscdbus/servicetool.h @@ -0,0 +1,120 @@ +#ifndef BLACKMISCTEST_SERVICETOOL_H +#define BLACKMISCTEST_SERVICETOOL_H + +#include "blackcore/dbus_server.h" +#include "datacontext.h" +#include "dummysignalslot.h" +#include +#include +#include + +class DatacontextAdaptor; + +namespace BlackMiscTest +{ + + class Testservice; // forward declaration + + /*! + * \brief Supporting functions for running the tests + */ + class ServiceTool + { + private: + ServiceTool() {} + + public: + /*! + * \brief Get process id + * \return + */ + static qint64 getPid() + { + return QCoreApplication::applicationPid(); + } + + /*! + * \brief Client side of data transfer test + * \param address + */ + static void dataTransferTestClient(const QString &address); + + /*! + * \brief Server side of data transfer test + */ + static void dataTransferTestServer(BlackCore::CDBusServer *dBusServer); + + /*! + * \brief Context test, server side + * \param dBusServer + */ + static void contextTestServer(BlackCore::CDBusServer *dBusServer); + + /*! + * \brief Context test, client side + * \param address + */ + static void contextTestClient(const QString &address); + + /*! + * \brief Start a new process + * \param executable + * \param arguments + * \param parent + * \return + */ + static QProcess *startNewProcess(const QString &executable, const QStringList &arguments = QStringList(), QObject *parent = 0); + + /*! + * \brief Loop to send data to test service (slots on server) + * \param connection + */ + static void sendDataToTestservice(const QDBusConnection &connection); + + /*! + * \brief Display QDBusArgument + * \param arg + */ + static void displayQDBusArgument(const QDBusArgument &arg, qint32 level = 0); + + /*! + * \brief Register testservice with connection + * \param connection + * \param parent + * \return test service object + */ + static Testservice *registerTestservice(QDBusConnection &connection, QObject *parent = 0); + + /*! + * \brief Server loop + * \param server + * \param dataContext + * \param dataContextAdaptor + * \param dummySignalSlot + */ + static void serverLoop(BlackCore::CDBusServer *server, CDataContext *dataContext, DatacontextAdaptor *dataContextAdaptor, CDummySignalSlot *dummySignalSlot); + + /*! + * \brief Client loop + * \param connection + */ + static void clientLoop(QDBusConnection &connection, CDummySignalSlot *dummyObjectSignalSlot); + + /*! + * \brief Get a random callsign + * \return + */ + static BlackMisc::Aviation::CCallsign getRandomCallsign(); + + /*! + * \brief Get stations + * \param number + * \return + */ + static BlackMisc::Aviation::CAtcStationList getStations(qint32 number); + + }; + +} // namespace + +#endif // guard diff --git a/samples/blackmiscdbus/testservice.cpp b/samples/blackmiscdbus/testservice.cpp new file mode 100644 index 000000000..6c36c4556 --- /dev/null +++ b/samples/blackmiscdbus/testservice.cpp @@ -0,0 +1,253 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "testservice.h" +#include "blackmisc/blackmiscfreefunctions.h" + +using namespace BlackMisc::Aviation; +using namespace BlackMisc::Geo; +using namespace BlackMisc::PhysicalQuantities; +using namespace BlackMisc::Network; + +namespace BlackMiscTest +{ + + const QString Testservice::ServiceName = QString(BLACKMISCKTEST_TESTSERVICE_INTERFACENAME); + const QString Testservice::ServicePath = QString(BLACKMISCKTEST_TESTSERVICE_SERVICEPATH); + + /* + * Constructor + */ + Testservice::Testservice(QObject *parent) : QObject(parent) + { + // void + } + + /* + * Slot to receive messages + */ + void Testservice::receiveStringMessage(const QString &message) + { + qDebug() << "Pid:" << ServiceTool::getPid() << "Received message:" << message; + } + + /* + * Receive variant + */ + void Testservice::receiveVariant(const QDBusVariant &variant, int localMetyType) + { + QVariant qv = variant.variant(); + QVariant qvF = BlackMisc::fixQVariantFromDbusArgument(qv, localMetyType); + QString s = BlackMisc::qVariantToString(qvF, true); + qDebug() << "Pid:" << ServiceTool::getPid() << "Received variant:" << s; + } + + /* + * Receive speed + */ + void Testservice::receiveSpeed(const BlackMisc::PhysicalQuantities::CSpeed &speed) + { + qDebug() << "Pid:" << ServiceTool::getPid() << "Received speed:" << speed; + } + + /* + * Ping speed + */ + BlackMisc::PhysicalQuantities::CSpeed Testservice::pingSpeed(const BlackMisc::PhysicalQuantities::CSpeed &speed) + { + return speed; + } + + + /* + * Get speed + */ + BlackMisc::PhysicalQuantities::CSpeed Testservice::getSpeed() const + { + return BlackMisc::PhysicalQuantities::CSpeed(666, BlackMisc::PhysicalQuantities::CSpeedUnit::km_h()); + } + + /* + * Station + */ + BlackMisc::Aviation::CAtcStation Testservice::getAtcStation() const + { + CCoordinateGeodetic geoPos = CCoordinateGeodetic::fromWgs84("48° 21′ 13″ N", "11° 47′ 09″ E", CLength(1487, CLengthUnit::ft())); // Munich + CAtcStation station(CCallsign("eddm_twr"), CUser("654321", "client"), + CFrequency(118.7, CFrequencyUnit::MHz()), + geoPos, CLength(50, CLengthUnit::km())); + return station; + } + + /* + * Receive COM unit + */ + void Testservice::receiveComUnit(const BlackMisc::Aviation::CComSystem &comUnit) + { + qDebug() << "Pid:" << ServiceTool::getPid() << "Received COM:" << comUnit; + } + + /* + * Receive altitude + */ + void Testservice::receiveAltitude(const BlackMisc::Aviation::CAltitude &altitude) + { + qDebug() << "Pid:" << ServiceTool::getPid() << "Received altitude:" << altitude; + } + + /* + * Ping altitude + */ + BlackMisc::Aviation::CAltitude Testservice::pingAltitude(const BlackMisc::Aviation::CAltitude &altitude) + { + return altitude; + } + + /* + * Receive matrix + */ + void Testservice::receiveMatrix(const BlackMisc::Math::CMatrix3x3 &matrix) + { + qDebug() << "Pid:" << ServiceTool::getPid() << "Received matrix:" << matrix; + } + + /* + * Receive a list + */ + void Testservice::receiveList(const QList &list) + { + qDebug() << "Pid:" << ServiceTool::getPid() << "Received list:" << list; + } + + /* + * Receive a geo position + */ + void Testservice::receiveGeoPosition(const BlackMisc::Geo::CCoordinateGeodetic &geo) const + { + qDebug() << "Pid:" << ServiceTool::getPid() << "Received geo data:" << geo; + } + + /* + * Receive transponder + */ + void Testservice::receiveTransponder(const BlackMisc::Aviation::CTransponder &transponder) const + { + qDebug() << "Pid:" << ServiceTool::getPid() << "Received transponder:" << transponder; + } + + /* + * Receive track + */ + void Testservice::receiveTrack(const BlackMisc::Aviation::CTrack &track) const + { + qDebug() << "Pid:" << ServiceTool::getPid() << "Received track:" << track; + } + + /* + * Receive a length + */ + void Testservice::receiveLength(const BlackMisc::PhysicalQuantities::CLength &length) const + { + qDebug() << "Pid:" << ServiceTool::getPid() << "Received length:" << length; + } + + /* + * Receive lengths + */ + void Testservice::receiveLengthsQvl(const QVariantList &lengthsVariantList) const + { + qDebug() << "Pid:" << ServiceTool::getPid() << lengthsVariantList; + foreach(QVariant lv, lengthsVariantList) + { + BlackMisc::PhysicalQuantities::CLength l; + lv.value() >> l; + qDebug() << " Received length in list:" << l; + } + } + + /* + * Receive lengths + */ + void Testservice::receiveLengthsQl(const QList &lengthsList) const + { + qDebug() << "Pid:" << ServiceTool::getPid() << "Received " << lengthsList; + foreach(QVariant lv, lengthsList) + { + BlackMisc::PhysicalQuantities::CLength l; + lv.value() >> l; + qDebug() << " Received length in list:" << l; + } + } + + /* + * Receive callsign + */ + void Testservice::receiveCallsign(const BlackMisc::Aviation::CCallsign &callsign) const + { + qDebug() << "Pid:" << ServiceTool::getPid() << "Received callsign:" << callsign; + } + + /* + * Receive ATC list + */ + void Testservice::receiveAtcStationList(const BlackMisc::Aviation::CAtcStationList &AtcStationList) const + { + qDebug() << "Pid:" << ServiceTool::getPid() << "Received ATC list:" << AtcStationList; + } + + /* + * Receive ATC list + */ + BlackMisc::Aviation::CAtcStationList Testservice::pingAtcStationList(const BlackMisc::Aviation::CAtcStationList &AtcStationList) const + { + return AtcStationList; + } + + /* + * Receive value map + */ + void Testservice::receiveValueMap(const BlackMisc::CValueMap &valueMap) const + { + qDebug() << "Pid:" << ServiceTool::getPid() << "Received value map:" << valueMap; + } + + /* + * Receive callsign + */ + void Testservice::receiveAtcStation(const BlackMisc::Aviation::CAtcStation &station) const + { + qDebug() << "Pid:" << ServiceTool::getPid() << "Received ATC station:" << station; + } + + /* + * Ping ATC station + */ + const BlackMisc::Aviation::CAtcStationList Testservice::getAtcStationList(const qint32 number) const + { + return BlackMisc::Aviation::CAtcStationList(ServiceTool::getStations(number)); + } + + /* + * Object paths + */ + const QList Testservice::getObjectPaths(const qint32 number) const + { + QList paths; + for (int i = 0; i < number; i++) + { + paths.append(QDBusObjectPath(BLACKMISCKTEST_TESTSERVICE_SERVICEPATH)); + } + return paths; + } + + /* + * Ping ATC station + */ + BlackMisc::Aviation::CAtcStation Testservice::pingAtcStation(const BlackMisc::Aviation::CAtcStation &station) + { + return station; + } + +} // namespace diff --git a/samples/blackmiscdbus/testservice.h b/samples/blackmiscdbus/testservice.h new file mode 100644 index 000000000..3f69eec69 --- /dev/null +++ b/samples/blackmiscdbus/testservice.h @@ -0,0 +1,230 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef BLACKMISCKTEST_TESTSERVICEPQAV_H +#define BLACKMISCKTEST_TESTSERVICEPQAV_H + +// clash with struct interface in objbase.h used to happen +#pragma push_macro("interface") +#undef interface + +#include "blackmisc/avallclasses.h" +#include "blackmisc/pqallquantities.h" +#include "blackmisc/mathallclasses.h" +#include "servicetool.h" +#include +#include +#include +#include +#include + +#define BLACKMISCKTEST_TESTSERVICE_INTERFACENAME "blackmisctest.testservice" +#define BLACKMISCKTEST_TESTSERVICE_SERVICEPATH "/ts" + +namespace BlackMiscTest +{ + + /*! + * Testservice for PQ DBus tests. Needs to re-generate the introspection xml file + * (qdbuscpp2xml) when new slots have been added. + */ + class Testservice : public QObject + { + // see the readme.txt on how to qdbuscpp2xml + // remember to recompile the plugin when new class have been createdand registered + // http://techbase.kde.org/Development/Tutorials/D-Bus/CustomTypes#Write_a_class + // https://dev.vatsim-germany.org/projects/vatpilotclient/wiki/DBusExample + // http://qt-project.org/doc/qt-4.8/examples-dbus.html + // http://dbus.freedesktop.org/doc/dbus-tutorial.html#meta + + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", BLACKMISCKTEST_TESTSERVICE_INTERFACENAME) + + // For some reasons the interface name in the XML is not set correctly + // to the above name + + signals: + /*! + * \brief Send string message + * \param message + */ + void sendStringMessage(const QString &message); + + public slots: + + /*! + * \brief Receive string message + * \param message + */ + void receiveStringMessage(const QString &message); + + /*! + * \brief Receive a QVariant + * \param variant + * \param localMetyType, works only in the same binary + */ + void receiveVariant(const QDBusVariant &variant, int localMetyType); + + /*! + * \brief Receive speed + * \param speed + */ + void receiveSpeed(const BlackMisc::PhysicalQuantities::CSpeed &speed); + + /*! + * \brief Receive speed + * \param speed + */ + BlackMisc::PhysicalQuantities::CSpeed pingSpeed(const BlackMisc::PhysicalQuantities::CSpeed &speed); + + /*! + * \brief Receive com unit + * \param comUnit + */ + void receiveComUnit(const BlackMisc::Aviation::CComSystem &comUnit); + + /*! + * \brief Receive altitude + * \param comUnit + */ + void receiveAltitude(const BlackMisc::Aviation::CAltitude &altitude); + + /*! + * \brief Receive altitude + * \param comUnit + */ + BlackMisc::Aviation::CAltitude pingAltitude(const BlackMisc::Aviation::CAltitude &altitude); + + /*! + * \brief Receive matrix + * \param matrix + */ + void receiveMatrix(const BlackMisc::Math::CMatrix3x3 &matrix); + + /*! + * \brief Receive list + * \param list + */ + void receiveList(const QList &list); + + /*! + * \brief Receive a geo position + * \param geo + */ + void receiveGeoPosition(const BlackMisc::Geo::CCoordinateGeodetic &geo) const; + + /*! + * \brief Receive transponder + * \param transponder + */ + void receiveTransponder(const BlackMisc::Aviation::CTransponder &transponder) const; + + /*! + * \brief Receive track + * \param track + */ + void receiveTrack(const BlackMisc::Aviation::CTrack &track) const; + + /*! + * \brief Receive a length (not working) + * \param length + */ + void receiveLength(const BlackMisc::PhysicalQuantities::CLength &length) const; + + /*! + * \brief Receive lengths + * \param length + */ + void receiveLengthsQl(const QList &lengthsList) const; + + /*! + * \brief Receive lengths + * \param length + */ + void receiveLengthsQvl(const QVariantList &lengthsVariantList) const; + + /*! + * \brief Receive ATC station + * \param station + */ + void receiveAtcStation(const BlackMisc::Aviation::CAtcStation &station) const; + + /*! + * \brief Ping ATC station + * \param station + */ + BlackMisc::Aviation::CAtcStation pingAtcStation(const BlackMisc::Aviation::CAtcStation &station); + + /*! + * \brief Receive callsign + * \param callsign + */ + void receiveCallsign(const BlackMisc::Aviation::CCallsign &callsign) const; + + /*! + * \brief return n ATC stations + * \param number + * \return + */ + const BlackMisc::Aviation::CAtcStationList getAtcStationList(const qint32 number) const; + + /*! + * \brief Get object paths + * \param number + * \return + */ + const QList getObjectPaths(const qint32 number) const; + + /*! + * \brief Receive ATC list + * \param AtcStationList + */ + void receiveAtcStationList(const BlackMisc::Aviation::CAtcStationList &AtcStationList) const; + + /*! + * \brief Receive an value map + * \param valueMap + */ + void receiveValueMap(const BlackMisc::CValueMap &valueMap) const; + + /*! + * \brief Ping atc list + * \param AtcStationList + * \return + */ + BlackMisc::Aviation::CAtcStationList pingAtcStationList(const BlackMisc::Aviation::CAtcStationList &AtcStationList) const; + + /*! + * \brief Get speed + * \return + */ + BlackMisc::PhysicalQuantities::CSpeed getSpeed() const; + + /*! + * \brief Get station + * \return + */ + BlackMisc::Aviation::CAtcStation getAtcStation() const; + + public: + static const QString ServiceName; + static const QString ServicePath; + + /*! + * \brief Constructor + * \param parent + */ + explicit Testservice(QObject *parent = 0); + + private: + BlackMisc::Aviation::CAtcStationList m_someAtcStations; + + }; + +} // namespace + +#pragma pop_macro("interface") + +#endif // guard diff --git a/samples/blackmiscquantities/sample_quantities_aviation.pro b/samples/blackmiscquantities/sample_quantities_aviation.pro new file mode 100644 index 000000000..e6d824300 --- /dev/null +++ b/samples/blackmiscquantities/sample_quantities_aviation.pro @@ -0,0 +1,22 @@ +QT += core dbus + +TARGET = sample_quantities_aviation +TEMPLATE = app + +CONFIG += console c++11 +CONFIG -= app_bundle + +DEPENDPATH += . ../../src/blackmisc +INCLUDEPATH += . ../../src + +LIBS += -L../../lib -lblackmisc + +win32:!win32-g++*: PRE_TARGETDEPS += ../../lib/blackmisc.lib +else: PRE_TARGETDEPS += ../../lib/libblackmisc.a + +DESTDIR = ../../bin + +HEADERS += *.h +SOURCES += *.cpp + +OTHER_FILES += diff --git a/samples/blackmiscquantities/samplesaviation.cpp b/samples/blackmiscquantities/samplesaviation.cpp index 436c47f04..96fe88fce 100644 --- a/samples/blackmiscquantities/samplesaviation.cpp +++ b/samples/blackmiscquantities/samplesaviation.cpp @@ -9,11 +9,15 @@ #include "blackmisc/aviocomsystem.h" #include "blackmisc/avionavsystem.h" #include "blackmisc/aviotransponder.h" +#include "blackmisc/avatcstationlist.h" #include +using namespace BlackMisc; using namespace BlackMisc::Aviation; using namespace BlackMisc::PhysicalQuantities; +using namespace BlackMisc::Geo; +using namespace BlackMisc::Network; namespace BlackMiscTest { @@ -62,7 +66,38 @@ namespace BlackMiscTest CTransponder tr2("T2", "4532", CTransponder::ModeMil3); qDebug() << tr1 << tr2; + // Callsign and ATC station + CCallsign callsign1("d-ambz"); + CCallsign callsign2("DAmbz"); + qDebug() << callsign1 << callsign2 << (callsign1 == callsign2); + QDateTime dtFrom = QDateTime::currentDateTimeUtc(); + QDateTime dtUntil = dtFrom.addSecs(60 * 60.0); // 1 hour + QDateTime dtFrom2 = dtUntil; + QDateTime dtUntil2 = dtUntil.addSecs(60 * 60.0); + CCoordinateGeodetic geoPos = + CCoordinateGeodetic::fromWgs84("48° 21′ 13″ N", "11° 47′ 09″ E", CLength(1487, CLengthUnit::ft())); + CAtcStation station1(CCallsign("eddm_twr"), CUser("123456", "Joe Doe"), + CFrequency(118.7, CFrequencyUnit::MHz()), + geoPos, CLength(50, CLengthUnit::km()), false, dtFrom, dtUntil); + CAtcStation station2(station1); + CAtcStation station3(CCallsign("eddm_twr"), CUser("654321", "Jen Doe"), + CFrequency(118.7, CFrequencyUnit::MHz()), + geoPos, CLength(100, CLengthUnit::km()), false, dtFrom2, dtUntil2); + qDebug() << station1 << station2 << (station1.getCallsign() == station2.getCallsign()); + + + // ATC List + CAtcStationList atcList; + atcList.push_back(station1); + atcList.push_back(station2); + atcList.push_back(station3); + atcList.push_back(station1); + atcList.push_back(station2); + atcList.push_back(station3); + atcList = atcList.findBy(&CAtcStation::getCallsign, "eddm_twr", &CAtcStation::getFrequency, CFrequency(118.7, CFrequencyUnit::MHz())); + atcList = atcList.sortedBy(&CAtcStation::getBookedFromUtc, &CAtcStation::getCallsign, &CAtcStation::getControllerRealname); + qDebug() << atcList; qDebug() << "-----------------------------------------------"; return 0; diff --git a/samples/blackmiscquantities_dbus/BlackMiscTest.Testservice.xml b/samples/blackmiscquantities_dbus/BlackMiscTest.Testservice.xml deleted file mode 100644 index cdabcbf5a..000000000 --- a/samples/blackmiscquantities_dbus/BlackMiscTest.Testservice.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/blackmiscquantities_dbus/main.cpp b/samples/blackmiscquantities_dbus/main.cpp deleted file mode 100644 index 6e571e3da..000000000 --- a/samples/blackmiscquantities_dbus/main.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* Copyright (C) 2013 VATSIM Community / authors - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include -#include -#include -#include -#include - -#include "testservice.h" -#include "testservice_adaptor.h" -#include "testservice_interface.h" -#include "testservicetool.h" - -using namespace BlackMisc::PhysicalQuantities; -using namespace BlackMisc::Aviation; -using namespace BlackMisc::Math; -using namespace BlackMisc::Geo; -using namespace BlackMiscTest; - -/*! - * Sample tests - */ -int main(int argc, char *argv[]) -{ - BlackMisc::registerMetadata(); - QCoreApplication a(argc, argv); - - // init - if (argc < 1) { - qFatal("Missing name of executable"); - } - const QString executable = QString(argv[0]); - Testservice* pTestservice = NULL; - TestserviceAdaptor* pTestserviceAdaptor = NULL; - - // Create a Testservice instance and register it with the session bus only if - // the service isn't already available. - QDBusConnection connection = QDBusConnection::sessionBus(); - if (!connection.interface()->isServiceRegistered(Testservice::ServiceName)) { - pTestservice = new Testservice(&a); - pTestserviceAdaptor = new TestserviceAdaptor(pTestservice); - - if (!connection.registerService(Testservice::ServiceName)) { - QDBusError err = connection.lastError(); - qWarning() << err.message(); - qWarning() << "Started dbus-daemon.exe --session?"; - qWarning() << "Created directory session.d? See https://dev.vatsim-germany.org/projects/vatpilotclient/wiki/DBusExample#Running-the-example"; - qFatal("Could not register service!"); - } - - if (!connection.registerObject(Testservice::ServicePath, pTestservice)) { - qFatal("Could not register service object!"); - } - - qDebug() << "Registration running as pid: " << TestserviceTool::getPid(); - if (pTestservice) qDebug() << "Service registered"; - if (pTestserviceAdaptor) qDebug() << "Adaptor object registered"; - - new TestserviceAdaptor(pTestservice); // adaptor - QString service; // service not needed - if (QDBusConnection::sessionBus().connect( - service, Testservice::ServicePath, Testservice::ServiceName, - "sendStringMessage", pTestservice, SLOT(receiveStringMessage(const QString &)))) { - qDebug() << "Connected object with bus sendStringMessage"; - } else { - qFatal("Cannot connect service with DBus"); - } - - // Call myself to implement client - TestserviceTool::startNewProcess(executable, &a); - - } else { - qDebug() << "Already registered, assuming 2nd pid: " << TestserviceTool::getPid(); - BlackmisctestTestserviceInterface testserviceInterface(Testservice::ServiceName, Testservice::ServicePath, connection, &a); - - CSpeed speed(200, BlackMisc::PhysicalQuantities::CSpeedUnit::km_h()); - CAltitude al(1000, CAltitude::MeanSeaLevel, CLengthUnit::ft()); - - while (true) { - QDBusMessage m = QDBusMessage::createSignal( - Testservice::ServicePath, Testservice::ServiceName, - "sendStringMessage"); - - //The << operator is used to add the parameters for the slot - QDateTime dtnow = QDateTime::currentDateTimeUtc(); - QString msg = QString("Message from %1 at %2").arg(TestserviceTool::getPid()).arg(dtnow.toString("MM/dd/yyyy @ hh:mm:ss")); - m << msg; - - // We send this as a non-replying message. This is used for sending errors, replys, signals, - // and method calls (slots) that don't return - if (connection.send(m)) { - qDebug() << "Send via low level method" << m; - } - - // same as interface message - testserviceInterface.receiveStringMessage(msg); - qDebug() << "Send string via interface" << msg; - - // a list - QList list; - list << 1.0 << 2.0 << 3.0; - testserviceInterface.receiveList(list); - qDebug() << "Send list via interface" << list; - - // PQs - testserviceInterface.receiveSpeed(speed); - qDebug() << "Send speed via interface" << speed; - - speed.switchUnit(CSpeedUnit::kts()); - testserviceInterface.receiveSpeed(speed); - qDebug() << "Send speed via interface" << speed; - TestserviceTool::sleep(2500); - speed.switchUnit(CSpeedUnit::km_h()); - speed.addValueSameUnit(1.0); - - // Aviation - CComSystem comSystem = CComSystem("DBUS COM1", CPhysicalQuantitiesConstants::FrequencyInternationalAirDistress(), CPhysicalQuantitiesConstants::FrequencyUnicom()); - testserviceInterface.receiveComUnit(comSystem); - qDebug() << "Send COM via interface" << comSystem; - - QDBusVariant qv(QVariant::fromValue(al)); - testserviceInterface.receiveVariant(qv); - testserviceInterface.receiveAltitude(al); - qDebug() << "Send altitude via interface" << al; - al.addValueSameUnit(1); - - CTransponder transponder("transponder", 7000, CTransponder::ModeC); - testserviceInterface.receiveTransponder(transponder); - qDebug() << "Send transponder via interface" << transponder; - - CTrack track(123.45, CTrack::Magnetic, CAngleUnit::deg()); - testserviceInterface.receiveTrack(track); - qDebug() << "Send track via interface" << track; - - CLength len(33, CLengthUnit::m()); - testserviceInterface.receiveLength(len); - qDebug() << "Send length via interface" << len; - - CAltitude alt(33, CAltitude::MeanSeaLevel, CLengthUnit::m()); - testserviceInterface.receiveLength(alt); - qDebug() << "Send altitude via interface" << alt; - - QVariantList lengths; - lengths << QVariant::fromValue(len); - lengths << QVariant::fromValue(alt); - testserviceInterface.receiveLengths(lengths); - qDebug() << "Send lengths via interface"; - - TestserviceTool::sleep(2500); - - // Math - CMatrix3x3 m33; - m33.setCellIndex(); - testserviceInterface.receiveMatrix(m33); - qDebug() << "Send matrix" << m33; - - // Geo - // EDDF: 50° 2′ 0″ N, 8° 34′ 14″ E, 100m MSL - CLatitude lat = CLatitude::fromWgs84("50° 2′ 1″ 23 N"); - CLongitude lon = CLongitude::fromWgs84("8° 34′ 14″ E"); - CLength height(100, CLengthUnit::m()); - CCoordinateGeodetic geoPos(lat, lon, height); - testserviceInterface.receiveGeoPosition(geoPos); - qDebug() << "Send geo position" << geoPos; - - // next round? - qDebug() << "Key ......."; - getchar(); - } - } - - return a.exec(); -} diff --git a/samples/blackmiscquantities_dbus/sample_quantities_avionics_dbus.pro b/samples/blackmiscquantities_dbus/sample_quantities_avionics_dbus.pro deleted file mode 100644 index ae5acc6c6..000000000 --- a/samples/blackmiscquantities_dbus/sample_quantities_avionics_dbus.pro +++ /dev/null @@ -1,29 +0,0 @@ -QT += core dbus - -TARGET = sample_quantities_avionics_dbus -TEMPLATE = app - -CONFIG += console c++11 -CONFIG -= app_bundle - -# Causes nmake to run qdbusxml2cpp to automatically generate the dbus adaptor and interface classes, -# then automatically adds them to the sources to compile -DBUS_ADAPTORS += BlackMiscTest.Testservice.xml -DBUS_INTERFACES += BlackMiscTest.Testservice.xml -QDBUSXML2CPP_INTERFACE_HEADER_FLAGS = -i blackmisc/blackmiscfreefunctions.h -QDBUSXML2CPP_ADAPTOR_HEADER_FLAGS = -i blackmisc/blackmiscfreefunctions.h - -DEPENDPATH += . ../../src/blackmisc -INCLUDEPATH += . ../../src - -LIBS += -L../../lib -lblackmisc - -win32:!win32-g++*: PRE_TARGETDEPS += ../../lib/blackmisc.lib -else: PRE_TARGETDEPS += ../../lib/libblackmisc.a - -DESTDIR = ../../bin - -HEADERS += *.h -SOURCES += *.cpp - -OTHER_FILES += readme.txt BlackMiscTest.Testservice.xml diff --git a/samples/blackmiscquantities_dbus/testservice.cpp b/samples/blackmiscquantities_dbus/testservice.cpp deleted file mode 100644 index 6d88cf33c..000000000 --- a/samples/blackmiscquantities_dbus/testservice.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* Copyright (C) 2013 VATSIM Community / authors - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "testservice.h" - -namespace BlackMiscTest -{ - -const QString Testservice::ServiceName = QString(BLACKMISCKTEST_SERVICENAME); -const QString Testservice::ServicePath = QString(BLACKMISCKTEST_SERVICEPATH); - -/* - * Constructor - */ -Testservice::Testservice(QObject *parent) : QObject(parent) -{ - // void -} - -/* - * Slot to receive messages - */ -void Testservice::receiveStringMessage(const QString &message) -{ - qDebug() << "Pid:" << TestserviceTool::getPid() << "Received message:" << message; -} - -/* - * Receive variant - */ -void Testservice::receiveVariant(const QDBusVariant &variant) -{ - QVariant qv = variant.variant(); - BlackMisc::Aviation::CAltitude altitude = qv.value(); - qDebug() << "Pid:" << TestserviceTool::getPid() << "Received variant:" << altitude; -} - -/* - * Receive speed - */ -void Testservice::receiveSpeed(const BlackMisc::PhysicalQuantities::CSpeed &speed) -{ - qDebug() << "Pid:" << TestserviceTool::getPid() << "Received speed:" << speed; -} - -/* - * Receive COM unit - */ -void Testservice::receiveComUnit(const BlackMisc::Aviation::CComSystem &comUnit) -{ - qDebug() << "Pid:" << TestserviceTool::getPid() << "Received COM:" << comUnit; -} - -/* - * Receive altitude - */ -void Testservice::receiveAltitude(const BlackMisc::Aviation::CAltitude &altitude) -{ - qDebug() << "Pid:" << TestserviceTool::getPid() << "Received altitude:" << altitude; -} - -/* - * Receive matrix - */ -void Testservice::receiveMatrix(const BlackMisc::Math::CMatrix3x3 &matrix) -{ - qDebug() << "Pid:" << TestserviceTool::getPid() << "Received matrix:" << matrix; -} - -/* - * Receive a list - */ -void Testservice::receiveList(const QList &list) -{ - qDebug() << "Pid:" << TestserviceTool::getPid() << "Received list:" << list; -} - -/* - * Receive a geo position - */ -void Testservice::receiveGeoPosition(const BlackMisc::Geo::CCoordinateGeodetic &geo) -{ - qDebug() << "Pid:" << TestserviceTool::getPid() << "Received geo data:" << geo; -} - -/* - * Receive transponder - */ -void Testservice::receiveTransponder(const BlackMisc::Aviation::CTransponder &transponder) -{ - qDebug() << "Pid:" << TestserviceTool::getPid() << "Received transponder:" << transponder; -} - -/* - * Receive track - */ -void Testservice::receiveTrack(const BlackMisc::Aviation::CTrack &track) -{ - qDebug() << "Pid:" << TestserviceTool::getPid() << "Received track:" << track; -} - -/* - * Receive a length - */ -void Testservice::receiveLength(const BlackMisc::PhysicalQuantities::CLength &length) -{ - qDebug() << "Pid:" << TestserviceTool::getPid() << "Received length:" << length; -} - -/* - * Receive lengths - */ -void Testservice::receiveLengths(const QVariantList &lengths) -{ - BlackMisc::PhysicalQuantities::CLength l; - foreach(QVariant lv, lengths) { - l = lv.value(); - qDebug() << "Pid:" << TestserviceTool::getPid() << "Received in list:" << l; - } -} - -} // namespace diff --git a/samples/blackmiscquantities_dbus/testservice.h b/samples/blackmiscquantities_dbus/testservice.h deleted file mode 100644 index d9028b6a4..000000000 --- a/samples/blackmiscquantities_dbus/testservice.h +++ /dev/null @@ -1,137 +0,0 @@ -/* Copyright (C) 2013 VATSIM Community / authors - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef BLACKMISCKTEST_TESTSERVICEPQAV_H -#define BLACKMISCKTEST_TESTSERVICEPQAV_H - -// clash with struct interace in objbase.h used to happen -#pragma push_macro("interface") -#undef interface - -#define BLACKMISCKTEST_SERVICENAME "blackmisctest.testservice" -#define BLACKMISCKTEST_SERVICEPATH "/blackbus" - -#include -#include -#include -#include "blackmisc/blackmiscfreefunctions.h" -#include "testservicetool.h" - -namespace BlackMiscTest { - -/*! - * \brief Testservice for PQ DBus tests - */ -class Testservice : public QObject -{ - // http://techbase.kde.org/Development/Tutorials/D-Bus/CustomTypes#Write_a_class - // https://dev.vatsim-germany.org/projects/vatpilotclient/wiki/DBusExample - // http://qt-project.org/doc/qt-4.8/examples-dbus.html - // http://dbus.freedesktop.org/doc/dbus-tutorial.html#meta - - Q_OBJECT - Q_CLASSINFO("D-Bus Interface", BLACKMISCKTEST_SERVICENAME) - - // For some reasons the interface name in the XML is not set correctly - // to the above name - - -signals: - /*! - * \brief Send string message - * \param message - */ - void sendStringMessage(const QString& message); - -public slots: - /*! - * \brief Receive string message - * \param message - */ - void receiveStringMessage(const QString &message); - - /*! - * \brief Receive a QVariant - * \param variant - */ - void receiveVariant(const QDBusVariant &variant); - - /*! - * \brief Receive speed - * \param speed - */ - void receiveSpeed(const BlackMisc::PhysicalQuantities::CSpeed &speed); - - /*! - * \brief Receive com unit - * \param comUnit - */ - void receiveComUnit(const BlackMisc::Aviation::CComSystem &comUnit); - - /*! - * \brief Receive altitude - * \param comUnit - */ - void receiveAltitude(const BlackMisc::Aviation::CAltitude &altitude); - - /*! - * \brief Receive matrix - * \param matrix - */ - void receiveMatrix(const BlackMisc::Math::CMatrix3x3 &matrix); - - /*! - * \brief Receive list - * \param list - */ - void receiveList(const QList &list); - - /*! - * \brief Receive a geo position - * \param geo - */ - void receiveGeoPosition(const BlackMisc::Geo::CCoordinateGeodetic &geo); - - /*! - * \brief Receive transponder - * \param transponder - */ - void receiveTransponder(const BlackMisc::Aviation::CTransponder &transponder); - - /*! - * \brief Receive track - * \param track - */ - void receiveTrack(const BlackMisc::Aviation::CTrack &track); - - /*! - * \brief Receive a length - * \param length - */ - void receiveLength(const BlackMisc::PhysicalQuantities::CLength &length); - - /*! - * \brief Receive lengths - * \param length - */ - void receiveLengths(const QVariantList &lengths); - -public: - static const QString ServiceName; - static const QString ServicePath; - - /*! - * \brief Constructor - * \param parent - */ - explicit Testservice(QObject *parent = 0); - -}; - -} // namespace - -#pragma pop_macro("interface") - -#endif // BLACKMISCKTEST_TESTSERVICEPQAV_H diff --git a/samples/blackmiscquantities_dbus/testservicetool.cpp b/samples/blackmiscquantities_dbus/testservicetool.cpp deleted file mode 100644 index 8c40db048..000000000 --- a/samples/blackmiscquantities_dbus/testservicetool.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "testservicetool.h" - -namespace BlackMiscTest -{ - -/* - * Start a new process - */ -QProcess * TestserviceTool::startNewProcess(const QString &executable, QObject *parent = 0) -{ - QProcess *process = new QProcess(parent); - process->startDetached(executable); - return process; -} - -/* - * Sleep - */ -void TestserviceTool::sleep(qint32 ms) -{ - if (ms < 1) return; - -#ifdef Q_OS_WIN - Sleep(uint(ms)); -#else - struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 }; - nanosleep(&ts, NULL); -#endif - -} - -} // namespace diff --git a/samples/blackmiscquantities_dbus/testservicetool.h b/samples/blackmiscquantities_dbus/testservicetool.h deleted file mode 100644 index 5d5f2a2c4..000000000 --- a/samples/blackmiscquantities_dbus/testservicetool.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef BLACKMISCTEST_TESTSERVICETOOL_H -#define BLACKMISCTEST_TESTSERVICETOOL_H - -#include -#include -#ifdef Q_OS_WIN -// for qdatetime, see here http://qt-project.org/forums/viewthread/22133 -#ifndef NOMINMAX -#define NOMINMAX -#endif -#include // for Sleep -#endif - -namespace BlackMiscTest -{ - -/*! - * \brief Supporting functions for running the tests - */ -class TestserviceTool -{ -private: - /*! - * \brief Constructor - */ - TestserviceTool() {} - -public: - /*! - * \brief Get process id - * \return - */ - static qint64 getPid() { - return QCoreApplication::applicationPid(); - } - - /*! - * \brief Start a new process - * \param executable - * \param parent - * \return - */ - static QProcess *startNewProcess(const QString &executable, QObject *parent); - - /*! - * \brief Own sleep to avoid inlude of QTest - * \param ms - */ - static void sleep(qint32 ms); - -}; - -} // namespace - -#endif // BLACKMISCTEST_TESTSERVICETOOL_H diff --git a/samples/blackmiscvectorgeo/samplesgeo.cpp b/samples/blackmiscvectorgeo/samplesgeo.cpp index 426be5213..1dd42b276 100644 --- a/samples/blackmiscvectorgeo/samplesgeo.cpp +++ b/samples/blackmiscvectorgeo/samplesgeo.cpp @@ -44,6 +44,13 @@ namespace BlackMiscTest // cned += ce2; // must not work + // checked with http://www.movable-type.co.uk/scripts/latlong.html + CCoordinateGeodetic coord1 = CCoordinateGeodetic::fromWgs84("50 03 59N", "005 42 53W"); + CCoordinateGeodetic coord2 = CCoordinateGeodetic::fromWgs84("50 03 59N", "005 42 53W"); + CCoordinateGeodetic coord3 = CCoordinateGeodetic::fromWgs84("58 38 38N", "003 04 12W"); + qDebug() << coord1 << coord2 << greatCircleDistance(coord1, coord2); // should be 0 + qDebug() << coord1 << coord3 << greatCircleDistance(coord1, coord3) << greatCircleDistance(coord1, coord3).switchUnit(CLengthUnit::km()) ; // should be Distance: 968.9 km (to 4 SF*) + // bye qDebug() << "-----------------------------------------------"; return 0; diff --git a/tests/blackcore/test_blackcore.pro b/tests/blackcore/test_blackcore.pro index 2c3fe7dfe..441dc109f 100644 --- a/tests/blackcore/test_blackcore.pro +++ b/tests/blackcore/test_blackcore.pro @@ -1,6 +1,6 @@ include (../../externals.pri) -QT += core testlib dbus +QT += core testlib dbus network TARGET = test_blackcore TEMPLATE = app diff --git a/tests/blackcore/testblackcoremain.cpp b/tests/blackcore/testblackcoremain.cpp index b7c2fdcea..619ca502d 100644 --- a/tests/blackcore/testblackcoremain.cpp +++ b/tests/blackcore/testblackcoremain.cpp @@ -6,7 +6,6 @@ #include "testblackcoremain.h" #include "testinterpolator.h" #include "testnetwork.h" -#include "testnetmediators.h" namespace BlackCoreTest { @@ -25,10 +24,6 @@ int CBlackCoreTestMain::unitMain(int argc, char *argv[]) CTestNetwork networkTests; status |= QTest::qExec(&networkTests, argc, argv); } - { - CTestNetMediators mediatorTests; - status |= QTest::qExec(&mediatorTests, argc, argv); - } return status; } } // namespace diff --git a/tests/blackcore/testblackcoremain.h b/tests/blackcore/testblackcoremain.h index 14858b317..61fa25be4 100644 --- a/tests/blackcore/testblackcoremain.h +++ b/tests/blackcore/testblackcoremain.h @@ -6,6 +6,7 @@ #ifndef BLACKCORETEST_TESTMAIN_H #define BLACKCORETEST_TESTMAIN_H +#include "blackmisc/valueobject.h" // for qHash overload, include before Qt stuff due GCC issue #include namespace BlackCoreTest diff --git a/tests/blackcore/testnetwork.cpp b/tests/blackcore/testnetwork.cpp index 944909589..7e1dceab7 100644 --- a/tests/blackcore/testnetwork.cpp +++ b/tests/blackcore/testnetwork.cpp @@ -8,29 +8,30 @@ using namespace BlackCore; using namespace BlackMisc; +using namespace BlackMisc::Aviation; +using namespace BlackMisc::Network; +using namespace BlackMisc::Geo; +using namespace BlackMisc::PhysicalQuantities; -void BlackCoreTest::CTestNetwork::networkTest(BlackCore::INetwork* net) +void BlackCoreTest::CTestNetwork::networkTest(BlackCore::INetwork *net) { Expect e(net); - QString callsign = "TEST01"; EXPECT_UNIT(e) - .send(&INetwork::setServerDetails, "vatsim-germany.org", 6809) - .send(&INetwork::setUserCredentials, "guest", "guest") - .send(&INetwork::setRealName, "Pilot Client Tester") - .send(&INetwork::setCallsign, callsign) + .send(&INetwork::setServer, CServer("", "", "vatsim-germany.org", 6809, CUser("guest", "", "", "guest"))) + .send(&INetwork::setCallsign, "BLACK") .send(&INetwork::initiateConnection) - .expect(&INetwork::connectionStatusConnecting, []{ qDebug() << "CONNECTING"; }) - .expect(&INetwork::connectionStatusConnected, []{ qDebug() << "CONNECTED"; }) + .expect(&INetwork::connectionStatusConnecting, [] { qDebug() << "CONNECTING"; }) + .expect(&INetwork::connectionStatusConnected, [] { qDebug() << "CONNECTED"; }) .wait(10); EXPECT_UNIT(e) .send(&INetwork::ping, "server") - .expect(&INetwork::pong, [](QString s, PhysicalQuantities::CTime t){ qDebug() << "PONG" << s << t; }) + .expect(&INetwork::pong, [](CCallsign callsign, PhysicalQuantities::CTime elapsedTime) { qDebug() << "PONG" << callsign << elapsedTime; }) .wait(10); EXPECT_UNIT(e) .send(&INetwork::terminateConnection) - .expect(&INetwork::connectionStatusDisconnected, []{ qDebug() << "DISCONNECTED"; }) + .expect(&INetwork::connectionStatusDisconnected, [] { qDebug() << "DISCONNECTED"; }) .wait(10); -} \ No newline at end of file +} diff --git a/tests/blackmisc/testaviation.cpp b/tests/blackmisc/testaviation.cpp index f7d4bd3f6..533590bbc 100644 --- a/tests/blackmisc/testaviation.cpp +++ b/tests/blackmisc/testaviation.cpp @@ -4,9 +4,23 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "testaviation.h" +#include "blackmisc/pqconstants.h" +#include "blackmisc/avheading.h" +#include "blackmisc/avinformationmessage.h" +#include "blackmisc/avaircraftsituation.h" +#include "blackmisc/avaircrafticao.h" +#include "blackmisc/avcallsign.h" +#include "blackmisc/aviocomsystem.h" +#include "blackmisc/avionavsystem.h" +#include "blackmisc/aviotransponder.h" +#include "blackmisc/avatcstation.h" +#include "blackmisc/nwuser.h" +#include "blackmisc/nwserver.h" using namespace BlackMisc::Aviation; using namespace BlackMisc::PhysicalQuantities; +using namespace BlackMisc::Network; +using namespace BlackMisc::Geo; namespace BlackMiscTest { @@ -79,4 +93,57 @@ namespace BlackMiscTest } + /* + * Callsign + */ + void CTestAviation::callsign() + { + CCallsign cs1("EDDm_twr"); + CCallsign cs2("EDDmtwr"); + CCallsign cs3("EDDmapp"); + QVERIFY2(cs1 == cs2, "Callsigns shall be equal"); + QVERIFY2(cs1 != cs3, "Callsigns shall not be equal"); + } + + /* + * Copy and compare + */ + void CTestAviation::copyAndEqual() + { + CFrequency f1(123.45, CFrequencyUnit::MHz()); + CFrequency f2(f1); + QVERIFY2(f1 == f2, "frequencies shall be equal"); + + CCallsign c1("EABCD"); + CCallsign c2(c1); + QVERIFY2(c1 == c2, "callsigns shall be equal"); + + CInformationMessage im1(CInformationMessage::METAR, "I am a metar"); + CInformationMessage im2(im1); + QVERIFY2(im1 == im2, "information shall be equal"); + + CUser user1("112233dd", "Joe", "", "secret"); + CUser user2(user1); + QVERIFY2(user1 == user2, "information shall be equal"); + + CServer server1("development", "VATSIM dev.server", "vatsim-germany.org", 6809, user1); + CServer server2(server1); + QVERIFY2(server1 == server2, "server shall be equal"); + + CAircraftSituation situation1( + CCoordinateGeodetic( + CLatitude::fromWgs84("N 049° 18' 17"), + CLongitude::fromWgs84("E 008° 27' 05"), + CLength(0, CLengthUnit::m())), + CAltitude(312, CAltitude::MeanSeaLevel, CLengthUnit::ft()) + ); + CAircraftSituation situation2(situation1); + QVERIFY2(situation1 == situation2, "situations shall be equal"); + + CAircraftIcao icao1(CAircraftIcao("C172", "L1P", "GA", "GA", "0000ff")); + CAircraftIcao icao2(icao1); + QVERIFY2(icao1 == icao2, "ICAOs shall be equal"); + + } + } // namespace diff --git a/tests/blackmisc/testaviation.h b/tests/blackmisc/testaviation.h index 2736b558f..37e7e19d9 100644 --- a/tests/blackmisc/testaviation.h +++ b/tests/blackmisc/testaviation.h @@ -6,11 +6,6 @@ #ifndef BLACKMISCTEST_TESTAVIATIONBASE_H #define BLACKMISCTEST_TESTAVIATIONBASE_H -#include "blackmisc/pqconstants.h" -#include "blackmisc/avheading.h" -#include "blackmisc/aviocomsystem.h" -#include "blackmisc/avionavsystem.h" -#include "blackmisc/aviotransponder.h" #include namespace BlackMiscTest @@ -28,7 +23,7 @@ namespace BlackMiscTest * \brief Standard test case constructor * \param parent */ - explicit CTestAviation(QObject *parent = 0); + explicit CTestAviation(QObject *parent = nullptr); private slots: /*! @@ -45,6 +40,16 @@ namespace BlackMiscTest */ void transponder(); + /*! + * \brief Callsigns + */ + void callsign(); + + /*! + * \brief Testing copying and equality of objects + */ + void copyAndEqual(); + }; } // namespace diff --git a/tests/blackmisc/testblackmiscmain.cpp b/tests/blackmisc/testblackmiscmain.cpp index 5d0be957b..fe805b2ab 100644 --- a/tests/blackmisc/testblackmiscmain.cpp +++ b/tests/blackmisc/testblackmiscmain.cpp @@ -3,7 +3,12 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "testphysicalquantities.h" +#include "testaviation.h" +#include "testvectormatrix.h" +#include "testgeo.h" #include "testcontainers.h" +#include "testvariantandmap.h" #include "testblackmiscmain.h" namespace BlackMiscTest @@ -20,11 +25,13 @@ namespace BlackMiscTest CTestVectorMatrix vmTests; CTestGeo geoTests; CTestContainers containerTests; + CTestVariantAndValueMap variantAndValueMap; status |= QTest::qExec(&pqBaseTests, argc, argv); status |= QTest::qExec(&avBaseTests, argc, argv); status |= QTest::qExec(&vmTests, argc, argv); status |= QTest::qExec(&geoTests, argc, argv); status |= QTest::qExec(&containerTests, argc, argv); + status |= QTest::qExec(&variantAndValueMap, argc, argv); } return status; diff --git a/tests/blackmisc/testblackmiscmain.h b/tests/blackmisc/testblackmiscmain.h index 38a829db9..8955ccdd7 100644 --- a/tests/blackmisc/testblackmiscmain.h +++ b/tests/blackmisc/testblackmiscmain.h @@ -6,10 +6,6 @@ #ifndef BLACKMISCTEST_TESTMAIN_H #define BLACKMISCTEST_TESTMAIN_H -#include "testphysicalquantities.h" -#include "testaviation.h" -#include "testvectormatrix.h" -#include "testgeo.h" #include namespace BlackMiscTest diff --git a/tests/blackmisc/testphysicalquantities.cpp b/tests/blackmisc/testphysicalquantities.cpp index d4f54c794..3c285ab4e 100644 --- a/tests/blackmisc/testphysicalquantities.cpp +++ b/tests/blackmisc/testphysicalquantities.cpp @@ -6,210 +6,211 @@ #include "testphysicalquantities.h" using namespace BlackMisc::PhysicalQuantities; +using namespace BlackMisc::Math; namespace BlackMiscTest { -/* - * Basic unit tests for physical units - */ -void CTestPhysicalQuantities::unitsBasics() -{ - // some tests on units - CLengthUnit du1 = CLengthUnit::m(); // Copy - CLengthUnit du2 = CLengthUnit::m(); // Copy - QVERIFY2(du1 == du2, "Compare by value 1"); - du1 = CLengthUnit::m(); // Copy - du2 = CLengthUnit::m(); // Copy - QVERIFY2(du1 == du2, "Compare by value 2"); - QVERIFY2(CLengthUnit::m() == CLengthUnit::m(), "Compare by value"); + /* + * Basic unit tests for physical units + */ + void CTestPhysicalQuantities::unitsBasics() + { + // some tests on units + CLengthUnit du1 = CLengthUnit::m(); // Copy + CLengthUnit du2 = CLengthUnit::m(); // Copy + QVERIFY2(du1 == du2, "Compare by value 1"); + du1 = CLengthUnit::m(); // Copy + du2 = CLengthUnit::m(); // Copy + QVERIFY2(du1 == du2, "Compare by value 2"); + QVERIFY2(CLengthUnit::m() == CLengthUnit::m(), "Compare by value"); - CFrequencyUnit fu1 = CFrequencyUnit::Hz(); - QVERIFY2(fu1 != du1, "Hz must not be meter"); -} + CFrequencyUnit fu1 = CFrequencyUnit::Hz(); + QVERIFY2(fu1 != du1, "Hz must not be meter"); + } -/* - * Distance tests - */ -void CTestPhysicalQuantities::lengthBasics() -{ - CLength d1(1, CLengthUnit::m()); // 1m - CLength d2(100, CLengthUnit::cm()); - CLength d3(1.852 * 1000, CLengthUnit::m()); // 1852m - CLength d4(1, CLengthUnit::NM()); - QVERIFY2(d1 == d2, "1meter shall be 100cm"); - QVERIFY2(d3 == d4, "1852meters shall be 1NM"); - QVERIFY2(d1 * 2 == 2 * d1, "Commutative multiplication"); + /* + * Distance tests + */ + void CTestPhysicalQuantities::lengthBasics() + { + CLength d1(1, CLengthUnit::m()); // 1m + CLength d2(100, CLengthUnit::cm()); + CLength d3(1.852 * 1000, CLengthUnit::m()); // 1852m + CLength d4(1, CLengthUnit::NM()); + QVERIFY2(d1 == d2, "1meter shall be 100cm"); + QVERIFY2(d3 == d4, "1852meters shall be 1NM"); + QVERIFY2(d1 * 2 == 2 * d1, "Commutative multiplication"); - d3 *= 2; // SI value - d4 *= 2.0; // SI value ! - QVERIFY2(d3 == d4, "2*1852meters shall be 2NM"); + d3 *= 2; // SI value + d4 *= 2.0; // SI value ! + QVERIFY2(d3 == d4, "2*1852meters shall be 2NM"); - // less / greater - QVERIFY2(!(d1 < d2), "Nothing shall be less / greater"); - QVERIFY2(!(d1 > d2), "Nothing shall be less / greater"); + // less / greater + QVERIFY2(!(d1 < d2), "Nothing shall be less / greater"); + QVERIFY2(!(d1 > d2), "Nothing shall be less / greater"); - // epsilon tests - d1 = d2; // both in same unit - d1.addValueSameUnit(d1.getUnit().getEpsilon() / 2.0); // this should be still the same - QVERIFY2(d1 == d2, "Epsilon: 100cm + epsilon shall be 100cm"); - QVERIFY2(!(d1 != d2), "Epsilon: 100cm + epsilon shall be still 100cm"); - QVERIFY2(!(d1 > d2), "d1 shall not be greater"); + // epsilon tests + d1 = d2; // both in same unit + d1.addValueSameUnit(d1.getUnit().getEpsilon() / 2.0); // this should be still the same + QVERIFY2(d1 == d2, "Epsilon: 100cm + epsilon shall be 100cm"); + QVERIFY2(!(d1 != d2), "Epsilon: 100cm + epsilon shall be still 100cm"); + QVERIFY2(!(d1 > d2), "d1 shall not be greater"); - d1.addValueSameUnit(d1.getUnit().getEpsilon()); // now over epsilon threshold - QVERIFY2(d1 != d2, "Epsilon exceeded: 100 cm + 2 epsilon shall not be 100cm"); - QVERIFY2(d1 > d2, "d1 shall be greater"); -} + d1.addValueSameUnit(d1.getUnit().getEpsilon()); // now over epsilon threshold + QVERIFY2(d1 != d2, "Epsilon exceeded: 100 cm + 2 epsilon shall not be 100cm"); + QVERIFY2(d1 > d2, "d1 shall be greater"); + } -/* - * Unit tests for speed - */ -void CTestPhysicalQuantities::speedBasics() -{ - CSpeed s1(100, CSpeedUnit::km_h()); - CSpeed s2(1000, CSpeedUnit::ft_min()); - QVERIFY2(s1.valueRounded(CSpeedUnit::NM_h(), 0) == 54, qPrintable(QString("100km/h is not %1 NM/h").arg(s1.valueRounded(CSpeedUnit::NM_h(), 0)))); - QVERIFY2(s2.valueRounded(CSpeedUnit::m_s(), 1) == 5.1, qPrintable(QString("1000ft/min is not %1 m/s").arg(s2.valueRounded(CSpeedUnit::m_s(), 1)))); -} + /* + * Unit tests for speed + */ + void CTestPhysicalQuantities::speedBasics() + { + CSpeed s1(100, CSpeedUnit::km_h()); + CSpeed s2(1000, CSpeedUnit::ft_min()); + QVERIFY2(s1.valueRounded(CSpeedUnit::NM_h(), 0) == 54, qPrintable(QString("100km/h is not %1 NM/h").arg(s1.valueRounded(CSpeedUnit::NM_h(), 0)))); + QVERIFY2(s2.valueRounded(CSpeedUnit::m_s(), 1) == 5.1, qPrintable(QString("1000ft/min is not %1 m/s").arg(s2.valueRounded(CSpeedUnit::m_s(), 1)))); + } -/* - * Frequency unit tests - */ -void CTestPhysicalQuantities::frequencyTests() -{ - CFrequency f1(1, CFrequencyUnit::MHz()); - QVERIFY2(f1.valueRounded(CFrequencyUnit::kHz(), 2) == 1000, "Mega is 1000kHz"); - QVERIFY2(f1.value() == 1 , "1MHz"); - QVERIFY2(f1.value(CFrequencyUnit::defaultUnit()) == 1000000 , "1E6 Hz"); - CFrequency f2(1e+6, CFrequencyUnit::Hz()) ; // 1 Megahertz - QVERIFY2(f1 == f2 , "MHz is 1E6 Hz"); -} + /* + * Frequency unit tests + */ + void CTestPhysicalQuantities::frequencyTests() + { + CFrequency f1(1, CFrequencyUnit::MHz()); + QVERIFY2(f1.valueRounded(CFrequencyUnit::kHz(), 2) == 1000, "Mega is 1000kHz"); + QVERIFY2(f1.value() == 1 , "1MHz"); + QVERIFY2(f1.value(CFrequencyUnit::defaultUnit()) == 1000000 , "1E6 Hz"); + CFrequency f2(1e+6, CFrequencyUnit::Hz()) ; // 1 Megahertz + QVERIFY2(f1 == f2 , "MHz is 1E6 Hz"); + } -/* - * Angle tests - */ -void CTestPhysicalQuantities::angleTests() -{ - CAngle a1(180, CAngleUnit::deg()); - CAngle a2(1.5 * CAngle::PI(), CAngleUnit::rad()); - CAngle a3(35.4336, CAngleUnit::sexagesimalDeg()); // 35.72666 - CAngle a4(35.436, CAngleUnit::sexagesimalDegMin()); // 35.72666 - CAngle a5(-60.3015, CAngleUnit::sexagesimalDeg()); // negative angles = west longitude or south latitude - a2.switchUnit(CAngleUnit::deg()); - QVERIFY2(a1.piFactor() == 1, qPrintable(QString("Pi should be 1PI, not %1").arg(a1.piFactor()))); - QVERIFY2(a3.valueRounded(CAngleUnit::deg()) == 35.73, "Expecting 35.73"); - QVERIFY2(a4.valueRounded(CAngleUnit::deg()) == 35.73, "Expecting 35.73"); - QVERIFY2(a5.valueRounded(CAngleUnit::deg(), 4) == -60.5042, "Expecting -60.5042"); -} + /* + * Angle tests + */ + void CTestPhysicalQuantities::angleTests() + { + CAngle a1(180, CAngleUnit::deg()); + CAngle a2(1.5 * CAngle::PI(), CAngleUnit::rad()); + CAngle a3(35.4336, CAngleUnit::sexagesimalDeg()); // 35.72666 + CAngle a4(35.436, CAngleUnit::sexagesimalDegMin()); // 35.72666 + CAngle a5(-60.3015, CAngleUnit::sexagesimalDeg()); // negative angles = west longitude or south latitude + a2.switchUnit(CAngleUnit::deg()); + QVERIFY2(a1.piFactor() == 1, qPrintable(QString("Pi should be 1PI, not %1").arg(a1.piFactor()))); + QVERIFY2(a3.valueRounded(CAngleUnit::deg()) == 35.73, "Expecting 35.73"); + QVERIFY2(a4.valueRounded(CAngleUnit::deg()) == 35.73, "Expecting 35.73"); + QVERIFY2(a5.valueRounded(CAngleUnit::deg(), 4) == -60.5042, "Expecting -60.5042"); + } -/* - * Weight tests - */ -void CTestPhysicalQuantities::massTests() -{ - CMass w1(1000, CMassUnit::kg()); - CMass w2(w1.value(), CMassUnit::kg()); - w2.switchUnit(CMassUnit::tonne()); - QVERIFY2(w2.value() == 1, "1tonne shall be 1000kg"); - w2.switchUnit(CMassUnit::lb()); - QVERIFY2(w2.valueRounded(2) == 2204.62, "1tonne shall be 2204pounds"); - QVERIFY2(w1 == w2, "Masses shall be equal"); -} + /* + * Weight tests + */ + void CTestPhysicalQuantities::massTests() + { + CMass w1(1000, CMassUnit::kg()); + CMass w2(w1.value(), CMassUnit::kg()); + w2.switchUnit(CMassUnit::tonne()); + QVERIFY2(w2.value() == 1, "1tonne shall be 1000kg"); + w2.switchUnit(CMassUnit::lb()); + QVERIFY2(w2.valueRounded(2) == 2204.62, "1tonne shall be 2204pounds"); + QVERIFY2(w1 == w2, "Masses shall be equal"); + } -/* - * Pressure tests - */ -void CTestPhysicalQuantities::pressureTests() -{ - CPressure p1(1013.25, CPressureUnit::hPa()); - CPressure p2(29.92, CPressureUnit::inHg()); - CPressure p4(p1); - p4.switchUnit(CPressureUnit::mbar()); + /* + * Pressure tests + */ + void CTestPhysicalQuantities::pressureTests() + { + CPressure p1(1013.25, CPressureUnit::hPa()); + CPressure p2(29.92, CPressureUnit::inHg()); + CPressure p4(p1); + p4.switchUnit(CPressureUnit::mbar()); - // does not match exactly - QVERIFY2(p1 != p2, "Standard pressure test little difference"); - QVERIFY2(p1.value() == p4.value(), "mbar/hPa test"); -} + // does not match exactly + QVERIFY2(p1 != p2, "Standard pressure test little difference"); + QVERIFY2(p1.value() == p4.value(), "mbar/hPa test"); + } -/* - * Temperature tests - */ -void CTestPhysicalQuantities::temperatureTests() -{ - CTemperature t1(0, CTemperatureUnit::C()); // 0C - CTemperature t2(1, CTemperatureUnit::F()); // 1F - CTemperature t3(220.15, CTemperatureUnit::F()); - CTemperature t4(10, CTemperatureUnit::F()); - QVERIFY2(t1.valueRounded(CTemperatureUnit::K()) == 273.15, qPrintable(QString("0C shall be 273.15K, not %1 K").arg(t1.valueRounded(CTemperatureUnit::K())))); - QVERIFY2(t2.valueRounded(CTemperatureUnit::C()) == -17.22, qPrintable(QString("1F shall be -17.22C, not %1 C").arg(t2.valueRounded(CTemperatureUnit::C())))); - QVERIFY2(t3.valueRounded(CTemperatureUnit::C()) == 104.53, qPrintable(QString("220.15F shall be 104.53C, not %1 C").arg(t3.valueRounded(CTemperatureUnit::C())))); - QVERIFY2(t4.valueRounded(CTemperatureUnit::K()) == 260.93, qPrintable(QString("10F shall be 260.93K, not %1 K").arg(t4.valueRounded(CTemperatureUnit::K())))); -} + /* + * Temperature tests + */ + void CTestPhysicalQuantities::temperatureTests() + { + CTemperature t1(0, CTemperatureUnit::C()); // 0C + CTemperature t2(1, CTemperatureUnit::F()); // 1F + CTemperature t3(220.15, CTemperatureUnit::F()); + CTemperature t4(10, CTemperatureUnit::F()); + QVERIFY2(t1.valueRounded(CTemperatureUnit::K()) == 273.15, qPrintable(QString("0C shall be 273.15K, not %1 K").arg(t1.valueRounded(CTemperatureUnit::K())))); + QVERIFY2(t2.valueRounded(CTemperatureUnit::C()) == -17.22, qPrintable(QString("1F shall be -17.22C, not %1 C").arg(t2.valueRounded(CTemperatureUnit::C())))); + QVERIFY2(t3.valueRounded(CTemperatureUnit::C()) == 104.53, qPrintable(QString("220.15F shall be 104.53C, not %1 C").arg(t3.valueRounded(CTemperatureUnit::C())))); + QVERIFY2(t4.valueRounded(CTemperatureUnit::K()) == 260.93, qPrintable(QString("10F shall be 260.93K, not %1 K").arg(t4.valueRounded(CTemperatureUnit::K())))); + } -/* - * Time tests - */ -void CTestPhysicalQuantities::timeTests() -{ - CTime t1(1, CTimeUnit::h()); - CTime t2(1.5, CTimeUnit::h()); - CTime t3(1.25, CTimeUnit::min()); - CTime t4(1.0101, CTimeUnit::hms()); - QVERIFY2(t1.value(CTimeUnit::defaultUnit()) == 3600, "1hour shall be 3600s"); - QVERIFY2(t2.value(CTimeUnit::hrmin()) == 1.30, "1.5hour shall be 1h30m"); - QVERIFY2(t3.value(CTimeUnit::minsec()) == 1.15, "1.25min shall be 1m15s"); - QVERIFY2(t4.value(CTimeUnit::s()) == 3661, "1h01m01s shall be 3661s"); -} + /* + * Time tests + */ + void CTestPhysicalQuantities::timeTests() + { + CTime t1(1, CTimeUnit::h()); + CTime t2(1.5, CTimeUnit::h()); + CTime t3(1.25, CTimeUnit::min()); + CTime t4(1.0101, CTimeUnit::hms()); + QVERIFY2(CMath::epsilonEqual(t1.value(CTimeUnit::defaultUnit()), 3600), "1hour shall be 3600s"); + QVERIFY2(CMath::epsilonEqual(t2.value(CTimeUnit::hrmin()), 1.3), "1.5hour shall be 1h30m"); + QVERIFY2(CMath::epsilonEqual(t3.value(CTimeUnit::minsec()), 1.15), "1.25min shall be 1m15s"); + QVERIFY2(CMath::epsilonEqual(t4.value(CTimeUnit::s()), 3661), "1h01m01s shall be 3661s"); + } -/* - * Test acceleration - */ -void CTestPhysicalQuantities::accelerationTests() -{ - CLength oneMeter(1, CLengthUnit::m()); - double ftFactor = oneMeter.switchUnit(CLengthUnit::ft()).value(); + /* + * Test acceleration + */ + void CTestPhysicalQuantities::accelerationTests() + { + CLength oneMeter(1, CLengthUnit::m()); + double ftFactor = oneMeter.switchUnit(CLengthUnit::ft()).value(); - CAcceleration a1(10.0, CAccelerationUnit::m_s2()); - CAcceleration a2(a1); - a1.switchUnit(CAccelerationUnit::ft_s2()); - QVERIFY2(a1 == a2, "Accelerations should be similar"); - QVERIFY2(BlackMisc::Math::CMath::round(a2.value() * ftFactor, 6) == a1.valueRounded(6), - "Numerical values should be equal"); -} + CAcceleration a1(10.0, CAccelerationUnit::m_s2()); + CAcceleration a2(a1); + a1.switchUnit(CAccelerationUnit::ft_s2()); + QVERIFY2(a1 == a2, "Accelerations should be similar"); + QVERIFY2(BlackMisc::Math::CMath::round(a2.value() * ftFactor, 6) == a1.valueRounded(6), + "Numerical values should be equal"); + } -/* - * Just testing obvious memory create / destruct flaws - */ -void CTestPhysicalQuantities::memoryTests() -{ - CLength *c = new CLength(100, CLengthUnit::m()); - c->switchUnit(CLengthUnit::NM()); - QVERIFY2(c->getUnit() == CLengthUnit::NM() && CLengthUnit::defaultUnit() == CLengthUnit::m(), - "Testing distance units failed"); - delete c; + /* + * Just testing obvious memory create / destruct flaws + */ + void CTestPhysicalQuantities::memoryTests() + { + CLength *c = new CLength(100, CLengthUnit::m()); + c->switchUnit(CLengthUnit::NM()); + QVERIFY2(c->getUnit() == CLengthUnit::NM() && CLengthUnit::defaultUnit() == CLengthUnit::m(), + "Testing distance units failed"); + delete c; - CAngle *a = new CAngle(100, CAngleUnit::rad()); - a->switchUnit(CAngleUnit::deg()); - QVERIFY2(a->getUnit() == CAngleUnit::deg() && CAngleUnit::defaultUnit() == CAngleUnit::deg(), - "Testing angle units failed"); - delete a; -} + CAngle *a = new CAngle(100, CAngleUnit::rad()); + a->switchUnit(CAngleUnit::deg()); + QVERIFY2(a->getUnit() == CAngleUnit::deg() && CAngleUnit::defaultUnit() == CAngleUnit::deg(), + "Testing angle units failed"); + delete a; + } -/* - * Some very basic arithmetic tests on the PQs - */ -void CTestPhysicalQuantities::basicArithmetic() -{ - CPressure p1 = CPhysicalQuantitiesConstants::ISASeaLevelPressure(); - CPressure p2(p1); - p2 *= 2.0; - CPressure p3 = p1 + p1; - QVERIFY2(p3 == p2, "Pressure needs to be the same (2times)"); - p3 /= 2.0; - QVERIFY2(p3 == p1, "Pressure needs to be the same (1time)"); - p3 = p3 - p3; - QVERIFY2(p3.value() == 0, "Value needs to be zero"); - p3 = CPressure(1013, CPressureUnit::hPa()); - QVERIFY2(p3 * 1.5 == 1.5 * p3, "Basic commutative test on PQ failed"); -} + /* + * Some very basic arithmetic tests on the PQs + */ + void CTestPhysicalQuantities::basicArithmetic() + { + CPressure p1 = CPhysicalQuantitiesConstants::ISASeaLevelPressure(); + CPressure p2(p1); + p2 *= 2.0; + CPressure p3 = p1 + p1; + QVERIFY2(p3 == p2, "Pressure needs to be the same (2times)"); + p3 /= 2.0; + QVERIFY2(p3 == p1, "Pressure needs to be the same (1time)"); + p3 = p3 - p3; + QVERIFY2(p3.value() == 0, "Value needs to be zero"); + p3 = CPressure(1013, CPressureUnit::hPa()); + QVERIFY2(p3 * 1.5 == 1.5 * p3, "Basic commutative test on PQ failed"); + } } // namespace diff --git a/tests/blackmisc/testvariantandmap.cpp b/tests/blackmisc/testvariantandmap.cpp new file mode 100644 index 000000000..44e49c6c5 --- /dev/null +++ b/tests/blackmisc/testvariantandmap.cpp @@ -0,0 +1,78 @@ +/* Copyright (C) 2013 VATSIM Community / contributors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "blackmisc/avatcstation.h" +#include "testvariantandmap.h" +#include +#include +#include + +using namespace BlackMisc; +using namespace BlackMisc::Aviation; +using namespace BlackMisc::PhysicalQuantities; +using namespace BlackMisc::Geo; +using namespace BlackMisc::Network; + +namespace BlackMiscTest +{ + /* + * Variant tests + */ + void CTestVariantAndValueMap::variant() + { + // ATC station + QDateTime dtFrom = QDateTime::currentDateTimeUtc(); + QDateTime dtUntil = dtFrom.addSecs(60 * 60.0); // 1 hour + QDateTime dtFrom2 = dtUntil; + QDateTime dtUntil2 = dtUntil.addSecs(60 * 60.0); + CCoordinateGeodetic geoPos = + CCoordinateGeodetic::fromWgs84("48° 21′ 13″ N", "11° 47′ 09″ E", CLength(1487, CLengthUnit::ft())); + CAtcStation station1(CCallsign("eddm_twr"), CUser("123456", "Joe Doe"), + CFrequency(118.7, CFrequencyUnit::MHz()), + geoPos, CLength(50, CLengthUnit::km()), false, dtFrom, dtUntil); + CAtcStation station2(station1); + CAtcStation station3(CCallsign("eddm_app"), CUser("654321", "Jen Doe"), + CFrequency(120.7, CFrequencyUnit::MHz()), + geoPos, CLength(100, CLengthUnit::km()), false, dtFrom2, dtUntil2); + + // compare + QVariant station1qv = QVariant::fromValue(station1); + QVERIFY2(station1 == station1, "Station should be equal"); + QVERIFY2(station1 == station2, "Station should be equal"); + QVERIFY2(station1 != station3, "Station should not be equal"); + QVERIFY2(station1qv == station1, "Station should be equal (QVariant)"); + QVERIFY2(station1 == station1qv, "Station should be equal (QVariant)"); + QVERIFY2(station2 == station1qv, "Station should be equal (QVariant)"); + QVERIFY2(station3 != station1qv, "Station should be equal (QVariant)"); + } + + /* + * Value map tests + */ + void CTestVariantAndValueMap::valueMap() + { + // ATC station + QDateTime dtFrom = QDateTime::currentDateTimeUtc(); + QDateTime dtUntil = dtFrom.addSecs(60 * 60.0); // 1 hour + CCoordinateGeodetic geoPos = + CCoordinateGeodetic::fromWgs84("48° 21′ 13″ N", "11° 47′ 09″ E", CLength(1487, CLengthUnit::ft())); + CAtcStation station1(CCallsign("eddm_twr"), CUser("123456", "Joe Doe"), + CFrequency(118.7, CFrequencyUnit::MHz()), + geoPos, CLength(50, CLengthUnit::km()), false, dtFrom, dtUntil); + + // value maps + CValueMap vmWildcard(true); + CValueMap vmNoWildcard(false); + CValueMap vm; + vm.addValue(CAtcStation::IndexController, CUser("123456", "Joe Doe")); + + // compare + QVERIFY2(vmWildcard == station1, "Station should be equal to wildcard"); + QVERIFY2(station1 != vmNoWildcard, "Station should not be equal to empty list"); + QVERIFY2(station1 == vm, "Controller should match"); + + } + +} //namespace BlackMiscTest diff --git a/tests/blackmisc/testvariantandmap.h b/tests/blackmisc/testvariantandmap.h new file mode 100644 index 000000000..05a6aa277 --- /dev/null +++ b/tests/blackmisc/testvariantandmap.h @@ -0,0 +1,44 @@ +/* Copyright (C) 2013 VATSIM Community / contributors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef BLACKMISCTEST_TESTVARIANTANDVALUEMAP_H +#define BLACKMISCTEST_TESTVARIANTANDVALUEMAP_H + +#include "blackmisc/pqconstants.h" +#include "blackmisc/avatcstation.h" +#include + +namespace BlackMiscTest +{ + + /*! + * \brief Aviation classes basic tests + */ + class CTestVariantAndValueMap : public QObject + { + Q_OBJECT + + public: + /*! + * \brief Standard test case constructor + * \param parent + */ + explicit CTestVariantAndValueMap(QObject *parent = 0) : QObject(parent) {} + + private slots: + /*! + * \brief Basic unit tests for value objects and variants + */ + void variant(); + /*! + * \brief Unit tests for value maps and value objects + */ + void valueMap(); + + }; + +} // namespace + +#endif // guard diff --git a/tests/blackmisc/testvectormatrix.cpp b/tests/blackmisc/testvectormatrix.cpp index 29a45e9b6..e40134522 100644 --- a/tests/blackmisc/testvectormatrix.cpp +++ b/tests/blackmisc/testvectormatrix.cpp @@ -10,72 +10,72 @@ using namespace BlackMisc::Math; namespace BlackMiscTest { -/* - * Basic tests vector - */ -void CTestVectorMatrix::vectorBasics() -{ - CVector3D v1(1); - v1 *= 2.0; - CVector3D v2(2); - QVERIFY2(v1 == v2, "Vectors should be equal"); - QVERIFY2(v1 * 2 == 2 * v2, "Commutative vector multiplication failed"); - CVector3D v3(1, 1, 1); - CVector3D v4(2, 2, 2); - CVector3D v5 = v3.crossProduct(v4); - QVERIFY2(v5.isZeroEpsilon(), "Cross product shall be {0, 0, 0}"); - CVector3D v6(1, 2, 3); - CVector3D v7(3, 4, 5); - QVERIFY2(v6.crossProduct(v7) == CVector3D(-2, 4, -2), "Cross product is wrong"); - QVERIFY2(v6.dotProduct(v7) == 26, "Dot product is wrong, 26 expected"); - QVERIFY2(v6.length() == sqrt(1.0 + 4.0 + 9.0), "Wrong vector magnitude"); -} + /* + * Basic tests vector + */ + void CTestVectorMatrix::vectorBasics() + { + CVector3D v1(1); + v1 *= 2.0; + CVector3D v2(2); + QVERIFY2(v1 == v2, "Vectors should be equal"); + QVERIFY2(v1 * 2 == 2 * v2, "Commutative vector multiplication failed"); + CVector3D v3(1, 1, 1); + CVector3D v4(2, 2, 2); + CVector3D v5 = v3.crossProduct(v4); + QVERIFY2(v5.isZeroEpsilon(), "Cross product shall be {0, 0, 0}"); + CVector3D v6(1, 2, 3); + CVector3D v7(3, 4, 5); + QVERIFY2(v6.crossProduct(v7) == CVector3D(-2, 4, -2), "Cross product is wrong"); + QVERIFY2(CMath::epsilonEqual(v6.dotProduct(v7), 26), "Dot product is wrong, 26 expected"); + QVERIFY2(CMath::epsilonEqual(v6.length(), sqrt(1.0 + 4.0 + 9.0)), "Wrong vector magnitude"); + } -/* - * Matrix tests - * http://www.bluebit.gr/matrix-calculator/ - */ -void CTestVectorMatrix::matrixBasics() -{ - CMatrix3x3 m1; - CMatrix3x3 m2 = m1 - m1; - QVERIFY2(m1.isIdentity(), "Default matrix should be identity"); - QVERIFY2(m2.isZero(), "Matrix should be zero"); + /* + * Matrix tests + * http://www.bluebit.gr/matrix-calculator/ + */ + void CTestVectorMatrix::matrixBasics() + { + CMatrix3x3 m1; + CMatrix3x3 m2 = m1 - m1; + QVERIFY2(m1.isIdentity(), "Default matrix should be identity"); + QVERIFY2(m2.isZero(), "Matrix should be zero"); - bool invertible; - CMatrix3x3 mr; - CMatrix3x3 msame(3.0); - mr = msame.inverse(invertible); - QVERIFY2(!invertible, "Matrix with sigular values cannot be inverted"); + bool invertible; + CMatrix3x3 mr; + CMatrix3x3 msame(3.0); + mr = msame.inverse(invertible); + QVERIFY2(!invertible, "Matrix with sigular values cannot be inverted"); - mr.setToIdentity(); - QVERIFY2(mr.determinant() == 1, "Identity matrix should have determinant 1"); - mr = mr.inverse(invertible); - QVERIFY2(invertible && mr.isIdentity() == 1, "Identity matrix should have inverse identity"); + mr.setToIdentity(); + QVERIFY2(mr.determinant() == 1, "Identity matrix should have determinant 1"); + mr = mr.inverse(invertible); + QVERIFY2(invertible && mr.isIdentity() == 1, "Identity matrix should have inverse identity"); - m1.setToIdentity(); - m2 = m1 + m1; - m1 = m1 * 2.0; - QVERIFY2(m1 == m2, "2* Identity should be Identity + Identity"); - QVERIFY2(m1 * 2 == 2 * m1, "Commutative matrix multiplication failed"); + m1.setToIdentity(); + m2 = m1 + m1; + m1 = m1 * 2.0; + QVERIFY2(m1 == m2, "2* Identity should be Identity + Identity"); + QVERIFY2(m1 * 2 == 2 * m1, "Commutative matrix multiplication failed"); - m1 /= 2.0; - m2 -= m1; - QVERIFY2(m1 == m2, "Identity should be Identity"); + m1 /= 2.0; + m2 -= m1; + QVERIFY2(m1 == m2, "Identity should be Identity"); - m1 = CMatrix3x3(1, 5, 3, 2, 4, 7, 4, 6, 2); - double det = m1.determinant(); - QVERIFY2(det == 74, qPrintable(QString("Determinant should be 74, but is: %1").arg(det))); - QVERIFY2(m1(0, 0) == 1 && m1(1, 0) == 2 && m1(0, 2) == 3, "Index error"); - CMatrix3x3 mi = m1.inverse(invertible); - CMatrix3x3 mid = m1 * mi; - QVERIFY2(mid.isIdentityEpsilon(), qPrintable(QString("Multiply with inverse should be identity: %1").arg(mid.toQString()))); + m1 = CMatrix3x3(1, 5, 3, 2, 4, 7, 4, 6, 2); + double det = m1.determinant(); + QVERIFY2(det == 74, qPrintable(QString("Determinant should be 74, but is: %1").arg(det))); + QVERIFY2(m1(0, 0) == 1 && m1(1, 0) == 2 && m1(0, 2) == 3, "Index error"); + CMatrix3x3 mi = m1.inverse(invertible); + CMatrix3x3 mid = m1 * mi; + QVERIFY2(mid.isIdentityEpsilon(), qPrintable(QString("Multiply with inverse should be identity: %1").arg(mid.toQString()))); - m1.setToIdentity(); - CMatrix3x1 mc1 = m1.getColumn(0); - CMatrix1x3 mr2 = m1.getRow(1); - QVERIFY2(mc1 == CMatrix3x1(1, 0, 0), "Wrong column 0"); - QVERIFY2(mr2 == CMatrix1x3(0, 1, 0), "Wrong row 1"); -} + m1.setToIdentity(); + CMatrix3x1 mc1 = m1.getColumn(0); + CMatrix1x3 mr2 = m1.getRow(1); + QVERIFY2(mc1 == CMatrix3x1(1, 0, 0), "Wrong column 0"); + QVERIFY2(mr2 == CMatrix1x3(0, 1, 0), "Wrong row 1"); + } } // namespace