From b0b4fa521ff218b7cdad15a28533fbf54ce6362f Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 13 Mar 2024 01:30:10 +0100 Subject: [PATCH] Use mouse keys for CW modulation in SSB modulator. Fixes #1948 --- doc/img/ModCWControls2.png | Bin 3961 -> 4477 bytes doc/img/ModCWControls2.xcf | Bin 18843 -> 21650 bytes plugins/channeltx/modam/readme.md | 30 ++++++---- plugins/channeltx/modfreedv/readme.md | 30 ++++++---- plugins/channeltx/modnfm/readme.md | 30 ++++++---- plugins/channeltx/modssb/readme.md | 30 ++++++---- plugins/channeltx/modssb/ssbmodgui.cpp | 2 +- plugins/channeltx/modssb/ssbmodsource.cpp | 37 +++++++----- plugins/channeltx/modwfm/readme.md | 30 ++++++---- sdrbase/audio/audiofifo.cpp | 25 ++++++++ sdrbase/audio/audiofifo.h | 1 + sdrgui/CMakeLists.txt | 2 + sdrgui/gui/cwkeyergui.cpp | 26 ++++++++ sdrgui/gui/cwkeyergui.h | 4 ++ sdrgui/gui/cwkeyergui.ui | 29 ++++++++- sdrgui/gui/cwmousekeyerenabler.cpp | 70 ++++++++++++++++++++++ sdrgui/gui/cwmousekeyerenabler.h | 43 +++++++++++++ sdrgui/resources/mouse.png | Bin 0 -> 5212 bytes sdrgui/resources/res.qrc | 1 + 19 files changed, 313 insertions(+), 77 deletions(-) create mode 100644 sdrgui/gui/cwmousekeyerenabler.cpp create mode 100644 sdrgui/gui/cwmousekeyerenabler.h create mode 100644 sdrgui/resources/mouse.png diff --git a/doc/img/ModCWControls2.png b/doc/img/ModCWControls2.png index bfb478a30e0af5e7b93b1d8383f4719693efe524..38cf41a79d1daf6af43780c15c4ec82317634c57 100644 GIT binary patch literal 4477 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 literal 3961 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 F{{b3qnT7xW diff --git a/doc/img/ModCWControls2.xcf b/doc/img/ModCWControls2.xcf index e4254eb761b80cb09e6fef056a52c08b526ca459..6427d725e47e9b849a2321067c15fa39043682dd 100644 GIT binary patch literal 21650 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 N_44(i+Y{I7{~x+4(kcJ| literal 18843 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: Morse keyer controls +

12a: Morse keyer controls (line 1)

![Morse keyer control GUI1](../../../doc/img/ModCWControls1.png) -

12.1: CW keying speed

+

12a.1: CW keying speed

Sets the CW speed in Words Per Minute (WPM). This is based on the word "PARIS" sent 5 times. For 5 WPM the dot length is 240 ms. In other terms the dot length is calculated as 1.2 / WPM seconds. The dot length is used as the base to compute other timings: @@ -85,43 +85,49 @@ Sets the CW speed in Words Per Minute (WPM). This is based on the word "PARIS" s - Character silence separator: 3 dot lengths - Word silence separator: 7 dot lengths -

12.2: Dots keying

+

12a.2: Dots keying

Switch this button to send dots continuously -

12.3: Dashes keying

+

12a.3: Dashes keying

Switch this button to send dashes continuously -

12.4: Text keying

+

12a.4: Text keying

Switch this button to send the text typed into the text box (10) -

12.5: Text auto repeat

+

12a.5: Text auto repeat

Switch this button to auto repeat the text keying -

12.6: Text play/stop

+

12a.6: Text play/stop

Use this button to stop sending text. When resuming keying restarts at the start of text +

12a: Morse keyer controls (line 2)

+ ![Morse keyer control GUI2](../../../doc/img/ModCWControls2.png) ⚠ WARNING: what follows is not really useful if you do not use a proper Morse keyer with direct audio feedback. There is a significant audio delay either with the direct monitoring or by monitoring the transmitted signal so keying with this audio as feedback is not practical -12.7: Activate morse keys keyboard control +12b.1: Activate morse keys keyboard and mouse control -This disables text or continuous dots or dashes. Toggle input from keyboard. Occasionally the focus may get lost and you will have to deactivate and reactivate it to recover the key bindings. +This disables text or continuous dots or dashes. Toggle input from keyboard or mouse (see 16b.3). Occasionally the focus may get lost and you will have to deactivate and reactivate it to recover the key bindings. -12.8: Iambic or straight +12b.2: Iambic or straight Choose iambic or straight keying style. When straight is selected the dot or dash key may be used. -12.9: Register dot key +12b.3: Mouse control pad + +When keyboard and mouse control is activated move the pointer to this area to use the left button as the dot paddle and the right button as the dash paddle. In straight mode both buttons have the same effect (key down). + +12a.4: Register dot key Click on the button and while selected type a character or character and modifier (Shift + key for example) to select which key is used for dots. The key or key sequence appears next (here dot `.`) -12.10: Register dash key +12a.5: Register dash key Click on the button and while selected type a character or character and modifier (Shift + key for example) to select which key is used for dashes. The key or key sequence appears next (here dot `.`) diff --git a/plugins/channeltx/modfreedv/readme.md b/plugins/channeltx/modfreedv/readme.md index 3ad241d68..bb6092816 100644 --- a/plugins/channeltx/modfreedv/readme.md +++ b/plugins/channeltx/modfreedv/readme.md @@ -81,11 +81,11 @@ Enter the text to be keyed when Morse input is active and in text mode. Clears the CW (Morse) text -

