refs #473, own launcher subproject

* command line args for swift GUI
* removed _ from swiftgui_standard
* removed _ from swift_resources
This commit is contained in:
Klaus Basan
2015-11-05 02:50:51 +01:00
committed by Mathew Sutcliffe
parent 8e57914e67
commit 6dd66284ca
26 changed files with 346 additions and 115 deletions

View File

@@ -0,0 +1,56 @@
/* Copyright (C) 2013
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#ifndef STDGUI_GUIMODEENUMS_H
#define STDGUI_GUIMODEENUMS_H
#include <QString>
//! Modes, how GUI can be started (core/GUI)
struct GuiModes
{
public:
//! Core runs how and where?
enum CoreMode
{
CoreInGuiProcess,
CoreExternal,
CoreExternalAudioLocal
};
//! String to core mode
static CoreMode stringToCoreMode(const QString &m)
{
QString cm(m.toLower().trimmed());
if (cm.isEmpty()) { return CoreInGuiProcess; }
if (m == coreModeToString(CoreExternal)) { return CoreExternal; }
if (m == coreModeToString(CoreInGuiProcess)) { return CoreInGuiProcess; }
if (m == coreModeToString(CoreExternalAudioLocal)) { return CoreExternalAudioLocal; }
// some alternative names
if (cm.contains("audiolocal")) { return CoreExternalAudioLocal; }
if (cm.contains("localaudio")) { return CoreExternalAudioLocal; }
if (cm.contains("external")) { return CoreExternal; }
if (cm.contains("gui")) { return CoreInGuiProcess; }
return CoreInGuiProcess;
}
//! Core mode as string
static QString coreModeToString(CoreMode mode)
{
switch (mode)
{
case CoreInGuiProcess: return "coreinguiprocess";
case CoreExternal: return "coreexternal";
case CoreExternalAudioLocal: return "coreexternalaudiolocal";
}
return "";
}
};
#endif // guard

View File

@@ -0,0 +1,152 @@
/* Copyright (C) 2013
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#include "swiftguistd.h"
#include "guimodeenums.h"
#include "blackgui/stylesheetutility.h"
#include "blackcore/blackcorefreefunctions.h"
#include "blackcore/context_runtime_config.h"
#include "blackgui/guiutility.h"
#include "blackmisc/blackmiscfreefunctions.h"
#include "blackmisc/logmessage.h"
#include "blackmisc/icons.h"
#include "blackmisc/loghandler.h"
#include "blackmisc/filelogger.h"
#include <QtGlobal>
#include <QApplication>
#include <QMessageBox>
#include <QPushButton>
#include <QProcessEnvironment>
using namespace BlackGui;
using namespace BlackMisc;
using namespace BlackCore;
enum CommandLineParseResult
{
CommandLineOk,
CommandLineError,
CommandLineVersionRequested,
CommandLineHelpRequested
};
CommandLineParseResult parseCommandLine(QCommandLineParser &parser,
CEnableForFramelessWindow::WindowMode &windowMode,
GuiModes::CoreMode &coreMode,
QString &dBusAddress,
QString &errorMessage)
{
parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
// value core mode
QCommandLineOption modeOption(QStringList() << "c" << "core",
QCoreApplication::translate("main", "Core mode: (e)xternal, (g)ui (in GUI process), (l)ocalaudio (external, but local audio)."),
"coremode");
parser.addOption(modeOption);
// value DBus address
QCommandLineOption dBusOption(QStringList() << "dbus" << "dbus-address",
QCoreApplication::translate("main", "DBUS address."),
"dbusaddress");
parser.addOption(dBusOption);
// Window type
QCommandLineOption windowOption(QStringList() << "w" << "window",
QCoreApplication::translate("main", "Windows: (n)ormal, (f)rameless, (t)ool."),
"windowtype");
parser.addOption(windowOption);
// help/version
QCommandLineOption helpOption = parser.addHelpOption();
QCommandLineOption versionOption = parser.addVersionOption();
// evaluate
if (!parser.parse(QCoreApplication::arguments()))
{
errorMessage = parser.errorText();
return CommandLineError;
}
if (parser.isSet(helpOption)) { return CommandLineHelpRequested; }
if (parser.isSet(versionOption)) { return CommandLineVersionRequested; }
if (parser.isSet(dBusOption))
{
QString v(parser.value(dBusOption).trimmed());
dBusAddress = CDBusServer::fixAddressToDBusAddress(v);
}
if (parser.isSet(windowOption))
{
QString v(parser.value(windowOption).trimmed());
windowMode = CEnableForFramelessWindow::stringToWindowMode(v);
}
if (parser.isSet(modeOption))
{
QString v(parser.value(modeOption));
coreMode = GuiModes::stringToCoreMode(v);
}
return CommandLineOk;
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
const QString appName("swift pilot client GUI");
a.setApplicationVersion(CProject::swiftVersionString());
a.setApplicationName(appName);
// Process the actual command line arguments given by the user
QCommandLineParser parser;
parser.setApplicationDescription(appName);
CEnableForFramelessWindow::WindowMode windowMode = CEnableForFramelessWindow::WindowNormal;
GuiModes::CoreMode coreMode = GuiModes::CoreInGuiProcess;
QString dBusAddress, errorMessage;
switch (parseCommandLine(parser, windowMode, coreMode, dBusAddress, errorMessage))
{
case CommandLineOk:
break;
case CommandLineError:
CGuiUtility::commandLineErrorMessage(errorMessage, parser);
return 1;
case CommandLineVersionRequested:
CGuiUtility::commandLineVersionRequested();
return 0;
case CommandLineHelpRequested:
CGuiUtility::commandLineHelpRequested(parser);
return 0;
}
BlackCore::CRuntimeConfig runtimeConfig;
switch (coreMode)
{
case GuiModes::CoreExternal:
runtimeConfig = CRuntimeConfig::remote(dBusAddress);
break;
case GuiModes::CoreInGuiProcess:
runtimeConfig = CRuntimeConfig::local(dBusAddress);
break;
case GuiModes::CoreExternalAudioLocal:
runtimeConfig = CRuntimeConfig::remoteLocalAudio(dBusAddress);
break;
}
// show window
CGuiUtility::initSwiftGuiApplication(a, appName, CIcons::swift24());
SwiftGuiStd w(windowMode);
w.init(runtimeConfig); // object is complete by now
w.show();
int r = a.exec();
return r;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

@@ -0,0 +1 @@
IDI_ICON1 ICON DISCARDABLE "swift.ico"

View File

@@ -0,0 +1,37 @@
load(common_pre)
QT += core dbus gui svg network xml multimedia
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = swiftguistd
TEMPLATE = app
SOURCES += *.cpp
HEADERS += *.h
FORMS += *.ui
CONFIG += blackmisc blacksound blackinput blackcore blackgui
macx {
CONFIG += app_bundle
deployment.files = ../blackgui/qss
deployment.path = Contents/MacOS
QMAKE_BUNDLE_DATA += deployment
}
DEPENDPATH += . $$SourceRoot/src/blackmisc \
$$SourceRoot/src/blacksound \
$$SourceRoot/src/blackcore \
$$SourceRoot/src/blackgui \
$$SourceRoot/src/blackinput
INCLUDEPATH += . $$SourceRoot/src
OTHER_FILES += *.qss *.ico *.rc
RC_FILE = swift.rc
DISTFILES += swift.rc
DESTDIR = $$DestRoot/bin
load(common_post)

View File

@@ -0,0 +1,423 @@
/* Copyright (C) 2013
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#include "swiftguistd.h"
#include "ui_swiftguistd.h"
#include "blackmisc/icon.h"
#include "blackgui/stylesheetutility.h"
#include "blackgui/models/atcstationlistmodel.h"
#include "blackgui/components/logcomponent.h"
#include "blackgui/components/settingscomponent.h"
#include "blackcore/dbus_server.h"
#include "blackcore/context_network.h"
#include "blackcore/context_application.h"
#include "blackcore/context_ownaircraft.h"
#include "blackcore/network.h"
#include "blackmisc/logmessage.h"
#include "blackmisc/audio/notificationsounds.h"
#include <QMouseEvent>
#include <QMainWindow>
using namespace BlackCore;
using namespace BlackSound;
using namespace BlackMisc;
using namespace BlackGui;
using namespace BlackGui::Components;
using namespace BlackMisc::Network;
using namespace BlackMisc::Aviation;
using namespace BlackMisc::PhysicalQuantities;
using namespace BlackMisc::Geo;
using namespace BlackMisc::Audio;
using namespace BlackMisc::Input;
/*
* Constructor
*/
SwiftGuiStd::SwiftGuiStd(BlackGui::CEnableForFramelessWindow::WindowMode windowMode, QWidget *parent) :
QMainWindow(parent, CEnableForFramelessWindow::modeToWindowFlags(windowMode)),
CIdentifiable(this),
CEnableForFramelessWindow(windowMode, true, "framelessMainWindow", this),
ui(new Ui::SwiftGuiStd)
{
// GUI
ui->setupUi(this);
this->setDynamicProperties(windowMode == CEnableForFramelessWindow::WindowFrameless);
}
SwiftGuiStd::~SwiftGuiStd()
{ }
void SwiftGuiStd::mouseMoveEvent(QMouseEvent *event)
{
if (!handleMouseMoveEvent(event))
{
QMainWindow::mouseMoveEvent(event);
}
}
void SwiftGuiStd::mousePressEvent(QMouseEvent *event)
{
if (!handleMousePressEvent(event))
{
QMainWindow::mousePressEvent(event);
}
}
void SwiftGuiStd::performGracefulShutdown()
{
if (!this->m_init) { return; }
this->m_init = false;
// shut down all timers
this->stopAllTimers(true);
// if we have a context, we shut some things down
if (this->m_contextNetworkAvailable)
{
if (this->getIContextNetwork() && this->getIContextNetwork()->isConnected())
{
if (this->m_contextAudioAvailable)
{
this->getIContextAudio()->leaveAllVoiceRooms();
this->getIContextAudio()->disconnect(this); // break down signal / slots
}
this->getIContextNetwork()->disconnectFromNetwork();
this->getIContextNetwork()->disconnect(this); // avoid any status update signals, etc.
}
}
// clean up GUI
this->ui->comp_MainInfoArea->dockAllWidgets();
this->ui->comp_InvisibleInfoArea->dockAllWidgets();
// allow some other parts to react
QApplication::processEvents(QEventLoop::AllEvents, 100);
// tell GUI components to shut down
emit requestGracefulShutdown();
// tell context GUI is going down
if (this->getIContextApplication())
{
this->getIContextApplication()->unregisterApplication(identifier());
}
// allow some other parts to react
QApplication::processEvents(QEventLoop::AllEvents, 100);
}
void SwiftGuiStd::closeEvent(QCloseEvent *event)
{
Q_UNUSED(event);
this->performGracefulShutdown();
QApplication::exit();
}
void SwiftGuiStd::changeEvent(QEvent *event)
{
if (event->type() == QEvent::WindowStateChange)
{
// make sure a tool window is changed to Normal window so it is show in taskbar
if (!this->isFrameless())
{
bool toolWindow(this->isToolWindow());
if (isMinimized())
{
if (toolWindow)
{
// still tool, force normal window
BlackMisc::singleShot(0, QThread::currentThread(), [ = ]()
{
this->ps_showMinimized();
});
}
}
else
{
if (!toolWindow)
{
// not tool, force tool window
BlackMisc::singleShot(0, QThread::currentThread(), [ = ]()
{
this->ps_showNormal();
});
}
}
} // frameless?
}
QMainWindow::changeEvent(event);
}
QAction *SwiftGuiStd::getWindowMinimizeAction(QObject *parent)
{
QIcon i(CIcons::changeIconBackgroundColor(this->style()->standardIcon(QStyle::SP_TitleBarMinButton), Qt::white, QSize(16, 16)));
QAction *a = new QAction(i, "Window minimized", parent);
connect(a, &QAction::triggered, this, &SwiftGuiStd::ps_showMinimized);
return a;
}
QAction *SwiftGuiStd::getWindowNormalAction(QObject *parent)
{
QIcon i(CIcons::changeIconBackgroundColor(this->style()->standardIcon(QStyle::SP_TitleBarNormalButton), Qt::white, QSize(16, 16)));
QAction *a = new QAction(i, "Window normal", parent);
connect(a, &QAction::triggered, this, &SwiftGuiStd::ps_showNormal);
return a;
}
QAction *SwiftGuiStd::getToggleWindowVisibilityAction(QObject *parent)
{
QIcon i(CIcons::changeIconBackgroundColor(this->style()->standardIcon(QStyle::SP_TitleBarShadeButton), Qt::white, QSize(16, 16)));
QAction *a = new QAction(i, "Toogle main window visibility", parent);
connect(a, &QAction::triggered, this, &SwiftGuiStd::ps_toggleWindowVisibility);
return a;
}
QAction *SwiftGuiStd::getToggleStayOnTopAction(QObject *parent)
{
QIcon i(CIcons::changeIconBackgroundColor(this->style()->standardIcon(QStyle::SP_TitleBarUnshadeButton), Qt::white, QSize(16, 16)));
QAction *a = new QAction(i, "Toogle main window on top", parent);
connect(a, &QAction::triggered, this, &SwiftGuiStd::ps_toogleWindowStayOnTop);
return a;
}
void SwiftGuiStd::ps_setMainPage(SwiftGuiStd::MainPageIndex mainPage)
{
this->ui->sw_MainMiddle->setCurrentIndex(mainPage);
}
void SwiftGuiStd::ps_setMainPageInfoArea(CMainInfoAreaComponent::InfoArea infoArea)
{
this->ps_setMainPageToInfoArea();
this->ui->comp_MainInfoArea->selectArea(infoArea);
}
bool SwiftGuiStd::isMainPageSelected(SwiftGuiStd::MainPageIndex mainPage) const
{
return this->ui->sw_MainMiddle->currentIndex() == static_cast<int>(mainPage);
}
void SwiftGuiStd::ps_loginRequested()
{
if (this->ui->sw_MainMiddle->currentIndex() == static_cast<int>(MainPageLogin))
{
// already main page, we fake a re-trigger here
emit this->currentMainInfoAreaChanged(this->ui->sw_MainMiddle->currentWidget());
}
else
{
this->ps_setMainPage(MainPageLogin);
}
}
bool SwiftGuiStd::isContextNetworkAvailableCheck()
{
if (this->m_contextNetworkAvailable) return true;
CLogMessage(this).error("Network context not available, no updates this time");
return false;
}
bool SwiftGuiStd::isContextAudioAvailableCheck()
{
if (this->m_contextAudioAvailable) return true;
CLogMessage(this).error("Audio context not available");
return false;
}
void SwiftGuiStd::ps_displayStatusMessageInGui(const CStatusMessage &statusMessage)
{
if (!this->m_init) { return; }
if (statusMessage.isRedundant()) { return; }
if (statusMessage.wasHandledBy(this)) { return; }
statusMessage.markAsHandledBy(this);
this->m_statusBar.displayStatusMessage(statusMessage);
// main info areas
this->ui->comp_MainInfoArea->displayStatusMessage(statusMessage);
this->ui->comp_InvisibleInfoArea->displayStatusMessage(statusMessage);
// list
this->ui->comp_MainInfoArea->getLogComponent()->appendStatusMessageToList(statusMessage);
// display overlay for errors, but not for validation
if (statusMessage.getSeverity() == CStatusMessage::SeverityError && ! statusMessage.getCategories().contains(CLogCategory::validation()))
{
this->ui->fr_CentralFrameInside->showMessage(statusMessage);
}
}
void SwiftGuiStd::ps_onConnectionTerminated()
{
this->updateGuiStatusInformation();
}
void SwiftGuiStd::ps_onConnectionStatusChanged(BlackCore::INetwork::ConnectionStatus from, BlackCore::INetwork::ConnectionStatus to)
{
Q_UNUSED(from);
this->updateGuiStatusInformation();
// sounds
switch (to)
{
case INetwork::Connected:
this->playNotifcationSound(CNotificationSounds::NotificationLogin);
break;
case INetwork::Disconnected:
this->playNotifcationSound(CNotificationSounds::NotificationLogoff);
break;
case INetwork::DisconnectedError:
this->playNotifcationSound(CNotificationSounds::NotificationError);
break;
default:
break;
}
}
void SwiftGuiStd::ps_handleTimerBasedUpdates()
{
this->setContextAvailability();
this->updateGuiStatusInformation();
// own aircraft
this->ps_reloadOwnAircraft();
}
void SwiftGuiStd::setContextAvailability()
{
bool corePreviouslyAvailable = this->m_coreAvailable;
if (this->getIContextApplication()->isUsingImplementingObject())
{
this->m_coreAvailable = true;
}
else
{
this->m_coreAvailable = isMyIdentifier(this->getIContextApplication()->registerApplication(getCurrentTimestampIdentifier()));
}
this->m_contextNetworkAvailable = this->m_coreAvailable || this->getIContextNetwork()->isUsingImplementingObject();
this->m_contextAudioAvailable = this->m_coreAvailable || this->getIContextAudio()->isUsingImplementingObject();
// react to a change in core's availability
if (this->m_coreAvailable != corePreviouslyAvailable)
{
if (this->m_coreAvailable)
{
// core has just become available
this->getIContextApplication()->synchronizeLogSubscriptions();
this->getIContextApplication()->synchronizeLocalSettings();
}
else
{
// core has just become unavailable...
}
}
}
void SwiftGuiStd::updateGuiStatusInformation()
{
const QString now = QDateTime::currentDateTimeUtc().toString("yyyy-MM-dd HH:mm:ss");
QString network("unavailable");
if (this->m_contextNetworkAvailable)
{
bool dbus = !this->getIContextNetwork()->isUsingImplementingObject();
network = dbus ? now : "local";
this->ui->comp_InfoBarStatus->setDBusStatus(dbus);
}
// update status fields
QString s = QString("network: %1").arg(network);
this->ui->comp_InfoBarStatus->setDBusTooltip(s);
}
void SwiftGuiStd::ps_onChangedWindowOpacity(int opacity)
{
qreal o = opacity / 100.0;
o = o < 0.3 ? 0.3 : o;
o = o > 1.0 ? 1.0 : o;
QWidget::setWindowOpacity(o);
this->ui->comp_MainInfoArea->getSettingsComponent()->setGuiOpacity(o * 100.0);
}
void SwiftGuiStd::ps_toogleWindowStayOnTop()
{
Qt::WindowFlags flags = this->windowFlags();
if (Qt::WindowStaysOnTopHint & flags)
{
flags ^= Qt::WindowStaysOnTopHint;
flags |= Qt::WindowStaysOnBottomHint;
CLogMessage(this).info("Window on bottom");
}
else
{
flags ^= Qt::WindowStaysOnBottomHint;
flags |= Qt::WindowStaysOnTopHint;
CLogMessage(this).info("Window on top");
}
this->setWindowFlags(flags);
this->show();
}
void SwiftGuiStd::ps_toggleWindowVisibility()
{
if (this->isVisible())
{
this->hide();
}
else
{
this->show();
}
}
void SwiftGuiStd::ps_onStyleSheetsChanged()
{
this->initStyleSheet();
}
void SwiftGuiStd::ps_onCurrentMainWidgetChanged(int currentIndex)
{
emit currentMainInfoAreaChanged(this->ui->sw_MainMiddle->currentWidget());
Q_UNUSED(currentIndex);
}
void SwiftGuiStd::ps_onChangedMainInfoAreaFloating(bool floating)
{
// code for whole floating area goes here
Q_UNUSED(floating);
}
void SwiftGuiStd::ps_showMinimized()
{
if (!this->isFrameless()) { toolToNormalWindow(); }
this->showMinimized();
}
void SwiftGuiStd::ps_showNormal()
{
if (!this->isFrameless()) { normalToToolWindow(); }
this->showNormal();
}
void SwiftGuiStd::playNotifcationSound(CNotificationSounds::Notification notification) const
{
if (!this->m_contextAudioAvailable) { return; }
if (!this->ui->comp_MainInfoArea->getSettingsComponent()->playNotificationSounds()) { return; }
this->getIContextAudio()->playNotification(notification, true);
}
void SwiftGuiStd::displayConsole()
{
this->ui->comp_MainInfoArea->displayConsole();
}
void SwiftGuiStd::displayLog()
{
this->ui->comp_MainInfoArea->displayLog();
}

