From b8a0be9543d49a294f1ff84652a05d97284f5a8e Mon Sep 17 00:00:00 2001 From: Oliver Knoll Date: Sun, 28 Apr 2024 22:29:49 +0200 Subject: [PATCH] Feature/msfs shortcuts 2 (#133) * Write dialog titles in Title Case - Common titles: * Read Error * Write Error * Import Error * Export Error * Logbook Error * Update * Fix compilation: add missing includes * Ensure that aircraft type is non-null initially - Otherwise rejected during persistence ("type must not be null") * Remove duplicate keyboard sequences upon settings changes * Update layout * Improve Qt key sequence parsing * Define default keyboard shortcuts --- CHANGELOG.md | 14 +- src/Kernel/src/Settings.cpp | 14 +- src/Model/include/Model/AircraftHandleData.h | 2 - src/Model/include/Model/AircraftType.h | 2 +- src/Model/include/Model/EngineData.h | 3 - src/Model/include/Model/LightData.h | 3 - src/Model/include/Model/PositionData.h | 3 - .../include/Model/PrimaryFlightControlData.h | 3 - .../Model/SecondaryFlightControlData.h | 3 - src/Model/src/PositionData.cpp | 2 - .../src/Service/DatabaseService.cpp | 2 +- .../src/Connect/AbstractSkyConnect.cpp | 12 +- .../src/Flight/FlightExportPluginBase.cpp | 2 +- .../src/Flight/FlightImportPluginBase.cpp | 6 +- .../src/Location/LocationExportPluginBase.cpp | 2 +- .../src/Location/LocationImportPluginBase.cpp | 4 +- .../src/Module/AbstractModule.cpp | 2 +- .../src/Event/InputEvent.cpp | 282 ++++++++++++++---- .../src/Event/InputEvent.h | 4 +- .../src/Event/SimConnectEvent.h | 2 +- .../src/MSFSSimConnectPlugin.cpp | 4 +- .../Import/CsvImport/src/CsvImportPlugin.cpp | 2 - .../Import/GpxImport/src/GpxImportPlugin.cpp | 1 - .../Import/IgcImport/src/IgcImportPlugin.cpp | 1 - .../Import/KmlImport/src/KmlImportPlugin.cpp | 1 - .../SdLogImport/src/SdLogImportPlugin.cpp | 2 - .../Module/Formation/src/FormationPlugin.cpp | 2 +- .../Module/Logbook/src/LogbookPlugin.cpp | 12 +- .../Module/Logbook/src/LogbookWidget.cpp | 2 +- .../src/Dialog/LogbookBackupDialog.cpp | 2 +- .../src/Dialog/SettingsDialog.cpp | 101 ++++++- src/UserInterface/src/Dialog/SettingsDialog.h | 23 ++ .../src/Dialog/SettingsDialog.ui | 4 +- src/UserInterface/src/MainWindow.cpp | 8 +- 34 files changed, 391 insertions(+), 141 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d6bb3724e..81ebad5f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,12 +4,13 @@ ### New Features - Keyboard shortcuts can be defined and triggered within the flight simulator, in order to: - * Toggle recording / replay - * Pause / Stop - * Skip forward/backward - * Skip to begin - * The shortcuts can be defined in the Sky Dolly application settings -- Desktop notifications indicate whether recording has started, paused/resumed and stopped + * Toggle recording (CTRL+R) and replay (CTRL+P) + * Pause (ALT+P) and Stop (CTRL+S) + * Skip forward (CTRL+.) and backward (CTRL+,) + * Skip to begin (CTRL+PageUp) and end (CTRL+PageDown) + * The shortcuts can be defined in the Sky Dolly application settings (no restart required) +- Desktop notifications indicate whether recording has started, paused/resumed or stopped + * In order to make desktop notifications visible when the flight simulator is in fullscreen adjust the corresponding notification rules in the Windows settings (-> Notification Assistant) ### Improvements - The default logbook name is now *Sky Dolly Logbook* @@ -28,6 +29,7 @@ * The default import CSV format is now: *Flightradar24* * The default export CSV format is now: *Position and attitude* * Use the Sky Dolly logbook import & export instead +- Dialog titles are now consistently in Title Case and streamlined ("Write Error", "Read Error", ...) ### Bug Fixes - KML export: the _first_ position point is now properly exported as well diff --git a/src/Kernel/src/Settings.cpp b/src/Kernel/src/Settings.cpp index 49daa3830..2987b736d 100644 --- a/src/Kernel/src/Settings.cpp +++ b/src/Kernel/src/Settings.cpp @@ -139,15 +139,15 @@ struct SettingsPrivate static constexpr int DefaultPreviewInfoDialogCount {3}; static constexpr int PreviewInfoDialogBase {150}; - // TODO Select proper defaults (non-assigned by default in MSFS) static inline const QKeySequence DefaultRecordShortcut {"Ctrl+R"}; - static inline const QKeySequence DefaultReplayShortcut {"Ctrl+E"}; - static inline const QKeySequence DefaultPauseShortcut {"Ctrl+P"}; + static inline const QKeySequence DefaultReplayShortcut {"Ctrl+P"}; + static inline const QKeySequence DefaultPauseShortcut {"Alt+P"}; static inline const QKeySequence DefaultStopShortcut {"Ctrl+S"}; - static inline const QKeySequence DefaultBackwardShortcut {"Ctrl+B"}; - static inline const QKeySequence DefaultForwardShortcut {"Ctrl+F"}; - static inline const QKeySequence DefaultBeginShortcut {"Ctrl+T"}; - static inline const QKeySequence DefaultEndShortcut {"Ctrl+Shift+T"}; + static inline const QKeySequence DefaultBackwardShortcut {"Ctrl+,"}; + static inline const QKeySequence DefaultForwardShortcut {"Ctrl+."}; + // TODO Find good default keys that are not already taken my the MSFS default keyboard layout + static inline const QKeySequence DefaultBeginShortcut {"Ctrl+PgUp"}; + static inline const QKeySequence DefaultEndShortcut {"Ctrl+PgDown"}; static inline const FlightSimulatorShortcuts DefaultFlightSimulatorShortcuts { DefaultRecordShortcut, DefaultReplayShortcut, diff --git a/src/Model/include/Model/AircraftHandleData.h b/src/Model/include/Model/AircraftHandleData.h index 8b82e2ca6..503642c6d 100644 --- a/src/Model/include/Model/AircraftHandleData.h +++ b/src/Model/include/Model/AircraftHandleData.h @@ -27,8 +27,6 @@ #include -#include -#include #include "TimeVariableData.h" #include "ModelLib.h" diff --git a/src/Model/include/Model/AircraftType.h b/src/Model/include/Model/AircraftType.h index d9ffc6e4b..a5cbfd2b4 100644 --- a/src/Model/include/Model/AircraftType.h +++ b/src/Model/include/Model/AircraftType.h @@ -37,7 +37,7 @@ struct MODEL_API AircraftType final * The aircraft type, e.g. "Pitts Special". This is really the SimConnect "container title" * which is also used to spawn AI aircraft. */ - QString type; + QString type {"-"}; /*! * The aircraft category: diff --git a/src/Model/include/Model/EngineData.h b/src/Model/include/Model/EngineData.h index 667bd98d6..e502bdd4e 100644 --- a/src/Model/include/Model/EngineData.h +++ b/src/Model/include/Model/EngineData.h @@ -27,9 +27,6 @@ #include -#include -#include - #include "TimeVariableData.h" #include "ModelLib.h" diff --git a/src/Model/include/Model/LightData.h b/src/Model/include/Model/LightData.h index ae4472c2d..05dd0301d 100644 --- a/src/Model/include/Model/LightData.h +++ b/src/Model/include/Model/LightData.h @@ -25,9 +25,6 @@ #ifndef LIGHTDATA_H #define LIGHTDATA_H -#include -#include - #include "SimType.h" #include "TimeVariableData.h" #include "ModelLib.h" diff --git a/src/Model/include/Model/PositionData.h b/src/Model/include/Model/PositionData.h index 2163c4aad..3f93b76da 100644 --- a/src/Model/include/Model/PositionData.h +++ b/src/Model/include/Model/PositionData.h @@ -25,9 +25,6 @@ #ifndef POSITIONDATA_H #define POSITIONDATA_H -#include -#include - #include "TimeVariableData.h" #include "ModelLib.h" diff --git a/src/Model/include/Model/PrimaryFlightControlData.h b/src/Model/include/Model/PrimaryFlightControlData.h index 29bb82d67..52be26d86 100644 --- a/src/Model/include/Model/PrimaryFlightControlData.h +++ b/src/Model/include/Model/PrimaryFlightControlData.h @@ -27,9 +27,6 @@ #include -#include -#include - #include "TimeVariableData.h" #include "ModelLib.h" diff --git a/src/Model/include/Model/SecondaryFlightControlData.h b/src/Model/include/Model/SecondaryFlightControlData.h index 870e3a00f..20632a837 100644 --- a/src/Model/include/Model/SecondaryFlightControlData.h +++ b/src/Model/include/Model/SecondaryFlightControlData.h @@ -27,9 +27,6 @@ #include -#include -#include - #include "TimeVariableData.h" #include "ModelLib.h" diff --git a/src/Model/src/PositionData.cpp b/src/Model/src/PositionData.cpp index b38ec001b..6b7107831 100644 --- a/src/Model/src/PositionData.cpp +++ b/src/Model/src/PositionData.cpp @@ -22,8 +22,6 @@ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -#include - #include "SimType.h" #include "PositionData.h" diff --git a/src/Persistence/src/Service/DatabaseService.cpp b/src/Persistence/src/Service/DatabaseService.cpp index 5149b5ea9..f73584949 100644 --- a/src/Persistence/src/Service/DatabaseService.cpp +++ b/src/Persistence/src/Service/DatabaseService.cpp @@ -328,7 +328,7 @@ QString DatabaseService::getNewLogbookPath(QWidget *parent) noexcept newLogbookPath = logbookDirectoryPath + "/" % fileInfo.fileName() % Const::DotLogbookExtension; retry = false; } else { - QMessageBox::information(parent, QCoreApplication::translate("DatabaseService", "Database exists"), + QMessageBox::information(parent, QCoreApplication::translate("DatabaseService", "Database Exists"), QCoreApplication::translate("DatabaseService", "The logbook %1 already exists. Please choose another path.").arg(QDir::toNativeSeparators(logbookDirectoryPath))); } } else { diff --git a/src/PluginManager/src/Connect/AbstractSkyConnect.cpp b/src/PluginManager/src/Connect/AbstractSkyConnect.cpp index 487460e1d..9822647f0 100644 --- a/src/PluginManager/src/Connect/AbstractSkyConnect.cpp +++ b/src/PluginManager/src/Connect/AbstractSkyConnect.cpp @@ -751,21 +751,17 @@ void AbstractSkyConnect::tryFirstConnectAndSetup() noexcept bool AbstractSkyConnect::retryWithReconnect(const std::function &func) { int nofAttempts {2}; - bool ok {true}; - while (nofAttempts > 0) { + bool ok {false}; + while (!ok && nofAttempts > 0) { ok = func(); - --nofAttempts; if (!ok && nofAttempts > 0) { #ifdef DEBUG qDebug() << "AbstractSkyConnect::retryWithReconnect: previous connection is stale, RETRY with reconnect" << nofAttempts << "more time(s)..."; #endif // Automatically reconnect in case the server crashed // previously (without sending a "quit" message) - if (!connectWithSim()) { - nofAttempts = 0; - } - } else { - nofAttempts = 0; + connectWithSim(); + --nofAttempts; } } return ok; diff --git a/src/PluginManager/src/Flight/FlightExportPluginBase.cpp b/src/PluginManager/src/Flight/FlightExportPluginBase.cpp index aaf95f063..f997226d1 100644 --- a/src/PluginManager/src/Flight/FlightExportPluginBase.cpp +++ b/src/PluginManager/src/Flight/FlightExportPluginBase.cpp @@ -154,7 +154,7 @@ bool FlightExportPluginBase::exportFlight(const Flight &flight, const QString &f } } } else { - QMessageBox::critical(PluginBase::getParentWidget(), tr("Export error"), tr("An error occured during export into file %1.").arg(QDir::toNativeSeparators(filePath))); + QMessageBox::critical(PluginBase::getParentWidget(), tr("Export Error"), tr("An error occured during export into file %1.").arg(QDir::toNativeSeparators(filePath))); } return ok; diff --git a/src/PluginManager/src/Flight/FlightImportPluginBase.cpp b/src/PluginManager/src/Flight/FlightImportPluginBase.cpp index 218a703a0..adf77f241 100644 --- a/src/PluginManager/src/Flight/FlightImportPluginBase.cpp +++ b/src/PluginManager/src/Flight/FlightImportPluginBase.cpp @@ -118,10 +118,10 @@ bool FlightImportPluginBase::importFlights(Flight &flight) noexcept qDebug() << QFileInfo(selectedPath).fileName() << "import" << (ok ? "SUCCESS" : "FAIL") << "in" << timer.elapsed() << "ms"; #endif if (!ok && !baseSettings.isImportDirectoryEnabled()) { - QMessageBox::critical(PluginBase::getParentWidget(), tr("Import error"), tr("The file %1 could not be imported.").arg(selectedPath)); + QMessageBox::critical(PluginBase::getParentWidget(), tr("Import Error"), tr("The file %1 could not be imported.").arg(selectedPath)); } } else { - QMessageBox::critical(PluginBase::getParentWidget(), tr("Import error"), + QMessageBox::critical(PluginBase::getParentWidget(), tr("Import Error"), tr("The selected aircraft '%1' is not a known aircraft in the logbook. " "Check for spelling errors or record a flight with this aircraft first.").arg(d->selectedAircraftType.type)); } @@ -401,7 +401,7 @@ void FlightImportPluginBase::confirmImportError(const QString &filePath, bool &i messageBox->setIcon(QMessageBox::Critical); QPushButton *proceedButton = messageBox->addButton(tr("&Proceed"), QMessageBox::AcceptRole); QPushButton *ignoreAllButton = messageBox->addButton(tr("&Ignore All Failures"), QMessageBox::YesRole); - messageBox->setWindowTitle(tr("Import Failure")); + messageBox->setWindowTitle(tr("Import Error")); messageBox->setText(tr("The file %1 could not be imported. Do you want to proceed with the remaining files in directory %2?").arg(fileInfo.fileName(), fileInfo.dir().dirName())); messageBox->setInformativeText(tr("Aborting will keep the already successfully imported flights and aircraft.")); messageBox->setStandardButtons(QMessageBox::Cancel); diff --git a/src/PluginManager/src/Location/LocationExportPluginBase.cpp b/src/PluginManager/src/Location/LocationExportPluginBase.cpp index 93bc85822..4b82df7a7 100644 --- a/src/PluginManager/src/Location/LocationExportPluginBase.cpp +++ b/src/PluginManager/src/Location/LocationExportPluginBase.cpp @@ -132,7 +132,7 @@ bool LocationExportPluginBase::exportLocations(const std::vector &loca QDesktopServices::openUrl(QUrl(fileUrl)); } } else { - QMessageBox::critical(PluginBase::getParentWidget(), tr("Export error"), tr("An error occured during export into file %1.").arg(QDir::toNativeSeparators(filePath))); + QMessageBox::critical(PluginBase::getParentWidget(), tr("Export Error"), tr("An error occured during export into file %1.").arg(QDir::toNativeSeparators(filePath))); } return ok; diff --git a/src/PluginManager/src/Location/LocationImportPluginBase.cpp b/src/PluginManager/src/Location/LocationImportPluginBase.cpp index d7f0e8987..d1149b95b 100644 --- a/src/PluginManager/src/Location/LocationImportPluginBase.cpp +++ b/src/PluginManager/src/Location/LocationImportPluginBase.cpp @@ -92,7 +92,7 @@ bool LocationImportPluginBase::importLocations() noexcept qDebug() << QFileInfo(selectedPath).fileName() << "import" << (ok ? "SUCCESS" : "FAIL") << "in" << timer.elapsed() << "ms"; #endif if (!ok && !baseSettings.isImportDirectoryEnabled()) { - QMessageBox::critical(PluginBase::getParentWidget(), tr("Import error"), tr("The file %1 could not be imported.").arg(selectedPath)); + QMessageBox::critical(PluginBase::getParentWidget(), tr("Import Error"), tr("The file %1 could not be imported.").arg(selectedPath)); } } @@ -143,7 +143,7 @@ bool LocationImportPluginBase::importLocations(const QStringList &filePaths) noe messageBox->setIcon(QMessageBox::Critical); QPushButton *proceedButton = messageBox->addButton(tr("&Proceed"), QMessageBox::AcceptRole); QPushButton *ignoreAllButton = messageBox->addButton(tr("&Ignore All Failures"), QMessageBox::YesRole); - messageBox->setWindowTitle(tr("Import failure")); + messageBox->setWindowTitle(tr("Import Error")); messageBox->setText(tr("The file %1 could not be imported. Do you want to proceed with the remaining files in directory %2?").arg(fileInfo.fileName(), fileInfo.dir().dirName())); messageBox->setInformativeText(tr("Aborting will keep the already successfully imported flights and aircraft.")); messageBox->setStandardButtons(QMessageBox::Cancel); diff --git a/src/PluginManager/src/Module/AbstractModule.cpp b/src/PluginManager/src/Module/AbstractModule.cpp index fa3bb33f9..5266c63b4 100644 --- a/src/PluginManager/src/Module/AbstractModule.cpp +++ b/src/PluginManager/src/Module/AbstractModule.cpp @@ -144,7 +144,7 @@ void AbstractModule::onRecordingStopped() noexcept if (!ok) { const PersistenceManager &persistenceManager = PersistenceManager::getInstance(); const QString logbookPath = QDir::toNativeSeparators(persistenceManager.getLogbookPath()); - QMessageBox::critical(getWidget(), tr("Flight error"), tr("The flight could not be stored into the logbook %1.").arg(logbookPath)); + QMessageBox::critical(getWidget(), tr("Write Error"), tr("The flight could not be stored into the logbook %1.").arg(logbookPath)); } } diff --git a/src/Plugins/Connect/MSFSSimConnectPlugin/src/Event/InputEvent.cpp b/src/Plugins/Connect/MSFSSimConnectPlugin/src/Event/InputEvent.cpp index d7339c05b..521c56440 100644 --- a/src/Plugins/Connect/MSFSSimConnectPlugin/src/Event/InputEvent.cpp +++ b/src/Plugins/Connect/MSFSSimConnectPlugin/src/Event/InputEvent.cpp @@ -29,6 +29,7 @@ #include #include +#include #ifdef DEBUG #include #endif @@ -47,6 +48,21 @@ namespace enum struct NotificationGroup: ::SIMCONNECT_NOTIFICATION_GROUP_ID { ShortcutsGroup }; + + enum struct KeySequenceState: std::uint32_t + { + None = 0x0, + Record = 0x1, + Replay = 0x2, + Pause = 0x4, + Stop = 0x8, + Forward = 0x8, + Backward = 0x10, + Begin = 0x20, + End = 0x40, + All = 0xffffffff + }; + Q_DECLARE_FLAGS(KeySequenceStates, KeySequenceState) } // PRIVATE @@ -54,18 +70,79 @@ namespace struct InputEventPrivate { bool isInitialised {false}; + KeySequenceStates keySequenceStates {KeySequenceState::None}; + + // https://docs.flightsimulator.com/html/Programming_Tools/SimConnect/API_Reference/InputEvents/SimConnect_MapInputEventToClientEvent_EX1.htm + const std::unordered_map qtToMSFS { + { Qt::Key_Backspace, "Backspace" }, + { Qt::Key_Tab, "Tab" }, + // Note: the SimConnect documentation says "VK_Enter", but it is really "Enter" + { Qt::Key_Enter, "Enter" }, + { Qt::Key_Return, "Enter" }, + { Qt::Key_Pause, "VK_PAUSE" }, + { Qt::Key_CapsLock, "Caps_Lock" }, + { Qt::Key_Escape, "Esc" }, + { Qt::Key_Space, "Space" }, + { Qt::Key_PageUp, "VK_PRIOR" }, + { Qt::Key_PageDown, "VK_NEXT" }, + { Qt::Key_End, "VK_END" }, + { Qt::Key_Home, "VK_HOME" }, + { Qt::Key_Left, "VK_LEFT" }, + { Qt::Key_Up, "VK_UP" }, + { Qt::Key_Right, "VK_RIGHT" }, + { Qt::Key_Down, "VK_DOWN" }, + { Qt::Key_Select, "VK_SELECT" }, + { Qt::Key_Print, "VK_PRINT" }, + { Qt::Key_Execute, "VK_EXECUTE" }, + { Qt::Key_SysReq, "Sys_Req" }, + { Qt::Key_Insert, "VK_INSERT" }, + { Qt::Key_Delete, "VK_DELETE" }, + { Qt::Key_Help, "VK_HELP" }, + { Qt::Key_Meta, "VK_LWIN" }, + { Qt::Key_Sleep, "VK_SLEEP" }, + { Qt::Key_multiply, "VK_MULTIPLY" }, + { Qt::Key_Asterisk, "VK_MULTIPLY" }, + { Qt::Key_division, "VK_DIVIDE" }, + { Qt::Key_Pause, "Pause" }, + { Qt::Key_ScrollLock, "VK_SCROLL" }, + { Qt::Key_Shift, "VK_LSHIFT" }, + { Qt::Key_Control, "VK_LCONTROL" }, + { Qt::Key_Alt, "VK_LMENU" }, + { Qt::Key_AltGr, "VK_RMENU" }, + { Qt::Key_VolumeMute, "VK_VOLUME_MUTE" }, + { Qt::Key_VolumeDown, "VK_VOLUME_DOWN" }, + { Qt::Key_VolumeUp, "VK_VOLUME_UP" }, + { Qt::Key_MediaNext, "VK_MEDIA_NEXT_TRACK" }, + { Qt::Key_MediaPrevious, "VK_MEDIA_PREV_TRACK" }, + { Qt::Key_MediaStop, "VK_MEDIA_STOP" }, + { Qt::Key_MediaTogglePlayPause, "VK_MEDIA_PLAY_PAUSE" }, + { Qt::Key_Semicolon, "VK_SEMICOLON" }, + { Qt::Key_Plus, "VK_PLUS" }, + { Qt::Key_Comma, "VK_COMMA" }, + { Qt::Key_Minus, "VK_MINUS" }, + { Qt::Key_Period, "VK_PERIOD" }, + { Qt::Key_Slash, "VK_SLASH" }, + { Qt::Key_AsciiTilde, "VK_TILDE" }, + { Qt::Key_BracketLeft, "VK_LBRACKET" }, + { Qt::Key_Backslash, "VK_BACKSLASH" }, + { Qt::Key_BracketRight, "VK_RBRACKET" }, + { Qt::Key_QuoteDbl, "VK_QUOTE" }, + { Qt::Key_Play, "VK_PLAY" }, + { Qt::Key_Zoom, "VK_ZOOM" } + }; - // https://docs.flightsimulator.com/html/Programming_Tools/SimConnect/API_Reference/Events_And_Data/SimConnect_MapInputEventToClientEvent.htm - static const inline std::unordered_map qtToMSFS { - { "Alt", "VK_LMENU" }, - { "Ctrl", "VK_LCONTROL" }, - { "Shift", "VK_LSHIFT" }, - { "Up", "VK_UP" }, - { "Down", "VK_DOWN" }, - { "Left", "VK_LEFT" }, - { "Right", "VK_RIGHT" }, - { "PgUp", "VK_PRIOR" }, - { "PgDown", "VK_NEXT" } + const std::unordered_map qtModifierToMSFS { + { Qt::ShiftModifier, "VK_LSHIFT" }, + { Qt::ControlModifier, "VK_LCONTROL" }, + { Qt::AltModifier, "VK_LMENU" }, + { Qt::MetaModifier, "VK_LWIN" } + }; + + const std::unordered_map numpadify { + { "VK_PLUS", "VK_ADD" }, + { "VK_MINUS", "VK_SUBTRACT" }, + { "VK_PERIOD", "VK_DECIMAL" }, + { "VK_SLASH", "VK_DIVIDE" } }; }; @@ -81,56 +158,81 @@ bool InputEvent::setup(HANDLE simConnectHandle, const FlightSimulatorShortcuts & { HRESULT result {S_OK}; if (d->isInitialised) { - result = clear(simConnectHandle); + result = clear(simConnectHandle) ? S_OK : S_FALSE; } + QByteArray shortcut; // Recording - QByteArray shortcut = toMSFSShortcut(shortcuts.record); - result |= ::SimConnect_MapClientEventToSimEvent(simConnectHandle, Enum::underly(SimConnectEvent::Event::CustomRecording), "Custom.Recording"); - result |= ::SimConnect_MapInputEventToClientEvent(simConnectHandle, Enum::underly(Input::SkyDollyControl), shortcut, Enum::underly(SimConnectEvent::Event::CustomRecording)); - result |= ::SimConnect_AddClientEventToNotificationGroup(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomRecording)); + if (shortcuts.record.count() > 0) { + shortcut = toMSFSShortcut(shortcuts.record); + result |= ::SimConnect_MapClientEventToSimEvent(simConnectHandle, Enum::underly(SimConnectEvent::Event::CustomRecord), "Custom.Recording"); + result |= ::SimConnect_MapInputEventToClientEvent_EX1(simConnectHandle, Enum::underly(Input::SkyDollyControl), shortcut, Enum::underly(SimConnectEvent::Event::CustomRecord)); + result |= ::SimConnect_AddClientEventToNotificationGroup(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomRecord)); + d->keySequenceStates.setFlag(::KeySequenceState::Record); + } // Replay - shortcut = toMSFSShortcut(shortcuts.replay); - result |= ::SimConnect_MapClientEventToSimEvent(simConnectHandle, Enum::underly(SimConnectEvent::Event::CustomReplay), "Custom.Replay"); - result |= ::SimConnect_MapInputEventToClientEvent(simConnectHandle, Enum::underly(Input::SkyDollyControl), shortcut, Enum::underly(SimConnectEvent::Event::CustomReplay)); - result |= ::SimConnect_AddClientEventToNotificationGroup(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomReplay)); + if (shortcuts.replay.count() > 0) { + shortcut = toMSFSShortcut(shortcuts.replay); + result |= ::SimConnect_MapClientEventToSimEvent(simConnectHandle, Enum::underly(SimConnectEvent::Event::CustomReplay), "Custom.Replay"); + result |= ::SimConnect_MapInputEventToClientEvent_EX1(simConnectHandle, Enum::underly(Input::SkyDollyControl), shortcut, Enum::underly(SimConnectEvent::Event::CustomReplay)); + result |= ::SimConnect_AddClientEventToNotificationGroup(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomReplay)); + d->keySequenceStates.setFlag(::KeySequenceState::Replay); + } // Pause - shortcut = toMSFSShortcut(shortcuts.pause); - result |= ::SimConnect_MapClientEventToSimEvent(simConnectHandle, Enum::underly(SimConnectEvent::Event::CustomPause), "Custom.Pause"); - result |= ::SimConnect_MapInputEventToClientEvent(simConnectHandle, Enum::underly(Input::SkyDollyControl), shortcut, Enum::underly(SimConnectEvent::Event::CustomPause)); - result |= ::SimConnect_AddClientEventToNotificationGroup(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomPause)); + if (shortcuts.pause.count() > 0) { + shortcut = toMSFSShortcut(shortcuts.pause); + result |= ::SimConnect_MapClientEventToSimEvent(simConnectHandle, Enum::underly(SimConnectEvent::Event::CustomPause), "Custom.Pause"); + result |= ::SimConnect_MapInputEventToClientEvent_EX1(simConnectHandle, Enum::underly(Input::SkyDollyControl), shortcut, Enum::underly(SimConnectEvent::Event::CustomPause)); + result |= ::SimConnect_AddClientEventToNotificationGroup(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomPause)); + d->keySequenceStates.setFlag(::KeySequenceState::Pause); + } // Stop - shortcut = toMSFSShortcut(shortcuts.stop); - result |= ::SimConnect_MapClientEventToSimEvent(simConnectHandle, Enum::underly(SimConnectEvent::Event::CustomStop), "Custom.Stop"); - result |= ::SimConnect_MapInputEventToClientEvent(simConnectHandle, Enum::underly(Input::SkyDollyControl), shortcut, Enum::underly(SimConnectEvent::Event::CustomStop)); - result |= ::SimConnect_AddClientEventToNotificationGroup(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomStop)); + if (shortcuts.stop.count() > 0) { + shortcut = toMSFSShortcut(shortcuts.stop); + result |= ::SimConnect_MapClientEventToSimEvent(simConnectHandle, Enum::underly(SimConnectEvent::Event::CustomStop), "Custom.Stop"); + result |= ::SimConnect_MapInputEventToClientEvent_EX1(simConnectHandle, Enum::underly(Input::SkyDollyControl), shortcut, Enum::underly(SimConnectEvent::Event::CustomStop)); + result |= ::SimConnect_AddClientEventToNotificationGroup(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomStop)); + d->keySequenceStates.setFlag(::KeySequenceState::Stop); + } // Backward - shortcut = toMSFSShortcut(shortcuts.backward); - result |= ::SimConnect_MapClientEventToSimEvent(simConnectHandle, Enum::underly(SimConnectEvent::Event::CustomBackward), "Custom.Backward"); - result |= ::SimConnect_MapInputEventToClientEvent(simConnectHandle, Enum::underly(Input::SkyDollyControl), shortcut, Enum::underly(SimConnectEvent::Event::CustomBackward)); - result |= ::SimConnect_AddClientEventToNotificationGroup(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomBackward)); + if (shortcuts.backward.count() > 0) { + shortcut = toMSFSShortcut(shortcuts.backward); + result |= ::SimConnect_MapClientEventToSimEvent(simConnectHandle, Enum::underly(SimConnectEvent::Event::CustomBackward), "Custom.Backward"); + result |= ::SimConnect_MapInputEventToClientEvent_EX1(simConnectHandle, Enum::underly(Input::SkyDollyControl), shortcut, Enum::underly(SimConnectEvent::Event::CustomBackward)); + result |= ::SimConnect_AddClientEventToNotificationGroup(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomBackward)); + d->keySequenceStates.setFlag(::KeySequenceState::Backward); + } // Forward - shortcut = toMSFSShortcut(shortcuts.forward); - result |= ::SimConnect_MapClientEventToSimEvent(simConnectHandle, Enum::underly(SimConnectEvent::Event::CustomForward), "Custom.Forward"); - result |= ::SimConnect_MapInputEventToClientEvent(simConnectHandle, Enum::underly(Input::SkyDollyControl), shortcut, Enum::underly(SimConnectEvent::Event::CustomForward)); - result |= ::SimConnect_AddClientEventToNotificationGroup(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomForward)); + if (shortcuts.forward.count() > 0) { + shortcut = toMSFSShortcut(shortcuts.forward); + result |= ::SimConnect_MapClientEventToSimEvent(simConnectHandle, Enum::underly(SimConnectEvent::Event::CustomForward), "Custom.Forward"); + result |= ::SimConnect_MapInputEventToClientEvent_EX1(simConnectHandle, Enum::underly(Input::SkyDollyControl), shortcut, Enum::underly(SimConnectEvent::Event::CustomForward)); + result |= ::SimConnect_AddClientEventToNotificationGroup(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomForward)); + d->keySequenceStates.setFlag(::KeySequenceState::Forward); + } // Begin - shortcut = toMSFSShortcut(shortcuts.begin); - result |= ::SimConnect_MapClientEventToSimEvent(simConnectHandle, Enum::underly(SimConnectEvent::Event::CustomBegin), "Custom.Begin"); - result |= ::SimConnect_MapInputEventToClientEvent(simConnectHandle, Enum::underly(Input::SkyDollyControl), shortcut, Enum::underly(SimConnectEvent::Event::CustomBegin)); - result |= ::SimConnect_AddClientEventToNotificationGroup(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomBegin)); + if (shortcuts.begin.count() > 0) { + shortcut = toMSFSShortcut(shortcuts.begin); + result |= ::SimConnect_MapClientEventToSimEvent(simConnectHandle, Enum::underly(SimConnectEvent::Event::CustomBegin), "Custom.Begin"); + result |= ::SimConnect_MapInputEventToClientEvent_EX1(simConnectHandle, Enum::underly(Input::SkyDollyControl), shortcut, Enum::underly(SimConnectEvent::Event::CustomBegin)); + result |= ::SimConnect_AddClientEventToNotificationGroup(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomBegin)); + d->keySequenceStates.setFlag(::KeySequenceState::Begin); + } // End - shortcut = toMSFSShortcut(shortcuts.end); - result |= ::SimConnect_MapClientEventToSimEvent(simConnectHandle, Enum::underly(SimConnectEvent::Event::CustomEnd), "Custom.End"); - result |= ::SimConnect_MapInputEventToClientEvent(simConnectHandle, Enum::underly(Input::SkyDollyControl), shortcut, Enum::underly(SimConnectEvent::Event::CustomEnd)); - result |= ::SimConnect_AddClientEventToNotificationGroup(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomEnd)); + if (shortcuts.end.count() > 0) { + shortcut = toMSFSShortcut(shortcuts.end); + result |= ::SimConnect_MapClientEventToSimEvent(simConnectHandle, Enum::underly(SimConnectEvent::Event::CustomEnd), "Custom.End"); + result |= ::SimConnect_MapInputEventToClientEvent_EX1(simConnectHandle, Enum::underly(Input::SkyDollyControl), shortcut, Enum::underly(SimConnectEvent::Event::CustomEnd)); + result |= ::SimConnect_AddClientEventToNotificationGroup(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomEnd)); + d->keySequenceStates.setFlag(::KeySequenceState::End); + } result |= ::SimConnect_SetNotificationGroupPriority(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), SIMCONNECT_GROUP_PRIORITY_HIGHEST); result |= ::SimConnect_SetInputGroupState(simConnectHandle, Enum::underly(Input::SkyDollyControl), SIMCONNECT_STATE_ON); @@ -144,37 +246,87 @@ bool InputEvent::setup(HANDLE simConnectHandle, const FlightSimulatorShortcuts & bool InputEvent::clear(HANDLE simConnectHandle) noexcept { - HRESULT result = ::SimConnect_RemoveClientEvent(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomRecording)); - result |= ::SimConnect_RemoveClientEvent(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomReplay)); - result |= ::SimConnect_RemoveClientEvent(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomPause)); - result |= ::SimConnect_RemoveClientEvent(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomStop)); - result |= ::SimConnect_RemoveClientEvent(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomBackward)); - result |= ::SimConnect_RemoveClientEvent(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomForward)); - result |= ::SimConnect_RemoveClientEvent(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomBegin)); - result |= ::SimConnect_RemoveClientEvent(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomEnd)); + HRESULT result {S_OK}; + if (d->keySequenceStates.testFlag(::KeySequenceState::Record)) + { + result = ::SimConnect_RemoveClientEvent(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomRecord)); + } + if (d->keySequenceStates.testFlag(::KeySequenceState::Replay)) + { + result |= ::SimConnect_RemoveClientEvent(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomReplay)); + } + if (d->keySequenceStates.testFlag(::KeySequenceState::Pause)) + { + result |= ::SimConnect_RemoveClientEvent(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomPause)); + } + if (d->keySequenceStates.testFlag(::KeySequenceState::Stop)) + { + result |= ::SimConnect_RemoveClientEvent(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomStop)); + } + if (d->keySequenceStates.testFlag(::KeySequenceState::Backward)) + { + result |= ::SimConnect_RemoveClientEvent(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomBackward)); + } + if (d->keySequenceStates.testFlag(::KeySequenceState::Forward)) + { + result |= ::SimConnect_RemoveClientEvent(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomForward)); + } + if (d->keySequenceStates.testFlag(::KeySequenceState::Begin)) + { + result |= ::SimConnect_RemoveClientEvent(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomBegin)); + } + if (d->keySequenceStates.testFlag(::KeySequenceState::End)) + { + result |= ::SimConnect_RemoveClientEvent(simConnectHandle, Enum::underly(NotificationGroup::ShortcutsGroup), Enum::underly(SimConnectEvent::Event::CustomEnd)); + } + d->keySequenceStates = ::KeySequenceState::None; result |= ::SimConnect_ClearInputGroup(simConnectHandle, Enum::underly(Input::SkyDollyControl)); return result == S_OK; } -QByteArray InputEvent::toMSFSShortcut(const QKeySequence &sequence) noexcept { - QStringList keys = sequence.toString().split('+'); +QByteArray InputEvent::toMSFSShortcut(const QKeySequence &sequence) const noexcept +{ QByteArray shortcut; - shortcut.reserve(keys.size() * 6); - bool hasKey {false}; - for (const QString &key: keys) { - if (hasKey) { - shortcut.append('+'); + + const QKeyCombination combination = sequence[0]; + const auto modifier = combination.keyboardModifiers(); + bool numpadModifier {false}; + if (modifier != Qt::NoModifier) { + if (modifier.testFlag(Qt::ShiftModifier)) { + auto msfsModifier = d->qtModifierToMSFS.at(Qt::ShiftModifier); + shortcut.append(msfsModifier).append('+'); + } + if (modifier.testFlag(Qt::ControlModifier)) { + auto msfsModifier = d->qtModifierToMSFS.at(Qt::ControlModifier); + shortcut.append(msfsModifier).append('+'); + } + if (modifier.testFlag(Qt::AltModifier)) { + auto msfsModifier = d->qtModifierToMSFS.at(Qt::AltModifier); + shortcut.append(msfsModifier).append('+'); } - if (InputEventPrivate::qtToMSFS.contains(key)) { - shortcut.append(InputEventPrivate::qtToMSFS.at(key)); - } else { - shortcut.append(key.toLatin1()); + if (modifier.testFlag(Qt::MetaModifier)) { + auto msfsModifier = d->qtModifierToMSFS.at(Qt::MetaModifier); + shortcut.append(msfsModifier).append('+'); + } + if (modifier.testFlag(Qt::KeypadModifier)) { + numpadModifier = true; + } + } + + const auto key = combination.key(); + if (d->qtToMSFS.contains(key)) { + auto msfsKey = d->qtToMSFS.at(key); + if (numpadModifier) { + msfsKey = d->numpadify.contains(msfsKey) ? d->numpadify.at(msfsKey) : msfsKey; } - hasKey = true; + shortcut.append(msfsKey); + } else { + QStringList keys = sequence.toString().split('+'); + shortcut.append(keys.last().toLatin1()); } #ifdef DEBUG - qDebug() << "InputEvent::toMSFSShortcut: Qt:" << sequence.toString() << "MSFS:" << shortcut; + qDebug() << "InputEvent::toMSFSShortcut: Qt:" << sequence.toString() << "key:" << key << "MSFS:" << shortcut; #endif return shortcut; } diff --git a/src/Plugins/Connect/MSFSSimConnectPlugin/src/Event/InputEvent.h b/src/Plugins/Connect/MSFSSimConnectPlugin/src/Event/InputEvent.h index f4875ca0d..1501fe7a7 100644 --- a/src/Plugins/Connect/MSFSSimConnectPlugin/src/Event/InputEvent.h +++ b/src/Plugins/Connect/MSFSSimConnectPlugin/src/Event/InputEvent.h @@ -50,8 +50,8 @@ class InputEvent private: const std::unique_ptr d; - static bool clear(HANDLE simConnectHandle) noexcept; - static QByteArray toMSFSShortcut(const QKeySequence &sequence) noexcept; + bool clear(HANDLE simConnectHandle) noexcept; + QByteArray toMSFSShortcut(const QKeySequence &sequence) const noexcept; }; #endif // INPUTEVENT_H diff --git a/src/Plugins/Connect/MSFSSimConnectPlugin/src/Event/SimConnectEvent.h b/src/Plugins/Connect/MSFSSimConnectPlugin/src/Event/SimConnectEvent.h index 4f4a57d0e..9950eda0c 100644 --- a/src/Plugins/Connect/MSFSSimConnectPlugin/src/Event/SimConnectEvent.h +++ b/src/Plugins/Connect/MSFSSimConnectPlugin/src/Event/SimConnectEvent.h @@ -89,7 +89,7 @@ namespace SimConnectEvent ToggleLogoLights, ToggleCabinLights, // Custom input events - CustomRecording, + CustomRecord, CustomReplay, CustomPause, CustomStop, diff --git a/src/Plugins/Connect/MSFSSimConnectPlugin/src/MSFSSimConnectPlugin.cpp b/src/Plugins/Connect/MSFSSimConnectPlugin/src/MSFSSimConnectPlugin.cpp index b775f3a80..1be29b25b 100644 --- a/src/Plugins/Connect/MSFSSimConnectPlugin/src/MSFSSimConnectPlugin.cpp +++ b/src/Plugins/Connect/MSFSSimConnectPlugin/src/MSFSSimConnectPlugin.cpp @@ -829,9 +829,9 @@ void CALLBACK MSFSSimConnectPlugin::dispatch(::SIMCONNECT_RECV *receivedData, [[ } break; - case SimConnectEvent::Event::CustomRecording: + case SimConnectEvent::Event::CustomRecord: #ifdef DEBUG - qDebug() << "MSFSSimConnectPlugin::dispatch: SIMCONNECT_RECV_ID_EVENT: CustomRecording event"; + qDebug() << "MSFSSimConnectPlugin::dispatch: SIMCONNECT_RECV_ID_EVENT: CustomRecord event"; #endif emit skyConnect->shortCutActivated(FlightSimulatorShortcuts::Action::Record); break; diff --git a/src/Plugins/Flight/Import/CsvImport/src/CsvImportPlugin.cpp b/src/Plugins/Flight/Import/CsvImport/src/CsvImportPlugin.cpp index 198e4ac8d..6c62744d1 100644 --- a/src/Plugins/Flight/Import/CsvImport/src/CsvImportPlugin.cpp +++ b/src/Plugins/Flight/Import/CsvImport/src/CsvImportPlugin.cpp @@ -23,11 +23,9 @@ * DEALINGS IN THE SOFTWARE. */ #include -#include #include #include -#include #include #include diff --git a/src/Plugins/Flight/Import/GpxImport/src/GpxImportPlugin.cpp b/src/Plugins/Flight/Import/GpxImport/src/GpxImportPlugin.cpp index b7521aa6a..eabf3c10e 100644 --- a/src/Plugins/Flight/Import/GpxImport/src/GpxImportPlugin.cpp +++ b/src/Plugins/Flight/Import/GpxImport/src/GpxImportPlugin.cpp @@ -33,7 +33,6 @@ #include #include #include -#include #include #include diff --git a/src/Plugins/Flight/Import/IgcImport/src/IgcImportPlugin.cpp b/src/Plugins/Flight/Import/IgcImport/src/IgcImportPlugin.cpp index 6b80c4511..9036d31a5 100644 --- a/src/Plugins/Flight/Import/IgcImport/src/IgcImportPlugin.cpp +++ b/src/Plugins/Flight/Import/IgcImport/src/IgcImportPlugin.cpp @@ -31,7 +31,6 @@ #include #include -#include #include #include #include diff --git a/src/Plugins/Flight/Import/KmlImport/src/KmlImportPlugin.cpp b/src/Plugins/Flight/Import/KmlImport/src/KmlImportPlugin.cpp index 5c209a799..fdb2e6266 100644 --- a/src/Plugins/Flight/Import/KmlImport/src/KmlImportPlugin.cpp +++ b/src/Plugins/Flight/Import/KmlImport/src/KmlImportPlugin.cpp @@ -31,7 +31,6 @@ #include #include #include -#include #include #include diff --git a/src/Plugins/Flight/Import/SdLogImport/src/SdLogImportPlugin.cpp b/src/Plugins/Flight/Import/SdLogImport/src/SdLogImportPlugin.cpp index 5296735fd..0d5f5415d 100644 --- a/src/Plugins/Flight/Import/SdLogImport/src/SdLogImportPlugin.cpp +++ b/src/Plugins/Flight/Import/SdLogImport/src/SdLogImportPlugin.cpp @@ -24,7 +24,6 @@ */ #include #include -#include #include #include @@ -34,7 +33,6 @@ #include #include #include -#include #include #include diff --git a/src/Plugins/Module/Formation/src/FormationPlugin.cpp b/src/Plugins/Module/Formation/src/FormationPlugin.cpp index d195c78bd..ad81b73be 100644 --- a/src/Plugins/Module/Formation/src/FormationPlugin.cpp +++ b/src/Plugins/Module/Formation/src/FormationPlugin.cpp @@ -133,7 +133,7 @@ void FormationPlugin::onRecordingStopped() noexcept flight.removeLastAircraft(); const PersistenceManager &persistenceManager = PersistenceManager::getInstance(); const QString logbookPath = QDir::toNativeSeparators(persistenceManager.getLogbookPath()); - QMessageBox::critical(getWidget(), tr("Aircraft error"), tr("The aircraft could not be stored into the logbook %1.").arg(logbookPath)); + QMessageBox::critical(getWidget(), tr("Write Error"), tr("The aircraft could not be stored into the logbook %1.").arg(logbookPath)); } } else { AbstractModule::onRecordingStopped(); diff --git a/src/Plugins/Module/Logbook/src/LogbookPlugin.cpp b/src/Plugins/Module/Logbook/src/LogbookPlugin.cpp index b49ae8852..00d6a6834 100644 --- a/src/Plugins/Module/Logbook/src/LogbookPlugin.cpp +++ b/src/Plugins/Module/Logbook/src/LogbookPlugin.cpp @@ -24,12 +24,16 @@ */ #include +#include +#include + #include #include #include #include #include #include +#include #include #include #include @@ -89,7 +93,13 @@ void LogbookPlugin::onRecordingStopped() noexcept const std::size_t sequenceNumber = flight.count(); if (sequenceNumber > 1) { // Sequence starts at 1 - d->aircraftService->store(flight.getId(), sequenceNumber, flight[sequenceNumber - 1]); + const bool ok = d->aircraftService->store(flight.getId(), sequenceNumber, flight[sequenceNumber - 1]); + if (!ok) { + flight.removeLastAircraft(); + const PersistenceManager &persistenceManager = PersistenceManager::getInstance(); + const QString logbookPath = QDir::toNativeSeparators(persistenceManager.getLogbookPath()); + QMessageBox::critical(getWidget(), tr("Write Error"), tr("The aircraft could not be stored into the logbook %1.").arg(logbookPath)); + } } else { AbstractModule::onRecordingStopped(); } diff --git a/src/Plugins/Module/Logbook/src/LogbookWidget.cpp b/src/Plugins/Module/Logbook/src/LogbookWidget.cpp index 366454fe3..df2323593 100644 --- a/src/Plugins/Module/Logbook/src/LogbookWidget.cpp +++ b/src/Plugins/Module/Logbook/src/LogbookWidget.cpp @@ -775,7 +775,7 @@ void LogbookWidget::loadFlight() noexcept if (selectedFlightId != Const::InvalidId) { const bool ok = d->flightService->restoreFlight(selectedFlightId, Logbook::getInstance().getCurrentFlight()); if (!ok) { - QMessageBox::critical(this, tr("Logbook error"), tr("The flight %1 could not be read from the logbook.").arg(selectedFlightId)); + QMessageBox::critical(this, tr("Read Error"), tr("The flight %1 could not be read from the logbook.").arg(selectedFlightId)); } } } diff --git a/src/UserInterface/src/Dialog/LogbookBackupDialog.cpp b/src/UserInterface/src/Dialog/LogbookBackupDialog.cpp index b99256a0c..a2664bae1 100644 --- a/src/UserInterface/src/Dialog/LogbookBackupDialog.cpp +++ b/src/UserInterface/src/Dialog/LogbookBackupDialog.cpp @@ -98,7 +98,7 @@ void LogbookBackupDialog::accept() noexcept } if (!ok) { - QMessageBox::critical(this, tr("Logbook error"), tr("The logbook backup could not be created.")); + QMessageBox::critical(this, tr("Backup Error"), tr("The logbook backup could not be created.")); } } diff --git a/src/UserInterface/src/Dialog/SettingsDialog.cpp b/src/UserInterface/src/Dialog/SettingsDialog.cpp index 313ac1418..983f42cc5 100644 --- a/src/UserInterface/src/Dialog/SettingsDialog.cpp +++ b/src/UserInterface/src/Dialog/SettingsDialog.cpp @@ -104,11 +104,11 @@ void SettingsDialog::initUi() noexcept setWindowFlags(Qt::Dialog | Qt::WindowTitleHint | Qt::WindowCloseButtonHint); // Replay - ui->seekInSecondsSpinBox->setMinimum(MinSeekSeconds); - ui->seekInSecondsSpinBox->setMaximum(MaxSeekSeconds); + ui->seekInSecondsSpinBox->setMinimum(::MinSeekSeconds); + ui->seekInSecondsSpinBox->setMaximum(::MaxSeekSeconds); - ui->seekInPercentSpinBox->setMinimum(MinSeekPercent); - ui->seekInPercentSpinBox->setMaximum(MaxSeekPercent); + ui->seekInPercentSpinBox->setMinimum(::MinSeekPercent); + ui->seekInPercentSpinBox->setMaximum(::MaxSeekPercent); ui->repeatCanopyOpenCheckBox->setToolTip(SimVar::CanopyOpen); @@ -153,6 +153,51 @@ void SettingsDialog::frenchConnection() noexcept this, &SettingsDialog::handleAccepted); connect(ui->settingsTabWidget, &QTabWidget::currentChanged, this, &SettingsDialog::handleTabChanged); + + connect(ui->recordSequenceEdit, &QKeySequenceEdit::editingFinished, + this, &SettingsDialog::handleRecordKeySequence); + connect(ui->replaySequenceEdit, &QKeySequenceEdit::editingFinished, + this, &SettingsDialog::handleReplayKeySequence); + connect(ui->pauseSequenceEdit, &QKeySequenceEdit::editingFinished, + this, &SettingsDialog::handlePauseKeySequence); + connect(ui->stopSequenceEdit, &QKeySequenceEdit::editingFinished, + this, &SettingsDialog::handleStopKeySequence); + connect(ui->backwardSequenceEdit, &QKeySequenceEdit::editingFinished, + this, &SettingsDialog::handleBackwardKeySequence); + connect(ui->forwardSequenceEdit, &QKeySequenceEdit::editingFinished, + this, &SettingsDialog::handleForwardKeySequence); + connect(ui->beginSequenceEdit, &QKeySequenceEdit::editingFinished, + this, &SettingsDialog::handleBeginKeySequence); + connect(ui->endSequenceEdit, &QKeySequenceEdit::editingFinished, + this, &SettingsDialog::handleEndKeySequence); +} + +void SettingsDialog::handleDuplicateKeySequences(QKeySequence keySequence, KeySequence source) const noexcept +{ + if (source != KeySequence::Record && ui->recordSequenceEdit->keySequence() == keySequence) { + ui->recordSequenceEdit->clear(); + } + if (source != KeySequence::Replay && ui->replaySequenceEdit->keySequence() == keySequence) { + ui->replaySequenceEdit->clear(); + } + if (source != KeySequence::Pause && ui->pauseSequenceEdit->keySequence() == keySequence) { + ui->pauseSequenceEdit->clear(); + } + if (source != KeySequence::Stop && ui->stopSequenceEdit->keySequence() == keySequence) { + ui->stopSequenceEdit->clear(); + } + if (source != KeySequence::Backward && ui->backwardSequenceEdit->keySequence() == keySequence) { + ui->backwardSequenceEdit->clear(); + } + if (source != KeySequence::Forward && ui->forwardSequenceEdit->keySequence() == keySequence) { + ui->forwardSequenceEdit->clear(); + } + if (source != KeySequence::Begin && ui->beginSequenceEdit->keySequence() == keySequence) { + ui->beginSequenceEdit->clear(); + } + if (source != KeySequence::End && ui->endSequenceEdit->keySequence() == keySequence) { + ui->endSequenceEdit->clear(); + } } // PRIVATE SLOTS @@ -301,3 +346,51 @@ void SettingsDialog::handleTabChanged(int index) noexcept break; } } + +void SettingsDialog::handleRecordKeySequence() const noexcept +{ + auto sequence = ui->recordSequenceEdit->keySequence(); + handleDuplicateKeySequences(sequence, KeySequence::Record); +} + +void SettingsDialog::handleReplayKeySequence() const noexcept +{ + auto sequence = ui->replaySequenceEdit->keySequence(); + handleDuplicateKeySequences(sequence, KeySequence::Replay); +} + +void SettingsDialog::handlePauseKeySequence() const noexcept +{ + auto sequence = ui->pauseSequenceEdit->keySequence(); + handleDuplicateKeySequences(sequence, KeySequence::Pause); +} + +void SettingsDialog::handleStopKeySequence() const noexcept +{ + auto sequence = ui->stopSequenceEdit->keySequence(); + handleDuplicateKeySequences(sequence, KeySequence::Stop); +} + +void SettingsDialog::handleBackwardKeySequence() const noexcept +{ + auto sequence = ui->backwardSequenceEdit->keySequence(); + handleDuplicateKeySequences(sequence, KeySequence::Backward); +} + +void SettingsDialog::handleForwardKeySequence() const noexcept +{ + auto sequence = ui->forwardSequenceEdit->keySequence(); + handleDuplicateKeySequences(sequence, KeySequence::Forward); +} + +void SettingsDialog::handleBeginKeySequence() const noexcept +{ + auto sequence = ui->beginSequenceEdit->keySequence(); + handleDuplicateKeySequences(sequence, KeySequence::Begin); +} + +void SettingsDialog::handleEndKeySequence() const noexcept +{ + auto sequence = ui->endSequenceEdit->keySequence(); + handleDuplicateKeySequences(sequence, KeySequence::End); +} diff --git a/src/UserInterface/src/Dialog/SettingsDialog.h b/src/UserInterface/src/Dialog/SettingsDialog.h index 70cdbbf2c..d52df4338 100644 --- a/src/UserInterface/src/Dialog/SettingsDialog.h +++ b/src/UserInterface/src/Dialog/SettingsDialog.h @@ -28,6 +28,7 @@ #include #include +#include namespace Ui { class SettingsDialog; @@ -51,17 +52,39 @@ class SettingsDialog : public QDialog void hideEvent(QHideEvent *event) noexcept override; private: + enum struct KeySequence + { + Record, + Replay, + Pause, + Stop, + Backward, + Forward, + Begin, + End + }; + std::unique_ptr ui; const std::unique_ptr d; void initUi() noexcept; void frenchConnection() noexcept; + void handleDuplicateKeySequences(QKeySequence keySequence, KeySequence source) const noexcept; private slots: void updateUi() noexcept; void updateConnectionStatus() noexcept; void handleAccepted() noexcept; void handleTabChanged(int index) noexcept; + + void handleRecordKeySequence() const noexcept; + void handleReplayKeySequence() const noexcept; + void handlePauseKeySequence() const noexcept; + void handleStopKeySequence() const noexcept; + void handleBackwardKeySequence() const noexcept; + void handleForwardKeySequence() const noexcept; + void handleBeginKeySequence() const noexcept; + void handleEndKeySequence() const noexcept; }; #endif // SETTINGSDIALOG_H diff --git a/src/UserInterface/src/Dialog/SettingsDialog.ui b/src/UserInterface/src/Dialog/SettingsDialog.ui index eb8f3e745..96f6dd063 100644 --- a/src/UserInterface/src/Dialog/SettingsDialog.ui +++ b/src/UserInterface/src/Dialog/SettingsDialog.ui @@ -6,8 +6,8 @@ 0 0 - 702 - 408 + 820 + 387 diff --git a/src/UserInterface/src/MainWindow.cpp b/src/UserInterface/src/MainWindow.cpp index 1ad7e43d2..7a8ae0105 100644 --- a/src/UserInterface/src/MainWindow.cpp +++ b/src/UserInterface/src/MainWindow.cpp @@ -224,7 +224,7 @@ bool MainWindow::connectWithLogbook(const QString &filePath) noexcept if (d->connectedWithLogbook) { RecentFile::getInstance().addRecentFile(filePath); } else { - QMessageBox::critical(this, tr("Logbook error"), tr("The logbook %1 could not be opened.").arg(QDir::toNativeSeparators(filePath))); + QMessageBox::critical(this, tr("Logbook Error"), tr("The logbook %1 could not be opened.").arg(QDir::toNativeSeparators(filePath))); } return d->connectedWithLogbook; } @@ -1636,7 +1636,7 @@ void MainWindow::createNewLogbook() noexcept if (ok) { RecentFile::getInstance().addRecentFile(logbookPath); } else { - QMessageBox::critical(this, tr("Logbook error"), tr("The logbook %1 could not be created.").arg(QDir::toNativeSeparators(logbookPath))); + QMessageBox::critical(this, tr("Logbook Error"), tr("The logbook %1 could not be created.").arg(QDir::toNativeSeparators(logbookPath))); } } } @@ -1659,7 +1659,7 @@ void MainWindow::onRecentFileSelected(const QString &filePath, SecurityToken *se if (ok) { ok = connectWithLogbook(filePath); } else { - QMessageBox::critical(this, tr("Logbook not found"), tr("The logbook %1 does not exist.").arg(QDir::toNativeSeparators(filePath))); + QMessageBox::critical(this, tr("Logbook Not Found"), tr("The logbook %1 does not exist.").arg(QDir::toNativeSeparators(filePath))); } if (!ok) { RecentFile::getInstance().removeRecentFile(filePath); @@ -1706,7 +1706,7 @@ void MainWindow::optimiseLogbook() noexcept .arg(d->unit.formatMemory(fileInfo.size()), d->unit.formatMemory(oldSize))); messageBox->exec(); } else { - QMessageBox::critical(this, tr("Logbook error"), tr("The logbook could not be optimised.")); + QMessageBox::critical(this, tr("Logbook Error"), tr("The logbook could not be optimised.")); } } }