10: Morse keyer controls

+

10a: Morse keyer controls (line 1)

![Morse keyer control GUI1](../../../doc/img/ModCWControls1.png) -

10.1: CW keying speed

+

10a.1: CW keying speed

Sets the CW speed in Words Per Minute (WPM). This is based on the word "PARIS" sent 5 times. For 5 WPM the dot length is 240 ms. In other terms the dot length is calculated as 1.2 / WPM seconds. The dot length is used as the base to compute other timings: @@ -94,43 +94,49 @@ Sets the CW speed in Words Per Minute (WPM). This is based on the word "PARIS" s - Character silence separator: 3 dot lengths - Word silence separator: 7 dot lengths -

10.2: Dots keying

+

10a.2: Dots keying

Switch this button to send dots continuously -

10.3: Dashes keying

+

10a.3: Dashes keying

Switch this button to send dashes continuously -

10.4: Text keying

+

10a.4: Text keying

Switch this button to send the text typed into the text box (13) -

10.5: Text auto repeat

+

10a.5: Text auto repeat

Switch this button to auto repeat the text keying -

10.6: Text play/stop

+

10a.6: Text play/stop

Use this button to stop sending text. When resuming keying restarts at the start of text +

10b.1: CW keying speed

+ ![Morse keyer control GUI2](../../../doc/img/ModCWControls2.png) ⚠ WARNING: what follows is not really useful if you do not use a proper Morse keyer with direct audio feedback. There is a significant audio delay either with the direct monitoring or by monitoring the transmitted signal so keying with this audio as feedback is not practical -10.7: Activate morse keys keyboard control +10b.1: Activate morse keys keyboard and mouse control -This disables text or continuous dots or dashes. Toggle input from keyboard. Occasionally the focus may get lost and you will have to deactivate and reactivate it to recover the key bindings. +This disables text or continuous dots or dashes. Toggle input from keyboard or mouse (see 16b.3). Occasionally the focus may get lost and you will have to deactivate and reactivate it to recover the key bindings. -10.8: Iambic or straight +10b.2: Iambic or straight Choose iambic or straight keying style. When straight is selected the dot or dash key may be used. -10.9: Register dot key +10b.3: Mouse control pad + +When keyboard and mouse control is activated move the pointer to this area to use the left button as the dot paddle and the right button as the dash paddle. In straight mode both buttons have the same effect (key down). + +10a.4: Register dot key Click on the button and while selected type a character or character and modifier (Shift + key for example) to select which key is used for dots. The key or key sequence appears next (here dot `.`) -10.10: Register dash key +10a.5: Register dash key Click on the button and while selected type a character or character and modifier (Shift + key for example) to select which key is used for dashes. The key or key sequence appears next (here dot `.`) diff --git a/plugins/channeltx/modnfm/readme.md b/plugins/channeltx/modnfm/readme.md index 0d855a50e..4da22bc42 100644 --- a/plugins/channeltx/modnfm/readme.md +++ b/plugins/channeltx/modnfm/readme.md @@ -170,11 +170,11 @@ Enter the text to be keyed when Morse input is active and in text mode Clears the CW (Morse) text -

17: Morse keyer controls

+

17a: Morse keyer controls (line 1)

![Morse keyer control GUI1](../../../doc/img/ModCWControls1.png) -

17.1: CW keying speed

+

17a.1: CW keying speed

Sets the CW speed in Words Per Minute (WPM). This is based on the word "PARIS" sent 5 times. For 5 WPM the dot length is 240 ms. In other terms the dot length is calculated as 1.2 / WPM seconds. The dot length is used as the base to compute other timings: @@ -183,45 +183,49 @@ Sets the CW speed in Words Per Minute (WPM). This is based on the word "PARIS" s - Character silence separator: 3 dot lengths - Word silence separator: 7 dot lengths -