View File

@@ -0,0 +1,271 @@
/* Copyright (C) 2013
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
//! \file
#ifndef STDGUI_SWIFTGUISTD_H
#define STDGUI_SWIFTGUISTD_H
// clash with struct interface in objbase.h used to happen
#pragma push_macro("interface")
#undef interface
#include "guimodeenums.h"
#include "blackcore/context_all_interfaces.h"
#include "blackcore/actionbind.h"
#include "blackcore/data/globalsetup.h"
#include "blackgui/components/enableforruntime.h"
#include "blackgui/components/maininfoareacomponent.h"
#include "blackgui/transpondermodeselector.h"
#include "blackgui/models/atcstationlistmodel.h"
#include "blackgui/models/serverlistmodel.h"
#include "blackgui/models/userlistmodel.h"
#include "blackgui/models/statusmessagelistmodel.h"
#include "blackgui/enableforframelesswindow.h"
#include "blackgui/managedstatusbar.h"
#include "blackgui/overlaymessagesframe.h"
#include "blackmisc/network/textmessage.h"
#include "blackmisc/loghandler.h"
#include "blackmisc/identifiable.h"
#include "blacksound/soundgenerator.h"
#include <QMainWindow>
#include <QTextEdit>
#include <QTableView>
#include <QItemSelection>
#include <QLabel>
#include <QTimer>
namespace Ui { class SwiftGuiStd; }
//! swift GUI
class SwiftGuiStd :
public QMainWindow,
public BlackMisc::CIdentifiable,
public BlackGui::CEnableForFramelessWindow,
public BlackGui::Components::CEnableForRuntime
{
Q_OBJECT
public:
//! Main page indexes
//! \remarks keep the values in sync with the real tab indexes
enum MainPageIndex
{
MainPageInfoArea = 0,
MainPageLogin = 1,
MainPageInternals = 2,
MainPageInvisible = 3
};
//! Constructor
SwiftGuiStd(BlackGui::CEnableForFramelessWindow::WindowMode windowMode, QWidget *parent = nullptr);
//! Destructor
~SwiftGuiStd();
//! Init data
void init(const BlackCore::CRuntimeConfig &runtimeConfig);
//! Log message category
static QString getMessageCategory() { return "swift.gui.stdgui"; }
signals:
//! GUI is shutting down, request graceful shutdown
void requestGracefulShutdown();
//! Main info area changed
//! \remarks using widget pointer allows the component itself to identify if it is current
void currentMainInfoAreaChanged(const QWidget *currentWidget);
protected:
//! \copydoc QMainWindow::mouseMoveEvent
virtual void mouseMoveEvent(QMouseEvent *event) override;
//! \copydoc QMainWindow::mousePressEvent
virtual void mousePressEvent(QMouseEvent *event) override;
//! \copydoc QMainWindow::closeEvent
virtual void closeEvent(QCloseEvent *event) override;
//! \copydoc QMainWindow::changeEvent
virtual void changeEvent(QEvent *event) override;
//! Get a minimize action which minimizes the window
QAction *getWindowMinimizeAction(QObject *parent);
//! Get a normal window action which minimizes the window
QAction *getWindowNormalAction(QObject *parent);
//! Toggle window visibility action
QAction *getToggleWindowVisibilityAction(QObject *parent);
//! Toggle window stay on top action
QAction *getToggleStayOnTopAction(QObject *parent);
private:
QScopedPointer<Ui::SwiftGuiStd> ui;
bool m_init = false;
BlackGui::CManagedStatusBar m_statusBar;
BlackMisc::CLogSubscriber m_logSubscriber { this, &SwiftGuiStd::ps_displayStatusMessageInGui };
BlackCore::CData<BlackCore::Data::GlobalSetup> m_setup {this}; //!< setup cache
// contexts
bool m_coreAvailable = false;
bool m_contextNetworkAvailable = false;
bool m_contextAudioAvailable = false;
QTimer *m_timerContextWatchdog = nullptr; //!< core available?
BlackMisc::Simulation::CSimulatedAircraft m_ownAircraft; //!< own aircraft's state
QSize m_windowMinSizeWithMainPageShown;
QSize m_windowMinSizeWithMainPageHidden;
// cockpit
QString m_transponderResetValue; //!< Temp. storage of XPdr mode to reset, req. until timer allows singleShoot with Lambdas
QWidget *m_inputFocusedWidget = nullptr; //!< currently used widget for input, mainly used with cockpit
// actions
BlackCore::CActionBind m_action50 { "/swiftGui/Change opacity to 50%", this, &SwiftGuiStd::ps_onChangedWindowOpacityTo50 };
BlackCore::CActionBind m_action100 { "/swiftGui/Change opacity to 100%", this, &SwiftGuiStd::ps_onChangedWindowOpacityTo100 };
//! GUI status update
void updateGuiStatusInformation();
//! Set style sheet
void initStyleSheet();
//! 1st data reads
void initialDataReads();
//! Init GUI signals
void initGuiSignals();
//! Init dynamic menus
void initDynamicMenus();
//! Menu icons where required
void initMenuIcons();
//! Graceful shutdown
void performGracefulShutdown();
//! Context network availability check, otherwise status message
bool isContextNetworkAvailableCheck();
//! Context voice availability check, otherwise status message
bool isContextAudioAvailableCheck();
//! Audio device lists
void setAudioDeviceLists();
//! Context availability, used by watchdog
void setContextAvailability();
//! Position of own plane for testing
//! \param wgsLatitude WGS latitude
//! \param wgsLongitude WGS longitude
//! \param altitude
void setTestPosition(const QString &wgsLatitude, const QString &wgsLongitude, const BlackMisc::Aviation::CAltitude &altitude);
//! Is given main page selected?
//! \param mainPage index to be checked
bool isMainPageSelected(MainPageIndex mainPage) const;
//! Start all update timers
void startUpdateTimersWhenConnected();
//! Stop all update timers
void stopUpdateTimersWhenDisconnected();
//! Stop all timers
//! \param disconnect also disconnect signal/slots
void stopAllTimers(bool disconnectSignalSlots);
//! Play notifcation sound
void playNotifcationSound(BlackMisc::Audio::CNotificationSounds::Notification notification) const;
//! Display console
void displayConsole();
//! Display log
void displayLog();
private slots:
//
// Data received related slots
//
//! Reload own aircraft
bool ps_reloadOwnAircraft();
//! Display status message
void ps_displayStatusMessageInGui(const BlackMisc::CStatusMessage &);
//! Connection status changed
//! \param from old status, as int so it is compliant with DBus
//! \param to new status, as int so it is compliant with DBus
void ps_onConnectionStatusChanged(BlackCore::INetwork::ConnectionStatus from, BlackCore::INetwork::ConnectionStatus to);
//
// GUI related slots
//
//! Set \sa MainPageInfoArea
void ps_setMainPageToInfoArea() { this->ps_setMainPage(MainPageInfoArea); }
//! Set one of the main pages
void ps_setMainPage(MainPageIndex mainPage);
//! Set the main info area
void ps_setMainPageInfoArea(BlackGui::Components::CMainInfoAreaComponent::InfoArea infoArea);
//! Login requested
void ps_loginRequested();
//! Menu item clicked
void ps_onMenuClicked();
//! Terminated connection
void ps_onConnectionTerminated();
//! Update timer
void ps_handleTimerBasedUpdates();
//! Change opacity 0-100
void ps_onChangedWindowOpacityTo50(bool) { ps_onChangedWindowOpacity(50); }
//! Change opacity 0-100
void ps_onChangedWindowOpacityTo100(bool) { ps_onChangedWindowOpacity(100); }
//! Change opacity 0-100
void ps_onChangedWindowOpacity(int opacity = -1);
//! Toogle if windows stays on top
void ps_toogleWindowStayOnTop();
//! Toggle window visibility
void ps_toggleWindowVisibility();
//! Style sheet has been changed
void ps_onStyleSheetsChanged();
//! Main info area current widget changed
void ps_onCurrentMainWidgetChanged(int currentIndex);
//! Whole main info area floating
void ps_onChangedMainInfoAreaFloating(bool floating);
//! Show window minimized
void ps_showMinimized();
//! Show window normal
void ps_showNormal();
};
#pragma pop_macro("interface")
#endif // guard

View File

@@ -0,0 +1,599 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SwiftGuiStd</class>
<widget class="QMainWindow" name="SwiftGuiStd">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>350</width>
<height>574</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>325</width>
<height>550</height>
</size>
</property>
<property name="windowTitle">
<string>swift GUI</string>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonIconOnly</enum>
</property>
<property name="animated">
<bool>true</bool>
</property>
<property name="tabShape">
<enum>QTabWidget::Rounded</enum>
</property>
<property name="dockOptions">
<set>QMainWindow::AllowTabbedDocks|QMainWindow::AnimatedDocks|QMainWindow::ForceTabbedDocks</set>
</property>
<widget class="QWidget" name="wi_CentralWidgetOutside">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>350</width>
<height>500</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<layout class="QVBoxLayout" name="vl_CentralWidgetOutside">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<widget class="BlackGui::COverlayMessagesFrame" name="fr_CentralFrameInside">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<layout class="QVBoxLayout" name="vl_CentralFrameInside">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QStackedWidget" name="sw_MainMiddle">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<italic>false</italic>
<bold>true</bold>
</font>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="currentIndex">
<number>2</number>
</property>
<widget class="QWidget" name="pg_MainInfoArea">
<layout class="QVBoxLayout" name="vl_MainInfoArea">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="BlackGui::Components::CMainInfoAreaComponent" name="comp_MainInfoArea" native="true"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="pg_LoginConfirmation">
<layout class="QVBoxLayout" name="vl_LoginConfirmation">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="BlackGui::Components::CLoginComponent" name="comp_Login" native="true"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="pg_Internals">
<layout class="QVBoxLayout" name="vl_Internals">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="BlackGui::Components::CInternalsComponent" name="comp_Internals" native="true"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="pg_InvisibleAreas">
<layout class="QVBoxLayout" name="vl_InvisibleArea">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="BlackGui::Components::CInvisibleInfoAreaComponent" name="comp_InvisibleInfoArea" native="true"/>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="BlackGui::Components::CMainKeypadAreaComponent" name="comp_MainKeypadArea">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="mb_MainMenuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>350</width>
<height>21</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<widget class="QMenu" name="menu_Test">
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="title">
<string>Test</string>
</property>
<widget class="QMenu" name="menu_PlanePositions">
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="title">
<string>Set plane positions </string>
</property>
<addaction name="menu_TestLocationsEDRY"/>
<addaction name="menu_TestLocationsEDDF"/>
<addaction name="menu_TestLocationsEDDM"/>
<addaction name="menu_TestLocationsEDNX"/>
<addaction name="menu_TestLocationsLOWW"/>
</widget>
<widget class="QMenu" name="menu_Reload">
<property name="title">
<string>Reload</string>
</property>
<addaction name="menu_ReloadSettings"/>
</widget>
<widget class="QMenu" name="menu_InternalsItem">
<property name="title">
<string>Internals</string>
</property>
<addaction name="menu_Internals"/>
<addaction name="menu_InternalsMetatypes"/>
<addaction name="menu_InternalsEnvVars"/>
<addaction name="menu_InternalsSetup"/>
<addaction name="menu_InternalsCompileInfo"/>
<addaction name="menu_InternalsDeleteCachedFiles"/>
<addaction name="menu_InternalsDisplayCachedFiles"/>
</widget>
<addaction name="menu_InternalsItem"/>
<addaction name="separator"/>
<addaction name="menu_PlanePositions"/>
<addaction name="menu_Reload"/>
</widget>
<widget class="QMenu" name="menu_Help">
<property name="title">
<string>Help</string>
</property>
</widget>
<widget class="QMenu" name="menu_File">
<property name="title">
<string>File</string>
</property>
<addaction name="menu_FileSettingsDirectory"/>
<addaction name="menu_FileCacheDirectory"/>
<addaction name="menu_FileResetSettings"/>
<addaction name="menu_FileReloadStyleSheets"/>
<addaction name="separator"/>
<addaction name="menu_FileExit"/>
</widget>
<widget class="QMenu" name="menu_InfoAreas">
<property name="title">
<string>Info areas</string>
</property>
</widget>
<widget class="QMenu" name="menu_Window">
<property name="title">
<string>Window</string>
</property>
<addaction name="menu_WindowFont"/>
<addaction name="menu_WindowMinimize"/>
<addaction name="menu_WindowToggleOnTop"/>
<addaction name="menu_WindowToggleNavigator"/>
</widget>
<addaction name="menu_File"/>
<addaction name="menu_Window"/>
<addaction name="menu_InfoAreas"/>
<addaction name="menu_Help"/>
<addaction name="menu_Test"/>
</widget>
<widget class="QStatusBar" name="sb_MainStatusBar">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="sizeGripEnabled">
<bool>false</bool>
</property>
</widget>
<widget class="BlackGui::CDockWidgetInfoBar" name="dw_InfoBarStatus">
<property name="features">
<set>QDockWidget::AllDockWidgetFeatures</set>
</property>
<property name="allowedAreas">
<set>Qt::TopDockWidgetArea</set>
</property>
<property name="windowTitle">
<string>Info status bar</string>
</property>
<attribute name="dockWidgetArea">
<number>4</number>
</attribute>
<widget class="QWidget" name="qw_InfoBarStatusInner">
<layout class="QVBoxLayout" name="vl_InfoBarStatusOuter">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item alignment="Qt::AlignTop">
<widget class="BlackGui::Components::CInfoBarStatusComponent" name="comp_InfoBarStatus" native="true"/>
</item>
</layout>
</widget>
</widget>
<action name="menu_TestLocationsEDDF">
<property name="text">
<string>Position EDDF (Frankfurt, GER)</string>
</property>
</action>
<action name="menu_TestLocationsEDDM">
<property name="text">
<string>Position EDDM (Munich, GER)</string>
</property>
</action>
<action name="menu_TestLocationsEDRY">
<property name="text">
<string>Position EDRY (Speyer, GER)</string>
</property>
</action>
<action name="menu_ReloadSettings">
<property name="text">
<string>Reload settings</string>
</property>
</action>
<action name="menu_TestLocationsEDNX">
<property name="text">
<string>Position EDNX (Schleißheim, GER)</string>
</property>
</action>
<action name="menu_FileExit">
<property name="text">
<string>Exit</string>
</property>
</action>
<action name="menu_FileSettingsDirectory">
<property name="text">
<string>Settings directory</string>
</property>
</action>
<action name="menu_FileResetSettings">
<property name="text">
<string>Reset settings</string>
</property>
</action>
<action name="menu_FileReloadStyleSheets">
<property name="text">
<string>Reload style sheets</string>
</property>
</action>
<action name="menu_WindowFont">
<property name="text">
<string>Font</string>
</property>
</action>
<action name="menu_DebugMetaTypes">
<property name="text">
<string>Meta types (to console)</string>
</property>
</action>
<action name="menu_TestLocationsLOWW">
<property name="text">
<string>Position LOWW (Vienna, AUT)</string>
</property>
</action>
<action name="menu_WindowMinimize">
<property name="text">
<string>Minimize</string>
</property>
<property name="shortcut">
<string>Ctrl+W, Ctrl+M</string>
</property>
</action>
<action name="menu_WindowToggleOnTop">
<property name="text">
<string>Toggle stay on top</string>
</property>
<property name="shortcut">
<string>Ctrl+W, Ctrl+T</string>
</property>
</action>
<action name="menu_WindowToggleNavigator">
<property name="text">
<string>Navigator</string>
</property>
<property name="shortcut">
<string>Ctrl+W, Ctrl+N</string>
</property>
</action>
<action name="menu_NavigatorHorizontal">
<property name="text">
<string>Horizontal navigator</string>
</property>
</action>
<action name="menu_InternalsMetatypes">
<property name="text">
<string>Metatypes</string>
</property>
</action>
<action name="menu_InternalsEnvVars">
<property name="text">
<string>Env.variables</string>
</property>
</action>
<action name="menu_InternalsSetup">
<property name="text">
<string>Setup</string>
</property>
</action>
<action name="menu_InternalsCompileInfo">
<property name="text">
<string>Compile info</string>
</property>
</action>
<action name="menu_Internals">
<property name="text">
<string>Internal page</string>
</property>
</action>
<action name="menu_InternalsDeleteCachedFiles">
<property name="text">
<string>Delete cached files</string>
</property>
</action>
<action name="menu_InternalsDisplayCachedFiles">
<property name="text">
<string>Display cached files</string>
</property>
</action>
<action name="menu_FileCacheDirectory">
<property name="text">
<string>Cache directory</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
<customwidget>
<class>BlackGui::Components::CMainInfoAreaComponent</class>
<extends>QWidget</extends>
<header>blackgui/components/maininfoareacomponent.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>BlackGui::CDockWidgetInfoBar</class>
<extends>QDockWidget</extends>
<header>blackgui/dockwidgetinfobar.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>BlackGui::Components::CInfoBarStatusComponent</class>
<extends>QWidget</extends>
<header>blackgui/components/infobarstatuscomponent.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>BlackGui::Components::CMainKeypadAreaComponent</class>
<extends>QFrame</extends>
<header>blackgui/components/mainkeypadareacomponent.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>BlackGui::Components::CLoginComponent</class>
<extends>QWidget</extends>
<header>blackgui/components/logincomponent.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>BlackGui::Components::CInternalsComponent</class>
<extends>QWidget</extends>
<header>blackgui/components/internalscomponent.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>BlackGui::Components::CInvisibleInfoAreaComponent</class>
<extends>QWidget</extends>
<header>blackgui/components/invisibleinfoareacomponent.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>BlackGui::COverlayMessagesFrame</class>
<extends>QFrame</extends>
<header>blackgui/overlaymessagesframe.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
<slots>
<slot>setMainPage()</slot>
<slot>toggleNetworkConnection()</slot>
<slot>menuClicked()</slot>
<slot>networkServerSelected(QModelIndex)</slot>
<slot>alterTrafficServer()</slot>
<slot>reloadAtcStationsBooked()</slot>
<slot>onlineAtcStationSelected(QModelIndex)</slot>
<slot>commandEntered()</slot>
<slot>getMetar()</slot>
<slot>cockpitValuesChanged()</slot>
<slot>audioDeviceSelected(int)</slot>
<slot>voiceRoomOverride()</slot>
</slots>
</ui>

View File

@@ -0,0 +1,56 @@
/* Copyright (C) 2013
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#include "swiftguistd.h"
#include "blackgui/models/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::Simulation;
using namespace BlackMisc::PhysicalQuantities;
using namespace BlackMisc::Geo;
using namespace BlackMisc::Audio;
/*
* Load own aircraft
*/
bool SwiftGuiStd::ps_reloadOwnAircraft()
{
if (!this->isContextNetworkAvailableCheck()) { return false; }
// check for changed aircraft
bool changed = false;
CSimulatedAircraft loadedAircraft = this->getIContextOwnAircraft()->getOwnAircraft();
if (loadedAircraft != this->m_ownAircraft)
{
this->m_ownAircraft = loadedAircraft;
changed = true;
}
return changed;
}
/*
* Position
*/
void SwiftGuiStd::setTestPosition(const QString &wgsLatitude, const QString &wgsLongitude, const CAltitude &altitude)
{
CCoordinateGeodetic coordinate(
CLatitude::fromWgs84(wgsLatitude),
CLongitude::fromWgs84(wgsLongitude),
CLength(0, CLengthUnit::m()));
this->m_ownAircraft.setPosition(coordinate);
this->m_ownAircraft.setAltitude(altitude);
this->getIContextOwnAircraft()->updateOwnPosition(coordinate, altitude);
}

