From d3d6ebec89440f773c03555f9de0e42d46784d14 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 11 Dec 2016 11:35:25 +0100 Subject: [PATCH] CW Keyer with GUI. Sort of works --- CMakeLists.txt | 3 + plugins/channeltx/modam/ammod.cpp | 8 +- plugins/channeltx/modam/ammod.h | 2 + plugins/channeltx/modam/ammodgui.cpp | 14 + plugins/channeltx/modam/ammodgui.ui | 17 +- sdrbase/dsp/cwkeyer.cpp | 96 ++- sdrbase/dsp/cwkeyer.h | 24 +- sdrbase/gui/cwkeyergui.cpp | 269 ++++++ sdrbase/gui/cwkeyergui.h | 75 ++ sdrbase/gui/cwkeyergui.ui | 1187 +++++++++++++------------- 10 files changed, 1067 insertions(+), 628 deletions(-) create mode 100644 sdrbase/gui/cwkeyergui.cpp create mode 100644 sdrbase/gui/cwkeyergui.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c2dac7fa8..b39960963 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -138,6 +138,7 @@ set(sdrbase_SOURCES sdrbase/gui/buttonswitch.cpp sdrbase/gui/channelwindow.cpp sdrbase/gui/colormapper.cpp + sdrbase/gui/cwkeyergui.cpp sdrbase/gui/glscope.cpp sdrbase/gui/glscopegui.cpp sdrbase/gui/glshadersimple.cpp @@ -245,6 +246,7 @@ set(sdrbase_HEADERS sdrbase/gui/buttonswitch.h sdrbase/gui/channelwindow.h sdrbase/gui/colormapper.h + sdrbase/gui/cwkeyergui.h sdrbase/gui/glscope.h sdrbase/gui/glscopegui.h sdrbase/gui/glshadersimple.h @@ -303,6 +305,7 @@ set(sdrbase_FORMS sdrbase/gui/aboutdialog.ui sdrbase/gui/addpresetdialog.ui sdrbase/gui/basicchannelsettingswidget.ui + sdrbase/gui/cwkeyergui.ui sdrbase/gui/glscopegui.ui sdrbase/gui/glspectrumgui.ui sdrbase/gui/pluginsdialog.ui diff --git a/plugins/channeltx/modam/ammod.cpp b/plugins/channeltx/modam/ammod.cpp index e290541b3..8e026f88b 100644 --- a/plugins/channeltx/modam/ammod.cpp +++ b/plugins/channeltx/modam/ammod.cpp @@ -70,9 +70,8 @@ AMMod::AMMod() : // test CW keyer // TODO: link to CW keyer GUI m_cwKeyer.setSampleRate(m_config.m_audioSampleRate); - m_cwKeyer.setWPM(5); - m_cwKeyer.setText("PARIS PARIS PARIS PARIS PARIS"); - m_cwKeyer.setMode(CWKeyer::CWText); + m_cwKeyer.setWPM(13); + m_cwKeyer.setMode(CWKeyer::CWNone); } AMMod::~AMMod() @@ -192,9 +191,6 @@ void AMMod::pullAF(Real& sample) { sample = 0.0f; m_toneNco.setPhase(0); -// if (m_cwKeyer.eom()) { -// m_cwKeyer.resetText(); -// } } break; case AMModInputNone: diff --git a/plugins/channeltx/modam/ammod.h b/plugins/channeltx/modam/ammod.h index f6ee5a445..5325c529d 100644 --- a/plugins/channeltx/modam/ammod.h +++ b/plugins/channeltx/modam/ammod.h @@ -190,6 +190,8 @@ public: Real getMagSq() const { return m_magsq; } + CWKeyer *getCWKeyer() { return &m_cwKeyer; } + signals: /** * Level changed diff --git a/plugins/channeltx/modam/ammodgui.cpp b/plugins/channeltx/modam/ammodgui.cpp index 58c9be86b..5b4a11e2d 100644 --- a/plugins/channeltx/modam/ammodgui.cpp +++ b/plugins/channeltx/modam/ammodgui.cpp @@ -90,6 +90,7 @@ QByteArray AMModGUI::serialize() const s.writeS32(4, ui->modPercent->value()); s.writeU32(5, m_channelMarker.getColor().rgb()); s.writeS32(6, ui->volume->value()); + s.writeBlob(7, ui->cwKeyerGUI->serialize()); return s.final(); } @@ -130,6 +131,9 @@ bool AMModGUI::deserialize(const QByteArray& data) d.readS32(6, &tmp, 10); ui->volume->setValue(tmp); + d.readBlob(7, &bytetmp); + ui->cwKeyerGUI->deserialize(bytetmp); + blockApplySettings(false); m_channelMarker.blockSignals(false); @@ -266,6 +270,13 @@ void AMModGUI::on_morseKeyer_toggled(bool checked) ui->play->setEnabled(!checked); // release other source inputs ui->tone->setEnabled(!checked); // release other source inputs ui->mic->setEnabled(!checked); + + if (checked) { + ui->cwKeyerGUI->grabKeyboard(); + } else { + ui->cwKeyerGUI->releaseKeyboard(); + } + m_modAFInput = checked ? AMMod::AMModInputCWTone : AMMod::AMModInputNone; AMMod::MsgConfigureAFInput* message = AMMod::MsgConfigureAFInput::create(m_modAFInput); m_amMod->getInputMessageQueue()->push(message); @@ -374,8 +385,11 @@ AMModGUI::AMModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* pare ui->play->setEnabled(false); ui->play->setChecked(false); ui->tone->setChecked(false); + ui->morseKeyer->setChecked(false); ui->mic->setChecked(false); + ui->cwKeyerGUI->setBuddies(m_amMod->getInputMessageQueue(), m_amMod->getCWKeyer()); + applySettings(); connect(m_amMod->getOutputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages())); diff --git a/plugins/channeltx/modam/ammodgui.ui b/plugins/channeltx/modam/ammodgui.ui index 6e57945a9..bbe7f3046 100644 --- a/plugins/channeltx/modam/ammodgui.ui +++ b/plugins/channeltx/modam/ammodgui.ui @@ -7,7 +7,7 @@ 0 0 342 - 249 + 363 @@ -40,7 +40,7 @@ 10 10 320 - 211 + 341 @@ -474,6 +474,13 @@ + + + + + + + @@ -671,6 +678,12 @@
gui/levelmeter.h
1 + + CWKeyerGUI + QWidget +
gui/cwkeyergui.h
+ 1 +
diff --git a/sdrbase/dsp/cwkeyer.cpp b/sdrbase/dsp/cwkeyer.cpp index ab0e76b2e..f5209d722 100644 --- a/sdrbase/dsp/cwkeyer.cpp +++ b/sdrbase/dsp/cwkeyer.cpp @@ -156,6 +156,7 @@ const char CWKeyer::m_asciiToMorse[128][7] = { }; CWKeyer::CWKeyer() : + m_mutex(QMutex::Recursive), m_sampleRate(48000), m_textPointer(0), m_elementPointer(0), @@ -166,6 +167,7 @@ CWKeyer::CWKeyer() : m_dot(false), m_dash(false), m_elementOn(false), + m_loop(false), m_asciiChar('\0'), m_mode(CWKey), m_keyIambicState(KeySilent), @@ -178,43 +180,91 @@ CWKeyer::~CWKeyer() { } +void CWKeyer::setSampleRate(int sampleRate) +{ + m_mutex.lock(); + m_sampleRate = sampleRate; + m_mutex.unlock(); + setWPM(m_wpm); +} + void CWKeyer::setWPM(int wpm) { - if ((wpm > 0) && (wpm < 21)) + if ((wpm > 0) && (wpm < 27)) { + QMutexLocker mutexLocker(&m_mutex); + m_dotLength = (int) (0.24f * m_sampleRate * (5.0f / wpm)); m_wpm = wpm; - m_dotLength = (int) (0.24f * m_sampleRate * (wpm / 5.0f)); + } +} + +void CWKeyer::setText(const QString& text) +{ + QMutexLocker mutexLocker(&m_mutex); + m_text = text; + m_textState = TextStart; +} + +void CWKeyer::setMode(CWMode mode) +{ + if (mode != m_mode) + { + QMutexLocker mutexLocker(&m_mutex); + + if (mode == CWText) + { + m_textState = TextStart; + } + + m_mode = mode; + } +} + +void CWKeyer::setKey(bool key) +{ + if (m_mode == CWKey) + { + qDebug() << "CWKeyer::setKey: " << key; + m_key = key; } } void CWKeyer::setDot(bool dotOn) { - if (dotOn) + if (m_mode == CWIambic) { - m_dash = false; - m_dot = true; - } - else - { - m_dot = false; + if (dotOn) + { + m_dash = false; + m_dot = true; + } + else + { + m_dot = false; + } } } void CWKeyer::setDash(bool dashOn) { - if (dashOn) + if (m_mode == CWIambic) { - m_dot = false; - m_dash = true; - } - else - { - m_dash = false; + if (dashOn) + { + m_dot = false; + m_dash = true; + } + else + { + m_dash = false; + } } } int CWKeyer::getSample() { + QMutexLocker mutexLocker(&m_mutex); + if (m_mode == CWKey) { return m_key ? 1 : 0; @@ -324,6 +374,9 @@ void CWKeyer::nextStateText() m_elementPointer = 0; m_textPointer = 0; m_textState = TextStartChar; + m_key = false; + m_dot = false; + m_dash = false; break; case TextStartChar: m_samplePointer = 0; @@ -410,8 +463,19 @@ void CWKeyer::nextStateText() } break; case TextEnd: + if (m_loop) + { + m_textState = TextStart; + } + m_key = false; + m_dot = false; + m_dash = false; + break; + case TextStop: default: m_key = false; + m_dot = false; + m_dash = false; break; } } diff --git a/sdrbase/dsp/cwkeyer.h b/sdrbase/dsp/cwkeyer.h index 33b8aaf90..be32c6462 100644 --- a/sdrbase/dsp/cwkeyer.h +++ b/sdrbase/dsp/cwkeyer.h @@ -19,6 +19,8 @@ #define SDRBASE_DSP_CWKEYER_H_ #include +#include + #include "util/export.h" class SDRANGEL_API CWKeyer : public QObject { @@ -27,6 +29,7 @@ class SDRANGEL_API CWKeyer : public QObject { public: typedef enum { + CWNone, CWText, CWKey, CWIambic @@ -47,26 +50,34 @@ public: TextElement, TextCharSpace, TextWordSpace, - TextEnd + TextEnd, + TextStop } CWTextState; CWKeyer(); ~CWKeyer(); - void setSampleRate(int sampleRate) { m_sampleRate = sampleRate; } - void setWPM(int wpm); - void setText(const QString& text) { m_text = text; } - void setMode(CWMode mode) { m_mode = mode; } + void resetToDefaults(); + QByteArray serialize() const; + bool deserialize(const QByteArray& data); - void setKey(bool key) { m_key = key; }; + void setSampleRate(int sampleRate); + void setWPM(int wpm); + void setText(const QString& text); + void setMode(CWMode mode); + void setLoop(bool loop) { m_loop = loop; } + + void setKey(bool key); void setDot(bool dotOn); void setDash(bool dashOn); int getSample(); bool eom(); void resetText() { m_textState = TextStart; } + void stopText() { m_textState = TextStop; } private: + QMutex m_mutex; int m_sampleRate; int m_wpm; int m_dotLength; //!< dot length in samples @@ -80,6 +91,7 @@ private: bool m_dot; bool m_dash; bool m_elementOn; + bool m_loop; char m_asciiChar; CWMode m_mode; CWKeyIambicState m_keyIambicState; diff --git a/sdrbase/gui/cwkeyergui.cpp b/sdrbase/gui/cwkeyergui.cpp new file mode 100644 index 000000000..e64bd2582 --- /dev/null +++ b/sdrbase/gui/cwkeyergui.cpp @@ -0,0 +1,269 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 F4EXB // +// written by Edouard Griffiths // +// // +// 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 // +// // +// 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 "gui/cwkeyergui.h" +#include "ui_cwkeyergui.h" +#include "dsp/cwkeyer.h" +#include "util/simpleserializer.h" + +CWKeyerGUI::CWKeyerGUI(QWidget* parent) : + QWidget(parent), + ui(new Ui::CWKeyerGUI), + m_messageQueue(0), + m_cwKeyer(0), + m_key(0x30), + m_keyDot(0x31), + m_keyDash(0x32) +{ + ui->setupUi(this); +} + +CWKeyerGUI::~CWKeyerGUI() +{ + this->releaseKeyboard(); // just in case + delete ui; +} + +void CWKeyerGUI::setBuddies(MessageQueue* messageQueue, CWKeyer* cwKeyer) +{ + m_messageQueue = messageQueue; + m_cwKeyer = cwKeyer; + applySettings(); +} + +void CWKeyerGUI::resetToDefaults() +{ + m_key = false; + m_keyDot = false; + m_keyDash = false; +} + +QByteArray CWKeyerGUI::serialize() const +{ + SimpleSerializer s(1); + + s.writeString(1, ui->cwTextEdit->text()); + s.writeS32(2, ui->cwSpeed->value()); + s.writeS32(3, ui->morseKeyAssign->currentIndex()); + s.writeS32(4, ui->iambicKeyDotAssign->currentIndex()); + s.writeS32(5, ui->iambicKeyDashAssign->currentIndex()); + + return s.final(); +} + +bool CWKeyerGUI::deserialize(const QByteArray& data) +{ + SimpleDeserializer d(data); + + if(!d.isValid()) + { + resetToDefaults(); + return false; + } + + if(d.getVersion() == 1) + { + QString aString; + int aValue; + + d.readString(1, &aString, ""); + ui->cwTextEdit->setText(aString); + d.readS32(2, &aValue, 13); + ui->cwSpeed->setValue(aValue); + d.readS32(3, &aValue, 0); + ui->morseKeyAssign->setCurrentIndex(aValue); + d.readS32(4, &aValue, 1); + ui->iambicKeyDotAssign->setCurrentIndex(aValue); + d.readS32(5, &aValue, 2); + ui->iambicKeyDashAssign->setCurrentIndex(aValue); + + applySettings(); + return true; + } +} + +// === SLOTS ================================================================== + +void CWKeyerGUI::on_cwTextClear_clicked(bool checked) +{ + ui->cwTextEdit->clear(); + m_cwKeyer->setText(""); +} + +void CWKeyerGUI::on_cwTextEdit_editingFinished() +{ + m_cwKeyer->setText(ui->cwTextEdit->text()); +} + +void CWKeyerGUI::on_cwSpeed_valueChanged(int value) +{ + ui->cwSpeedText->setText(QString("%1").arg(value)); + m_cwKeyer->setWPM(value); +} + +void CWKeyerGUI::on_morseKey_toggled(bool checked) +{ + //ui->morseKey->setEnabled(!checked); + ui->iambicKey->setEnabled(!checked); + ui->playStop->setEnabled(!checked); + m_cwKeyer->setMode(checked ? CWKeyer::CWKey : CWKeyer::CWNone); +} + +void CWKeyerGUI::on_morseKeyAssign_currentIndexChanged(int index) +{ + if ((index >= 0) && (index < 9)) { + m_key = 0x30 + index; + } +} + +void CWKeyerGUI::on_iambicKey_toggled(bool checked) +{ + ui->morseKey->setEnabled(!checked); + //ui->iambicKey->setEnabled(!checked); + ui->playStop->setEnabled(!checked); + m_cwKeyer->setMode(checked ? CWKeyer::CWIambic : CWKeyer::CWNone); +} + +void CWKeyerGUI::on_iambicKeyDotAssign_currentIndexChanged(int index) +{ + if ((index >= 0) && (index < 9)) { + m_keyDot = 0x30 + index; + } +} + +void CWKeyerGUI::on_iambicKeyDashAssign_currentIndexChanged(int index) +{ + if ((index >= 0) && (index < 9)) { + m_keyDash = 0x30 + index; + } +} + +void CWKeyerGUI::on_playText_toggled(bool checked) +{ + ui->morseKey->setEnabled(!checked); + ui->iambicKey->setEnabled(!checked); + //ui->playStop->setEnabled(!checked); + m_cwKeyer->setMode(checked ? CWKeyer::CWText : CWKeyer::CWNone); +} + +void CWKeyerGUI::on_playLoop_toggled(bool checked) +{ + m_cwKeyer->setLoop(checked); +} + +void CWKeyerGUI::on_playStop_toggled(bool checked) +{ + if (checked) + { + m_cwKeyer->resetText(); + } + else + { + m_cwKeyer->stopText(); + } +} + +// === End SLOTS ============================================================== + +void CWKeyerGUI::applySettings() +{ + int value; + + m_cwKeyer->setText(ui->cwTextEdit->text()); + + value = ui->cwSpeed->value(); + ui->cwSpeedText->setText(QString("%1").arg(value)); + m_cwKeyer->setWPM(value); + + value = ui->morseKeyAssign->currentIndex(); + if ((value >= 0) && (value < 9)) { + m_key = 0x30 + value; + } + + value = ui->iambicKeyDotAssign->currentIndex(); + if ((value >= 0) && (value < 9)) { + m_keyDot = 0x30 + value; + } + + value = ui->iambicKeyDashAssign->currentIndex(); + if ((value >= 0) && (value < 9)) { + m_keyDash = 0x30 + value; + } +} + +void CWKeyerGUI::keyPressEvent(QKeyEvent* keyEvent) +{ + int key = keyEvent->key(); + + // Escape halts CW engine and releases keyboard immediately + // Thus keyboard cannot be left stuck + if (key == Qt::Key_Escape) + { + m_cwKeyer->setMode(CWKeyer::CWNone); + ui->morseKey->setChecked(false); + ui->iambicKey->setChecked(false); + ui->playStop->setChecked(false); + ui->morseKey->setEnabled(true); + ui->iambicKey->setEnabled(true); + ui->playStop->setEnabled(true); + this->releaseKeyboard(); + return; + } + + if (!keyEvent->isAutoRepeat()) + { + qDebug() << "CWKeyerGUI::keyPressEvent: key" + << ": " << key; + if (key == m_key) + { + m_cwKeyer->setKey(true); + } + else if (key == m_keyDot) + { + m_cwKeyer->setDot(true); + } + else if (key == m_keyDash) + { + m_cwKeyer->setDash(true); + } + } +} + +void CWKeyerGUI::keyReleaseEvent(QKeyEvent* keyEvent) +{ + if (!keyEvent->isAutoRepeat()) + { + qDebug() << "CWKeyerGUI::keyReleaseEvent: key" + << ": " << keyEvent->key(); + if (keyEvent->key() == m_key) + { + m_cwKeyer->setKey(false); + } + else if (keyEvent->key() == m_keyDot) + { + m_cwKeyer->setDot(false); + } + else if (keyEvent->key() == m_keyDash) + { + m_cwKeyer->setDash(false); + } + } +} + diff --git a/sdrbase/gui/cwkeyergui.h b/sdrbase/gui/cwkeyergui.h new file mode 100644 index 000000000..0afc1e8a8 --- /dev/null +++ b/sdrbase/gui/cwkeyergui.h @@ -0,0 +1,75 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 F4EXB // +// written by Edouard Griffiths // +// // +// 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 // +// // +// 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 SDRBASE_GUI_CWKEYERGUI_H_ +#define SDRBASE_GUI_CWKEYERGUI_H_ + +#include +#include "dsp/dsptypes.h" +#include "util/export.h" + +namespace Ui { + class CWKeyerGUI; +} + +class MessageQueue; +class CWKeyer; + +class SDRANGEL_API CWKeyerGUI : public QWidget { + Q_OBJECT + +public: + explicit CWKeyerGUI(QWidget* parent = NULL); + ~CWKeyerGUI(); + + void setBuddies(MessageQueue* messageQueue, CWKeyer* cwKeyer); + + void resetToDefaults(); + QByteArray serialize() const; + bool deserialize(const QByteArray& data); + +protected: + void keyPressEvent(QKeyEvent* keyEvent); + void keyReleaseEvent(QKeyEvent* keyEvent); + +private: + Ui::CWKeyerGUI* ui; + + MessageQueue* m_messageQueue; + CWKeyer* m_cwKeyer; + int m_key; + int m_keyDot; + int m_keyDash; + + void applySettings(); + +private slots: + void on_cwTextClear_clicked(bool checked); + void on_cwTextEdit_editingFinished(); + void on_cwSpeed_valueChanged(int value); + void on_morseKey_toggled(bool checked); + void on_morseKeyAssign_currentIndexChanged(int index); + void on_iambicKey_toggled(bool checked); + void on_iambicKeyDotAssign_currentIndexChanged(int index); + void on_iambicKeyDashAssign_currentIndexChanged(int index); + void on_playText_toggled(bool checked); + void on_playLoop_toggled(bool checked); + void on_playStop_toggled(bool checked); +}; + + +#endif /* SDRBASE_GUI_CWKEYERGUI_H_ */ diff --git a/sdrbase/gui/cwkeyergui.ui b/sdrbase/gui/cwkeyergui.ui index 10ac04079..e981c7383 100644 --- a/sdrbase/gui/cwkeyergui.ui +++ b/sdrbase/gui/cwkeyergui.ui @@ -1,598 +1,589 @@ - - - CWKeyerGUI - - - - 0 - 0 - 375 - 60 - - - - - Sans Serif - 8 - - - - CW Keyer - - - - 2 - - - 3 - - - - - 3 - - - - - - 0 - 0 - - - - - 24 - 24 - - - - Audio tone - - - Histogram - - - - :/mono.png:/mono.png - - - - 16 - 16 - - - - true - - - - - - - - 24 - 24 - - - - Audio tone volume - - - 240 - - - 1 - - - - - - - - 9 - - - - 1.0 - - - - - - - Qt::Vertical - - - - - - - - 24 - 24 - - - - CW speed (WPM) - - - 0 - - - 20 - - - 1 - - - - - - - - 9 - - - - CW speed display (WPM) - - - 13 - - - - - - - - 0 - 0 - - - - - 24 - 24 - - - - Morse key - - - Max Hold - - - - :/morsekey.png:/morsekey.png - - - - 16 - 16 - - - - true - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 35 - 16777215 - - - - - 9 - - - - Morse key assignment - - - - 0 - - - - - 1 - - - - - 2 - - - - - 3 - - - - - 4 - - - - - 5 - - - - - 6 - - - - - 7 - - - - - 8 - - - - - 9 - - - - - - - - - 0 - 0 - - - - - 24 - 24 - - - - Iambic key - - - Max Hold - - - - :/iambickey.png:/iambickey.png - - - - 16 - 16 - - - - true - - - - - - - - 0 - 0 - - - - - 35 - 16777215 - - - - - 9 - - - - Iambic key dot assignment - - - - 0 - - - - - 1 - - - - - 2 - - - - - 3 - - - - - 4 - - - - - 5 - - - - - 6 - - - - - 7 - - - - - 8 - - - - - 9 - - - - - - - - - 0 - 0 - - - - - 35 - 16777215 - - - - - 9 - - - - Iambic key dash assignment - - - - 0 - - - - - 1 - - - - - 2 - - - - - 3 - - - - - 4 - - - - - 5 - - - - - 6 - - - - - 7 - - - - - 8 - - - - - 9 - - - - - - - - Qt::Vertical - - - - - - - - 0 - 0 - - - - - 24 - 24 - - - - Play text in a loop - - - Inv - - - - :/playloop.png:/playloop.png - - - - 16 - 16 - - - - true - - - - - - - - 0 - 0 - - - - - 24 - 24 - - - - Play / pause text - - - Waterfall - - - - :/play.png - :/pause.png:/play.png - - - - 16 - 16 - - - - true - - - false - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - CW text - - - - - - - - 24 - 24 - - - - - 24 - 24 - - - - Clear CW text - - - - - - - :/clear.png:/clear.png - - - - 16 - 16 - - - - - - - - - - - ButtonSwitch - QToolButton -
gui/buttonswitch.h
-
-
- - morseKey - playLoop - - - - - -
+ + + CWKeyerGUI + + + + 0 + 0 + 375 + 60 + + + + + Sans Serif + 8 + + + + CW Keyer + + + + 2 + + + 3 + + + + + 3 + + + + + + 24 + 24 + + + + CW speed (WPM) + + + 1 + + + 26 + + + 1 + + + 13 + + + + + + + + 9 + + + + CW speed display (WPM) + + + 13 + + + + + + + + 0 + 0 + + + + + 24 + 24 + + + + Morse key + + + + :/morsekey.png:/morsekey.png + + + + 16 + 16 + + + + true + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 35 + 16777215 + + + + + 9 + + + + Morse key assignment + + + + 0 + + + + + 1 + + + + + 2 + + + + + 3 + + + + + 4 + + + + + 5 + + + + + 6 + + + + + 7 + + + + + 8 + + + + + 9 + + + + + + + + + 0 + 0 + + + + + 24 + 24 + + + + Iambic key + + + + :/iambickey.png:/iambickey.png + + + + 16 + 16 + + + + true + + + + + + + + 0 + 0 + + + + + 35 + 16777215 + + + + + 9 + + + + Iambic key dot assignment + + + 1 + + + + 0 + + + + + 1 + + + + + 2 + + + + + 3 + + + + + 4 + + + + + 5 + + + + + 6 + + + + + 7 + + + + + 8 + + + + + 9 + + + + + + + + + 0 + 0 + + + + + 35 + 16777215 + + + + + 9 + + + + Iambic key dash assignment + + + 2 + + + + 0 + + + + + 1 + + + + + 2 + + + + + 3 + + + + + 4 + + + + + 5 + + + + + 6 + + + + + 7 + + + + + 8 + + + + + 9 + + + + + + + + Qt::Vertical + + + + + + + + 0 + 0 + + + + + 24 + 24 + + + + + + + + + 255 + 255 + 255 + + + + + + + + + 255 + 255 + 255 + + + + + + + + + 106 + 104 + 100 + + + + + + + + + DejaVu Serif + 9 + 75 + true + + + + T + + + true + + + + + + + + 0 + 0 + + + + + 24 + 24 + + + + Play text in a loop + + + + :/playloop.png:/playloop.png + + + + 16 + 16 + + + + true + + + + + + + + 0 + 0 + + + + + 24 + 24 + + + + Play / pause text coding + + + + :/play.png + :/stop.png:/play.png + + + + 16 + 16 + + + + true + + + false + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + CW text + + + + + + + + 24 + 24 + + + + + 24 + 24 + + + + Clear CW text + + + + + + + :/clear.png:/clear.png + + + + 16 + 16 + + + + + + + + + + + ButtonSwitch + QToolButton +
gui/buttonswitch.h
+
+
+ + morseKey + playLoop + + + + + +