17.2: Dots keying

+

17a.2: Dots keying

Switch this button to send dots continuously -

17.3: Dashes keying

+

17a.3: Dashes keying

Switch this button to send dashes continuously -

17.4: Text keying

+

17a.4: Text keying

Switch this button to send the text typed into the text box (14) -

17.5: Text auto repeat

+

17a.5: Text auto repeat

Switch this button to auto repeat the text keying -

17.6: Text play/stop

+

17a.6: Text play/stop

Use this button to stop sending text. When resuming keying restarts at the start of text -

18: Use keyboard for morse keying

+

17b: Morse keyer controls (line 2)

![Morse keyer control GUI2](../../../doc/img/ModCWControls2.png) ⚠ WARNING: this is not really useful if you do not use a proper Morse keyer with direct audio feedback. There is a significant audio delay either with the direct monitoring or by monitoring the transmitted signal so keying with this audio as feedback is not practical -18.7: Activate morse keys keyboard control +17b.1: Activate morse keys keyboard and mouse control -This disables text or continuous dots or dashes. Toggle input from keyboard. Occasionally the focus may get lost and you will have to deactivate and reactivate it to recover the key bindings. +This disables text or continuous dots or dashes. Toggle input from keyboard or mouse (see 16b.3). Occasionally the focus may get lost and you will have to deactivate and reactivate it to recover the key bindings. -18.8: Iambic or straight +17b.2: Iambic or straight Choose iambic or straight keying style. When straight is selected the dot or dash key may be used. -18.9: Register dot key +17b.3: Mouse control pad + +When keyboard and mouse control is activated move the pointer to this area to use the left button as the dot paddle and the right button as the dash paddle. In straight mode both buttons have the same effect (key down). + +17a.4: Register dot key Click on the button and while selected type a character or character and modifier (Shift + key for example) to select which key is used for dots. The key or key sequence appears next (here dot `.`) -18.10: Register dash key +17a.5: Register dash key Click on the button and while selected type a character or character and modifier (Shift + key for example) to select which key is used for dashes. The key or key sequence appears next (here dot `.`) diff --git a/plugins/channeltx/modssb/readme.md b/plugins/channeltx/modssb/readme.md index 26f271c54..e032187e8 100644 --- a/plugins/channeltx/modssb/readme.md +++ b/plugins/channeltx/modssb/readme.md @@ -161,11 +161,11 @@ Enter the text to be keyed when Morse input is active and in text mode Clears the CW (Morse) text -

16: Morse keyer controls

+

16a: Morse keyer controls (line1)

![Morse keyer control GUI1](../../../doc/img/ModCWControls1.png) -

16.1: CW keying speed

+

16a.1: CW keying speed

Sets the CW speed in Words Per Minute (WPM). This is based on the word "PARIS" sent 5 times. For 5 WPM the dot length is 240 ms. In other terms the dot length is calculated as 1.2 / WPM seconds. The dot length is used as the base to compute other timings: @@ -174,43 +174,49 @@ Sets the CW speed in Words Per Minute (WPM). This is based on the word "PARIS" s - Character silence separator: 3 dot lengths - Word silence separator: 7 dot lengths -

16.2: Dots keying

+

16a.2: Dots keying

Switch this button to send dots continuously -

16.3: Dashes keying

+

16a.3: Dashes keying

Switch this button to send dashes continuously -

16.4: Text keying

+

16a.4: Text keying

Switch this button to send the text typed into the text box (13) -

16.5: Text auto repeat

+

16a.5: Text auto repeat

Switch this button to auto repeat the text keying -

16.6: Text play/stop

+

16a.6: Text play/stop

Use this button to stop sending text. When resuming keying restarts at the start of text +

16b: Morse keyer controls (line2)