View File

@@ -0,0 +1,253 @@
/* Copyright (C) 2013
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#include "swiftguistd.h"
#include "ui_swiftguistd.h"
#include "blackcore/dbus_server.h"
#include "blackcore/context_all_interfaces.h"
#include "blackgui/stylesheetutility.h"
#include "blackgui/guiutility.h"
#include "blackgui/components/allmaininfoareacomponents.h"
#include "blackgui/models/atcstationlistmodel.h"
#include "blackmisc/icons.h"
#include "blackmisc/aviation/selcal.h"
#include "blackmisc/project.h"
#include "blackmisc/logmessage.h"
#include <QSizeGrip>
#include <QHBoxLayout>
#include <QPushButton>
using namespace BlackCore;
using namespace BlackMisc;
using namespace BlackMisc::Input;
using namespace BlackGui;
using namespace BlackGui::Components;
void SwiftGuiStd::init(const CRuntimeConfig &runtimeConfig)
{
// POST(!) GUI init
if (this->m_init) { return; }
this->setVisible(false); // hide all, so no flashing windows during init
// init window
this->setWindowIcon(CIcons::swift24());
this->setWindowTitle(CProject::swiftVersionStringDevInfo());
this->setObjectName("SwiftGuiStd");
this->initStyleSheet();
QPoint pos = CGuiUtility::introWindowPosition();
this->move(pos);
// with frameless window, we shift menu and statusbar into central widget
// http://stackoverflow.com/questions/18316710/frameless-and-transparent-window-qt5
if (this->isFrameless())
{
// wrap menu in layout, add button to menu bar and insert on top
QHBoxLayout *menuBarLayout = this->addFramelessCloseButton(this->ui->mb_MainMenuBar);
this->ui->vl_CentralWidgetOutside->insertLayout(0, menuBarLayout, 0);
// now insert the dock widget info bar into the widget
this->ui->vl_CentralWidgetOutside->insertWidget(1, this->ui->dw_InfoBarStatus);
// move the status bar into the frame
// (otherwise it is dangling outside the frame as it belongs to the window)
this->ui->sb_MainStatusBar->setParent(this->ui->wi_CentralWidgetOutside);
this->ui->vl_CentralWidgetOutside->addWidget(this->ui->sb_MainStatusBar, 0);
// grip
this->addFramelessSizeGripToStatusBar(this->ui->sb_MainStatusBar);
}
// timers
if (this->m_timerContextWatchdog == nullptr)
{
this->m_timerContextWatchdog = new QTimer(this);
this->m_timerContextWatchdog->setObjectName(this->objectName().append(":m_timerContextWatchdog"));
}
// context
this->createRuntime(runtimeConfig, this);
CEnableForRuntime::setRuntimeForComponents(this->getRuntime(), this);
// info bar and status bar
this->m_statusBar.initStatusBar(this->ui->sb_MainStatusBar);
this->ui->dw_InfoBarStatus->allowStatusBar(false);
this->ui->dw_InfoBarStatus->setPreferredSizeWhenFloating(this->ui->dw_InfoBarStatus->size()); // set floating size
// navigator
CNavigatorDockWidget *nav = this->ui->comp_InvisibleInfoArea->getNavigatorComponent();
Q_ASSERT(nav);
nav->addAction(this->getToggleWindowVisibilityAction(nav));
nav->addActions(this->ui->comp_MainInfoArea->getInfoAreaToggleFloatingActions(nav));
nav->addAction(this->getWindowNormalAction(nav));
nav->addAction(this->getWindowMinimizeAction(nav));
nav->addAction(this->getToggleStayOnTopAction(nav));
this->ui->comp_InvisibleInfoArea->getNavigatorComponent()->buildNavigator(1);
// wire GUI signals
this->initGuiSignals();
// signal / slots contexts / timers
connect(this->getIContextNetwork(), &IContextNetwork::connectionTerminated, this, &SwiftGuiStd::ps_onConnectionTerminated);
connect(this->getIContextNetwork(), &IContextNetwork::connectionStatusChanged, this, &SwiftGuiStd::ps_onConnectionStatusChanged);
connect(this->getIContextNetwork(), &IContextNetwork::textMessagesReceived, this->ui->comp_MainInfoArea->getTextMessageComponent(), &CTextMessageComponent::onTextMessageReceived);
connect(this->getIContextNetwork(), &IContextNetwork::textMessageSent, this->ui->comp_MainInfoArea->getTextMessageComponent(), &CTextMessageComponent::onTextMessageSent);
connect(this->m_timerContextWatchdog, &QTimer::timeout, this, &SwiftGuiStd::ps_handleTimerBasedUpdates);
// log messages
m_logSubscriber.changeSubscription(CLogPattern().withSeverityAtOrAbove(CStatusMessage::SeverityInfo));
// start timers, update timers will be started when network is connected
this->m_timerContextWatchdog->start(2500);
// init availability
this->setContextAvailability();
// data
this->initialDataReads();
// start screen and complete menu
this->ps_setMainPageToInfoArea();
this->initDynamicMenus();
this->initMenuIcons();
// info
this->ui->comp_MainInfoArea->getLogComponent()->appendPlainTextToConsole(CProject::swiftVersionString());
this->ui->comp_MainInfoArea->getLogComponent()->appendPlainTextToConsole(CProject::compiledWithInfo());
// update timers
this->startUpdateTimersWhenConnected();
// do this as last statement, so it can be used as flag
// whether init has been completed
this->setVisible(true);
this->m_init = true;
}
void SwiftGuiStd::initStyleSheet()
{
const QString s = CStyleSheetUtility::instance().styles(
{
CStyleSheetUtility::fileNameFonts(),
CStyleSheetUtility::fileNameStandardWidget(),
CStyleSheetUtility::fileNameSwiftStandardGui()
}
);
this->setStyleSheet(s);
}
void SwiftGuiStd::initGuiSignals()
{
// Remark: With new style, only methods of same signature can be connected
// This is why we still have some "old" SIGNAL/SLOT connections here
// main window
connect(this->ui->sw_MainMiddle, &QStackedWidget::currentChanged, this, &SwiftGuiStd::ps_onCurrentMainWidgetChanged);
// main keypad
connect(this->ui->comp_MainKeypadArea, &CMainKeypadAreaComponent::selectedMainInfoAreaDockWidget, this, &SwiftGuiStd::ps_setMainPageInfoArea);
connect(this->ui->comp_MainKeypadArea, &CMainKeypadAreaComponent::connectPressed, this, &SwiftGuiStd::ps_loginRequested);
connect(this->ui->comp_MainKeypadArea, &CMainKeypadAreaComponent::changedOpacity, this , &SwiftGuiStd::ps_onChangedWindowOpacity);
connect(this->ui->comp_MainKeypadArea, &CMainKeypadAreaComponent::identPressed, this->ui->comp_MainInfoArea->getCockpitComponent(), &CCockpitComponent::setSelectedTransponderModeStateIdent);
connect(this->ui->comp_MainKeypadArea, &CMainKeypadAreaComponent::commandEntered, this->ui->comp_MainInfoArea->getTextMessageComponent(), &CTextMessageComponent::handleGlobalCommandLine);
connect(this->ui->comp_MainInfoArea, &CMainInfoAreaComponent::changedInfoAreaStatus, ui->comp_MainKeypadArea, &CMainKeypadAreaComponent::onMainInfoAreaChanged);
// menu
connect(this->ui->menu_ReloadSettings, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked);
connect(this->ui->menu_TestLocationsEDDF, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked);
connect(this->ui->menu_TestLocationsEDDM, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked);
connect(this->ui->menu_TestLocationsEDNX, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked);
connect(this->ui->menu_TestLocationsEDRY, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked);
connect(this->ui->menu_FileExit, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked);
connect(this->ui->menu_FileSettingsDirectory, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked);
connect(this->ui->menu_FileCacheDirectory, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked);
connect(this->ui->menu_FileResetSettings, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked);
connect(this->ui->menu_FileReloadStyleSheets, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked);
connect(this->ui->menu_WindowFont, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked);
connect(this->ui->menu_WindowMinimize, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked);
connect(this->ui->menu_WindowToggleOnTop, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked);
connect(this->ui->menu_WindowToggleNavigator, &QAction::triggered, this->ui->comp_InvisibleInfoArea, &CInvisibleInfoAreaComponent::toggleNavigator);
connect(this->ui->menu_InternalsCompileInfo, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked);
connect(this->ui->menu_InternalsEnvVars, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked);
connect(this->ui->menu_InternalsMetatypes, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked);
connect(this->ui->menu_InternalsSetup, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked);
connect(this->ui->menu_InternalsDeleteCachedFiles, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked);
connect(this->ui->menu_InternalsDisplayCachedFiles, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked);
// command line / text messages
connect(this->ui->comp_MainInfoArea->getTextMessageComponent(), &CTextMessageComponent::displayInInfoWindow, this->ui->fr_CentralFrameInside, &COverlayMessagesFrame::showVariant);
// settings (GUI component), styles
connect(this->ui->comp_MainInfoArea->getSettingsComponent(), &CSettingsComponent::changedWindowsOpacity, this, &SwiftGuiStd::ps_onChangedWindowOpacity);
connect(&CStyleSheetUtility::instance(), &CStyleSheetUtility::styleSheetsChanged, this, &SwiftGuiStd::ps_onStyleSheetsChanged);
// sliders
connect(this->ui->comp_MainInfoArea->getSettingsComponent(), &CSettingsComponent::changedUsersUpdateInterval, this->ui->comp_MainInfoArea->getUserComponent(), &CUserComponent::setUpdateIntervalSeconds);
connect(this->ui->comp_MainInfoArea->getSettingsComponent(), &CSettingsComponent::changedAircraftUpdateInterval, this->ui->comp_MainInfoArea->getAircraftComponent(), &CAircraftComponent::setUpdateIntervalSeconds);
connect(this->ui->comp_MainInfoArea->getSettingsComponent(), &CSettingsComponent::changedAtcStationsUpdateInterval, this->ui->comp_MainInfoArea->getAtcStationComponent(), &::CAtcStationComponent::setUpdateIntervalSeconds);
// login
connect(this->ui->comp_Login, &CLoginComponent::loginOrLogoffCancelled, this, &SwiftGuiStd::ps_setMainPageToInfoArea);
connect(this->ui->comp_Login, &CLoginComponent::loginOrLogoffSuccessful, this, &SwiftGuiStd::ps_setMainPageToInfoArea);
connect(this->ui->comp_Login, &CLoginComponent::loginOrLogoffSuccessful, this->ui->comp_MainInfoArea->getFlightPlanComponent(), &CFlightPlanComponent::loginDataSet);
connect(this, &SwiftGuiStd::currentMainInfoAreaChanged, this->ui->comp_Login, &CLoginComponent::mainInfoAreaChanged);
connect(this->ui->comp_Login, &CLoginComponent::requestNetworkSettings, this->ui->comp_MainInfoArea->getFlightPlanComponent(), [ = ]()
{
this->ps_setMainPageInfoArea(CMainInfoAreaComponent::InfoAreaSettings);
this->ui->comp_MainInfoArea->getSettingsComponent()->setSettingsTab(CSettingsComponent::SettingTabNetworkServers);
});
// text messages
connect(this->ui->comp_MainInfoArea->getAtcStationComponent(), &CAtcStationComponent::requestTextMessageWidget, this->ui->comp_MainInfoArea->getTextMessageComponent(), &CTextMessageComponent::showCorrespondingTab);
connect(this->ui->comp_MainInfoArea->getMappingComponet(), &CMappingComponent::requestTextMessageWidget, this->ui->comp_MainInfoArea->getTextMessageComponent(), &CTextMessageComponent::showCorrespondingTab);
connect(this->ui->comp_MainInfoArea->getAircraftComponent(), &CAircraftComponent::requestTextMessageWidget, this->ui->comp_MainInfoArea->getTextMessageComponent(), &CTextMessageComponent::showCorrespondingTab);
// main info area
connect(this->ui->comp_MainInfoArea, &CMainInfoAreaComponent::changedWholeInfoAreaFloating, this, &SwiftGuiStd::ps_onChangedMainInfoAreaFloating);
}
void SwiftGuiStd::initialDataReads()
{
this->setContextAvailability();
if (!this->m_coreAvailable)
{
CLogMessage(this).error("No initial data read as network context is not available");
return;
}
this->ps_reloadOwnAircraft(); // init read, independent of traffic network
CLogMessage(this).info("Initial data read");
}
void SwiftGuiStd::startUpdateTimersWhenConnected()
{
this->ui->comp_MainInfoArea->getAtcStationComponent()->setUpdateIntervalSeconds(this->ui->comp_MainInfoArea->getSettingsComponent()->getAtcUpdateIntervalSeconds());
this->ui->comp_MainInfoArea->getAircraftComponent()->setUpdateIntervalSeconds(this->ui->comp_MainInfoArea->getSettingsComponent()->getAircraftUpdateIntervalSeconds());
this->ui->comp_MainInfoArea->getUserComponent()->setUpdateIntervalSeconds(this->ui->comp_MainInfoArea->getSettingsComponent()->getUsersUpdateIntervalSeconds());
}
void SwiftGuiStd::stopUpdateTimersWhenDisconnected()
{
this->ui->comp_MainInfoArea->getAtcStationComponent()->stopTimer();
this->ui->comp_MainInfoArea->getAircraftComponent()->stopTimer();
this->ui->comp_MainInfoArea->getUserComponent()->stopTimer();
}
void SwiftGuiStd::stopAllTimers(bool disconnectSignalSlots)
{
this->m_timerContextWatchdog->stop();
this->stopUpdateTimersWhenDisconnected();
if (!disconnectSignalSlots) { return; }
this->disconnect(this->m_timerContextWatchdog);
}

View File

@@ -0,0 +1,145 @@
/* Copyright (C) 2013
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#include "swiftguistd.h"
#include "ui_swiftguistd.h"
#include "blackcore/datacache.h"
#include "blackcore/settingscache.h"
#include "blackgui/stylesheetutility.h"
#include "blackgui/components/settingscomponent.h"
#include "blackgui/components/logcomponent.h"
#include "blackmisc/statusmessagelist.h"
#include "blackmisc/aviation/altitude.h"
#include "blackmisc/logmessage.h"
#include <QPoint>
#include <QMenu>
#include <QDesktopServices>
#include <QProcess>
#include <QFontDialog>
using namespace BlackGui;
using namespace BlackCore;
using namespace BlackMisc;
using namespace BlackMisc::PhysicalQuantities;
using namespace BlackMisc::Aviation;
/*
* Menu clicked
*/
void SwiftGuiStd::ps_onMenuClicked()
{
QObject *sender = QObject::sender();
if (sender == this->ui->menu_TestLocationsEDRY)
{
this->setTestPosition("N 049° 18' 17", "E 008° 27' 05", CAltitude(312, CAltitude::MeanSeaLevel, CLengthUnit::ft()));
}
else if (sender == this->ui->menu_TestLocationsEDNX)
{
this->setTestPosition("N 048° 14 22", "E 011° 33 41", CAltitude(486, CAltitude::MeanSeaLevel, CLengthUnit::m()));
}
else if (sender == this->ui->menu_TestLocationsEDDM)
{
this->setTestPosition("N 048° 21 14", "E 011° 47 10", CAltitude(448, CAltitude::MeanSeaLevel, CLengthUnit::m()));
}
else if (sender == this->ui->menu_TestLocationsEDDF)
{
this->setTestPosition("N 50° 2 0", "E 8° 34 14", CAltitude(100, CAltitude::MeanSeaLevel, CLengthUnit::m()));
}
else if (sender == this->ui->menu_TestLocationsLOWW)
{
this->setTestPosition("N 40° 7 6.3588", "E 16° 33 39.924", CAltitude(100, CAltitude::MeanSeaLevel, CLengthUnit::m()));
}
else if (sender == this->ui->menu_FileReloadStyleSheets)
{
CStyleSheetUtility::instance().read();
}
else if (sender == this->ui->menu_WindowFont)
{
this->ps_setMainPageToInfoArea();
this->ui->comp_MainInfoArea->selectSettingsTab(BlackGui::Components::CSettingsComponent::SettingTabGui);
}
else if (sender == this->ui->menu_WindowMinimize)
{
this->showMinimized();
}
else if (sender == this->ui->menu_WindowToggleOnTop)
{
this->ps_toogleWindowStayOnTop();
}
else if (sender == this->ui->menu_FileExit)
{
CLogMessage(this).info("Closing");
this->close();
}
else if (sender == this->ui->menu_FileSettingsDirectory)
{
QString path(QDir::toNativeSeparators(CSettingsCache::persistentStore()));
QDesktopServices::openUrl(QUrl("file:///" + path));
}
else if (sender == this->ui->menu_FileCacheDirectory)
{
QString path(QDir::toNativeSeparators(CDataCache::persistentStore()));
QDesktopServices::openUrl(QUrl("file:///" + path));
}
else if (sender == this->ui->menu_FileResetSettings)
{
//! \todo
}
else if (sender == this->ui->menu_Internals)
{
this->ui->sw_MainMiddle->setCurrentIndex(MainPageInternals);
}
else if (sender == this->ui->menu_InternalsMetatypes)
{
QString metadata(getAllUserMetatypesTypes());
this->ui->comp_MainInfoArea->getLogComponent()->appendPlainTextToConsole(metadata);
this->displayConsole();
}
else if (sender == this->ui->menu_InternalsSetup)
{
QString setup(this->m_setup.get().convertToQString("\n", true));
this->ui->comp_MainInfoArea->getLogComponent()->appendPlainTextToConsole(setup);
this->displayConsole();
}
else if (sender == this->ui->menu_InternalsCompileInfo)
{
QString project(CProject::convertToQString("\n"));
this->ui->comp_MainInfoArea->getLogComponent()->appendPlainTextToConsole(project);
this->displayConsole();
}
else if (sender == this->ui->menu_InternalsEnvVars)
{
QString project(CProject::getEnvironmentVariables());
this->ui->comp_MainInfoArea->getLogComponent()->appendPlainTextToConsole(project);
this->displayConsole();
}
else if (sender == this->ui->menu_InternalsDisplayCachedFiles)
{
//! \todo
this->displayConsole();
}
else if (sender == this->ui->menu_InternalsDeleteCachedFiles)
{
//! \todo
this->displayConsole();
}
}
void SwiftGuiStd::initDynamicMenus()
{
Q_ASSERT(this->ui->menu_InfoAreas);
Q_ASSERT(this->ui->comp_MainInfoArea);
this->ui->menu_InfoAreas->addActions(this->ui->comp_MainInfoArea->getInfoAreaSelectActions(this->ui->menu_InfoAreas));
}
void SwiftGuiStd::initMenuIcons()
{
this->ui->menu_WindowMinimize->setIcon(this->style()->standardIcon(QStyle::SP_TitleBarMinButton));
}