+ ![Morse keyer control GUI2](../../../doc/img/ModCWControls2.png) ⚠ WARNING: what follows is not really useful if you do not use a proper Morse keyer with direct audio feedback. There is a significant audio delay either with the direct monitoring or by monitoring the transmitted signal so keying with this audio as feedback is not practical -16.7: Activate morse keys keyboard control +16b.1: Activate morse keys keyboard and mouse control -This disables text or continuous dots or dashes. Toggle input from keyboard. Occasionally the focus may get lost and you will have to deactivate and reactivate it to recover the key bindings. +This disables text or continuous dots or dashes. Toggle input from keyboard or mouse (see 16b.3). Occasionally the focus may get lost and you will have to deactivate and reactivate it to recover the key bindings. -16.8: Iambic or straight +16b.2: Iambic or straight Choose iambic or straight keying style. When straight is selected the dot or dash key may be used. -16.9: Register dot key +16b.3: Mouse control pad + +When keyboard and mouse control is activated move the pointer to this area to use the left button as the dot paddle and the right button as the dash paddle. In straight mode both buttons have the same effect (key down). + +16b.4: Register dot key Click on the button and while selected type a character or character and modifier (Shift + key for example) to select which key is used for dots. The key or key sequence appears next (here dot `.`) -16.10: Register dash key +16b.5: Register dash key Click on the button and while selected type a character or character and modifier (Shift + key for example) to select which key is used for dashes. The key or key sequence appears next (here dot `.`) diff --git a/plugins/channeltx/modssb/ssbmodgui.cpp b/plugins/channeltx/modssb/ssbmodgui.cpp index 8e57b3e07..3289db300 100644 --- a/plugins/channeltx/modssb/ssbmodgui.cpp +++ b/plugins/channeltx/modssb/ssbmodgui.cpp @@ -790,7 +790,7 @@ void SSBModGUI::audioSelect(const QPoint& p) void SSBModGUI::audioFeedbackSelect(const QPoint& p) { qDebug("SSBModGUI::audioFeedbackSelect"); - AudioSelectDialog audioSelect(DSPEngine::instance()->getAudioDeviceManager(), m_settings.m_audioDeviceName, false); // false for output + AudioSelectDialog audioSelect(DSPEngine::instance()->getAudioDeviceManager(), m_settings.m_feedbackAudioDeviceName, false); // false for output audioSelect.move(p); new DialogPositioner(&audioSelect, false); audioSelect.exec(); diff --git a/plugins/channeltx/modssb/ssbmodsource.cpp b/plugins/channeltx/modssb/ssbmodsource.cpp index 8ebaa31c5..6310ca9a0 100644 --- a/plugins/channeltx/modssb/ssbmodsource.cpp +++ b/plugins/channeltx/modssb/ssbmodsource.cpp @@ -35,7 +35,7 @@ SSBModSource::SSBModSource() : m_spectrumSink(nullptr), m_audioSampleRate(48000), m_audioFifo(12000), - m_feedbackAudioFifo(48000), + m_feedbackAudioFifo(12000), m_levelCalcCount(0), m_peakLevel(0.0f), m_levelSum(0.0f), @@ -55,7 +55,7 @@ SSBModSource::SSBModSource() : m_audioReadBuffer.resize(24000); m_audioReadBufferFill = 0; - m_feedbackAudioBuffer.resize(1<<14); + m_feedbackAudioBuffer.resize(4800); m_feedbackAudioBufferFill = 0; m_demodBuffer.resize(1<<12); @@ -538,22 +538,31 @@ void SSBModSource::pushFeedback(Complex c) void SSBModSource::processOneSample(Complex& ci) { - m_feedbackAudioBuffer[m_feedbackAudioBufferFill].l = ci.real(); - m_feedbackAudioBuffer[m_feedbackAudioBufferFill].r = ci.imag(); - ++m_feedbackAudioBufferFill; - - if (m_feedbackAudioBufferFill >= m_feedbackAudioBuffer.size()) + if (m_settings.m_modAFInput == SSBModSettings::SSBModInputCWTone) // minimize latency for CW { - uint res = m_feedbackAudioFifo.write((const quint8*)&m_feedbackAudioBuffer[0], m_feedbackAudioBufferFill); + m_feedbackAudioBuffer[0].l = ci.real(); + m_feedbackAudioBuffer[0].r = ci.imag(); + m_feedbackAudioFifo.writeOne((const quint8*) &m_feedbackAudioBuffer[0]); + } + else + { + m_feedbackAudioBuffer[m_feedbackAudioBufferFill].l = ci.real(); + m_feedbackAudioBuffer[m_feedbackAudioBufferFill].r = ci.imag(); + ++m_feedbackAudioBufferFill; - if (res != m_feedbackAudioBufferFill) + if (m_feedbackAudioBufferFill >= m_feedbackAudioBuffer.size()) { - qDebug("SSBModSource::pushFeedback: %u/%u audio samples written m_feedbackInterpolatorDistance: %f", - res, m_feedbackAudioBufferFill, m_feedbackInterpolatorDistance); - m_feedbackAudioFifo.clear(); - } + uint res = m_feedbackAudioFifo.write((const quint8*)&m_feedbackAudioBuffer[0], m_feedbackAudioBufferFill); - m_feedbackAudioBufferFill = 0; + if (res != m_feedbackAudioBufferFill) + { + qDebug("SSBModSource::pushFeedback: %u/%u audio samples written m_feedbackInterpolatorDistance: %f", + res, m_feedbackAudioBufferFill, m_feedbackInterpolatorDistance); + m_feedbackAudioFifo.clear(); + } + + m_feedbackAudioBufferFill = 0; + } } } diff --git a/plugins/channeltx/modwfm/readme.md b/plugins/channeltx/modwfm/readme.md index fe1017292..92e675b7b 100644 --- a/plugins/channeltx/modwfm/readme.md +++ b/plugins/channeltx/modwfm/readme.md @@ -76,11 +76,11 @@ Enter the text to be keyed when Morse input is active and in text mode Clears the CW (Morse) text -

13: Morse keyer controls

+

13a: Morse keyer controls (line 1)

![Morse keyer control GUI1](../../../doc/img/ModCWControls1.png) -

13.1: CW keying speed

+

13a.1: CW keying speed

Sets the CW speed in Words Per Minute (WPM). This is based on the word "PARIS" sent 5 times. For 5 WPM the dot length is 240 ms. In other terms the dot length is calculated as 1.2 / WPM seconds. The dot length is used as the base to compute other timings: @@ -89,43 +89,49 @@ Sets the CW speed in Words Per Minute (WPM). This is based on the word "PARIS" s - Character silence separator: 3 dot lengths - Word silence separator: 7 dot lengths -

13.2: Dots keying

+

13a.2: Dots keying

Switch this button to send dots continuously -

13.3: Dashes keying

+

13a.3: Dashes keying

Switch this button to send dashes continuously -

13.4: Text keying

+

13a.4: Text keying

Switch this button to send the text typed into the text box (11) -

13.5: Text auto repeat

+

13a.5: Text auto repeat

Switch this button to auto repeat the text keying -

13.6: Text play/stop

+

13a.6: Text play/stop

Use this button to stop sending text. When resuming keying restarts at the start of text +

13b: Morse keyer controls (line 2)

+ ![Morse keyer control GUI2](../../../doc/img/ModCWControls2.png) ⚠ WARNING: what follows is not really useful if you do not use a proper Morse keyer with direct audio feedback. There is a significant audio delay either with the direct monitoring or by monitoring the transmitted signal so keying with this audio as feedback is not practical -13.7: Activate morse keys keyboard control +13b.1: Activate morse keys keyboard and mouse control -This disables text or continuous dots or dashes. Toggle input from keyboard. Occasionally the focus may get lost and you will have to deactivate and reactivate it to recover the key bindings. +This disables text or continuous dots or dashes. Toggle input from keyboard or mouse (see 16b.3). Occasionally the focus may get lost and you will have to deactivate and reactivate it to recover the key bindings. -13.8: Iambic or straight +13b.2: Iambic or straight Choose iambic or straight keying style. When straight is selected the dot or dash key may be used. -13.9: Register dot key +13b.3: Mouse control pad + +When keyboard and mouse control is activated move the pointer to this area to use the left button as the dot paddle and the right button as the dash paddle. In straight mode both buttons have the same effect (key down). + +13b.4: Register dot key Click on the button and while selected type a character or character and modifier (Shift + key for example) to select which key is used for dots. The key or key sequence appears next (here dot `.`) -13.10: Register dash key +13b.5: Register dash key Click on the button and while selected type a character or character and modifier (Shift + key for example) to select which key is used for dashes. The key or key sequence appears next (here dot `.`) diff --git a/sdrbase/audio/audiofifo.cpp b/sdrbase/audio/audiofifo.cpp index 14c65d0c7..d562c8a76 100644 --- a/sdrbase/audio/audiofifo.cpp +++ b/sdrbase/audio/audiofifo.cpp @@ -174,6 +174,31 @@ bool AudioFifo::readOne(quint8* data) return true; } +uint32_t AudioFifo::writeOne(const quint8* data) +{ + if (!m_fifo) { + return 0; + } + + if (isFull()) + { + emit overflow(1); + return 0; + } + + m_mutex.lock(); + + memcpy(m_fifo + (m_tail * m_sampleSize), data, m_sampleSize); + m_tail += 1; + m_tail %= m_size; + m_fill += 1; + + m_mutex.unlock(); + + emit dataReady(); + return 1; +} + uint AudioFifo::drain(uint32_t numSamples) { QMutexLocker mutexLocker(&m_mutex); diff --git a/sdrbase/audio/audiofifo.h b/sdrbase/audio/audiofifo.h index 3a09e2716..1a531f37f 100644 --- a/sdrbase/audio/audiofifo.h +++ b/sdrbase/audio/audiofifo.h @@ -41,6 +41,7 @@ public: uint32_t write(const quint8* data, uint32_t numSamples); uint32_t read(quint8* data, uint32_t numSamples); bool readOne(quint8* data); + uint32_t writeOne(const quint8* data); uint32_t drain(uint32_t numSamples); void clear(); diff --git a/sdrgui/CMakeLists.txt b/sdrgui/CMakeLists.txt index 358e4029f..39bec49ac 100644 --- a/sdrgui/CMakeLists.txt +++ b/sdrgui/CMakeLists.txt @@ -26,6 +26,7 @@ set(sdrgui_SOURCES gui/crightclickenabler.cpp gui/customtextedit.cpp gui/cwkeyergui.cpp + gui/cwmousekeyerenabler.cpp gui/datetimedelegate.cpp gui/decimaldelegate.cpp gui/devicesetselectiondialog.cpp @@ -150,6 +151,7 @@ set(sdrgui_HEADERS gui/crightclickenabler.h gui/customtextedit.h gui/cwkeyergui.h + gui/cwmousekeyerenabler.h gui/datetimedelegate.h gui/decimaldelegate.h gui/devicesetselectiondialog.h diff --git a/sdrgui/gui/cwkeyergui.cpp b/sdrgui/gui/cwkeyergui.cpp index 17ef78fdf..abeb7008b 100644 --- a/sdrgui/gui/cwkeyergui.cpp +++ b/sdrgui/gui/cwkeyergui.cpp @@ -21,6 +21,7 @@ #include "gui/cwkeyergui.h" #include "gui/dialpopup.h" +#include "gui/cwmousekeyerenabler.h" #include "ui_cwkeyergui.h" #include "dsp/cwkeyer.h" #include "util/simpleserializer.h" @@ -40,6 +41,11 @@ CWKeyerGUI::CWKeyerGUI(QWidget* parent) : m_commandKeyReceiver->setRelease(true); this->installEventFilter(m_commandKeyReceiver); DialPopup::addPopupsToChildDials(this); + CWMouseKeyerEnabler *cwMouseKeyerEnabler = new CWMouseKeyerEnabler(ui->cwMouseKeyerPad); + QObject::connect(cwMouseKeyerEnabler, &CWMouseKeyerEnabler::leftButtonPress, this, &CWKeyerGUI::cwKeyerMouseLeftPressed); + QObject::connect(cwMouseKeyerEnabler, &CWMouseKeyerEnabler::leftButtonRelease, this, &CWKeyerGUI::cwKeyerMouseLeftReleased); + QObject::connect(cwMouseKeyerEnabler, &CWMouseKeyerEnabler::rightButtonPress, this, &CWKeyerGUI::cwKeyerMouseRightPressed); + QObject::connect(cwMouseKeyerEnabler, &CWMouseKeyerEnabler::rightButtonRelease, this, &CWKeyerGUI::cwKeyerMouseRightReleased); } CWKeyerGUI::~CWKeyerGUI() @@ -359,3 +365,23 @@ void CWKeyerGUI::blockApplySettings(bool block) { m_doApplySettings = !block; } + +void CWKeyerGUI::cwKeyerMouseLeftPressed() +{ + m_cwKeyer->setKeyboardDots(); +} + +void CWKeyerGUI::cwKeyerMouseLeftReleased() +{ + m_cwKeyer->setKeyboardSilence(); +} + +void CWKeyerGUI::cwKeyerMouseRightPressed() +{ + m_cwKeyer->setKeyboardDashes(); +} + +void CWKeyerGUI::cwKeyerMouseRightReleased() +{ + m_cwKeyer->setKeyboardSilence(); +} diff --git a/sdrgui/gui/cwkeyergui.h b/sdrgui/gui/cwkeyergui.h index b71e69fa7..456ee0d56 100644 --- a/sdrgui/gui/cwkeyergui.h +++ b/sdrgui/gui/cwkeyergui.h @@ -90,6 +90,10 @@ private slots: void on_keyboardKeyer_toggled(bool checked); void commandKeyPressed(Qt::Key key, Qt::KeyboardModifiers keyModifiers, bool release); void keyboardKeyPressed(Qt::Key key, Qt::KeyboardModifiers keyModifiers, bool release); + void cwKeyerMouseLeftPressed(); + void cwKeyerMouseLeftReleased(); + void cwKeyerMouseRightPressed(); + void cwKeyerMouseRightReleased(); }; diff --git a/sdrgui/gui/cwkeyergui.ui b/sdrgui/gui/cwkeyergui.ui index fa01e02f1..f9bf4bd32 100644 --- a/sdrgui/gui/cwkeyergui.ui +++ b/sdrgui/gui/cwkeyergui.ui @@ -7,7 +7,7 @@ 0 0 375 - 91 + 92 @@ -82,6 +82,7 @@ + Liberation Sans 9 @@ -149,6 +150,7 @@ + Liberation Sans 12 75 true @@ -215,6 +217,7 @@ + Liberation Sans 12 75 true @@ -487,6 +490,28 @@ + + + + + 32 + 0 + + + + Put the mouse pointer here to activate the CW mouse keyer + + + QFrame::NoFrame + + + + + + :/mouse.png + + + @@ -546,6 +571,7 @@ + Liberation Sans 12 75 true @@ -634,6 +660,7 @@ + Liberation Sans 12 75 true diff --git a/sdrgui/gui/cwmousekeyerenabler.cpp b/sdrgui/gui/cwmousekeyerenabler.cpp new file mode 100644 index 000000000..535f3b8a6 --- /dev/null +++ b/sdrgui/gui/cwmousekeyerenabler.cpp @@ -0,0 +1,70 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2024 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include "cwmousekeyerenabler.h" + +CWMouseKeyerEnabler::CWMouseKeyerEnabler(QWidget *widget) : + QObject(widget), + m_widget(widget) +{ + m_widget->installEventFilter(this); +} + +bool CWMouseKeyerEnabler::eventFilter(QObject *obj, QEvent *event) +{ + if (event->type() == QEvent::MouseButtonPress) + { + auto mouseEvent = (QMouseEvent*) event; + + if (mouseEvent->button() == Qt::RightButton) + { + emit rightButtonPress(mouseEvent->globalPos()); + mouseEvent->setAccepted(true); + return true; + } + + if (mouseEvent->button() == Qt::LeftButton) + { + emit leftButtonPress(mouseEvent->globalPos()); + mouseEvent->setAccepted(true); + return true; + } + } + else if (event->type() == QEvent::MouseButtonRelease) + { + auto mouseEvent = (QMouseEvent*) event; + + if (mouseEvent->button() == Qt::RightButton) + { + emit rightButtonRelease(mouseEvent->globalPos()); + mouseEvent->setAccepted(true); + return true; + } + + if (mouseEvent->button() == Qt::LeftButton) + { + emit leftButtonRelease(mouseEvent->globalPos()); + mouseEvent->setAccepted(true); + return true; + } + } + + return QObject::eventFilter(obj, event); +} diff --git a/sdrgui/gui/cwmousekeyerenabler.h b/sdrgui/gui/cwmousekeyerenabler.h new file mode 100644 index 000000000..a39b41215 --- /dev/null +++ b/sdrgui/gui/cwmousekeyerenabler.h @@ -0,0 +1,43 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2024 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef SDRGUI_GUI_CWMOUSEKEYERENABLER_H_ +#define SDRGUI_GUI_CWMOUSEKEYERENABLER_H_ + +#include + +#include "export.h" + +class SDRGUI_API CWMouseKeyerEnabler : public QObject { + Q_OBJECT +public: + CWMouseKeyerEnabler(QWidget *widget); + +signals: + void leftButtonPress(const QPoint&); // Emitted for left mouse press + void leftButtonRelease(const QPoint&); // Emitted for left mouse release + void rightButtonPress(const QPoint&); // Emitted for right mouse press + void rightButtonRelease(const QPoint&); // Emitted for right mouse release + +protected: + bool eventFilter(QObject *watched, QEvent *event) override; + +private: + QWidget* m_widget; +}; + +#endif /* SDRGUI_GUI_CRIGHTCLICKENABLER_H_ */ diff --git a/sdrgui/resources/mouse.png b/sdrgui/resources/mouse.png new file mode 100644 index 0000000000000000000000000000000000000000..70190a280460767c76d770c798d40e793771e408 GIT binary patch literal 5212 zcmeHKX;f3!8ofZ72bo212m!5vnFAz|piCh_Knj#e``{+Ifk-BjKmv%&D5z)=We~7d zs)&GA3tCjf0SgF1F%_$bD6OT6pol{O>$?f4xL*Ib*6TmB)=h5C*=K*>x4(T(a`OTM zd<^xh^#A}cWYE2W;7^3|($Rw7CCSMX0H8je91<=K0%Zu1Sjge>AcQnY1R)?fmjeLu zTaSysDztGl$hjNgy|<^(*!1eX!$&%dPE0S19obI3mNk~@y9cz!R?qWT61|R;_Ilwx zZBuBSZB0_gibZtXPo0{EtLsBT89p0+_dUDi$zKOn_iI~yl^I#Tv$FAZ-TqPaurGUh zF&+ai)}$_Mi+?n=yQh+V$mjaD=A3a$(`Kz${i3)CpAJD(abWk+(NlX~JMNI$CFsUu%WdFwH;ns zo*SLl{R2{HmZT?c>cdQF{2AxqI1$AuXkI^kQz&NS46T@aw&37Yc-$2SUq79MTicpY zP(ySWuC@G@#zZeDH#cn*(-KD>=GOJ>Obq#rR%&%x%llzSY|oDmX@+Q;n}&^b=ME^L z$tp&G|Esl>dz`TsZPdmGcV3i5#rp5tX?cTJP`c_ukuEbkY~b3xJM*uU_+$(}NvR#2 z|IEO-zvMTLF2VS~_gOWLEvKf-mxZahSA0?FV{do-d11A0nm|3`8_nGONlF$wRUhG1 z5_!)+S0~*%FX-D#B|CI7q=18Hk@i+com~zxQu`P789SbpTOYGR1&7jPYgVHPy8;=^ z=-uA|q1*Fcvwr@5OMX7>OaF}z%Npz%IIeGd?^*M0d9BeK+dKPDSj^v9U)kSJO=&OJ zEI#z02$gc}NAu2zZ#Fzh%y3_^=cppwNfA<)+|@wj?YG?5sHjc4S|=UtjZd3U)TMNv zE0;1IE1oI{6^WCj-T33b}DIoG*wH@p~!mqtMZlj0|9`fF3eXGJcxl3S5JZ4tW z32gVYH$IgI*pz*K^3n=g`vlPq&QKj3vCf-E!u+&#>Ku$)rwdwwuS2 z18F{VtH^-g*Ue*F6y0k z-tA^oiLYocYJFqe0CYQ(8|#;7ba=wduET80M$e0ogYC=bMU`e5^O-*31;VD=8n_zs zfdba&833S`&GqyQWO#bM-D+@%^3<=X^h;~3a_=6>_jWL{G>>l!tXN66h*vn6AMmKQ zh)lr#I5Dq`XukqokQsO3!v5BptZgUjjp{QIuQcwD3|0*zmu@aLkGw4ZDSqBq>e$sg zvh<#6Y}dmwfOyCGdV6+BS6x2!m`?9PFP-?(h%4px-wm#69yJ-9`f7X3UwyC1lZvyg z>FIRWs|MGX4InB9elWZ?b=f4e@XPy>`|-Qc^y#*Q)*+W`-o=`g3vh%#lkV$$A3hTO zT~XnHM^5Mr-_=6b-!40$yB@~o)xK6rw;vceu=-IxTNm&SUP+pT65u}FWldc z!V>b)AX~_U&~m;Ab_D>qu9k~HRvaWnFrgT(fQlSDa~_G{vZ=^0Cx5KJ$P;ruW+PX->AA`&FaaNuf(SXECy-F&RHTZR0^ci#F-U|8B8{UW!~FvhosYoO|k9eCOU*zxqj$R;{RRPum zBL_to92$$^^D%Q*NTlA0Fv)B}|F}XD0{?x0~sGpcgtCIW|h$NvHP zZS5*BjPm!VcnMhv%AgD{DpHv*g)L-p*%Z|+7Eg2mU7ScL9Gl5R5wUD6io{_NP!I

b}C~z^bu%ObXFtchLu7%<$hCr!M z93m9*s7Ph52qmS;-U!#3rqH<(7?GrO{H*7Lq4=3^Gh2YiRZSrfD%(;()=Urym<7}5Cg&cd)82I$GQK|EC>sCgzQ8{;qXi>iil^EP)v}+L9uZl+&R#hNn|^J z$Sx6bq%u$pxyQhj!qvbAQdNUkuF`nLhiF+Wq!bXg6$(p0VaXvl0);@NI1wDNI11c6 z%xu9J<*t5Pu`A|(G;vh{<{Sg?x|uQfc!5tV%)8@iRx_oH|Ke-57yn`enEF$YkJ9&( zT%Y9nC<^^xi-4Kmzz*kPLpD$+|l40sJVW#a!#-1-t<| z0pMt%Ssy&2E22k80Kn+7@>1L5Xk-HqYD*dZ-rB<&x&}z62~nyTe%@_kc)5p!UwT}O zTdU!2oO4$z&sd*tM>Danh-E<_t7&T*qIx-fv){;L??gKcqtJ6)P5=5opHTz8UGZ*Osr_V&T)Ej=Qx(H_Z2+}jKua2AkUQi$EL>U^}R`cqe%>C z|8C=NidwpB%^S;7)3pEAoK8|Z@*hcd#=62>Q)8?$*y$o-ae6xWs6|9eUKMgzLA+Mg zQj5C1eS2y(i#WoHT#90S!BXTiA79?A{O=vHwO{g_>iF`C#W^-ssAwH){L3jy#g3{H=Sg^Fh)+7H9&u8DMw^c-4DE GXZ{zP?b-4G literal 0 HcmV?d00001 diff --git a/sdrgui/resources/res.qrc b/sdrgui/resources/res.qrc index 031ced019..cc76843c6 100644 --- a/sdrgui/resources/res.qrc +++ b/sdrgui/resources/res.qrc @@ -156,6 +156,7 @@ tab.png clockfile.png clockcurrent.png + mouse.png LiberationMono-Regular.ttf LiberationSans-Regular.ttf