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 @@
1
+
+ CWKeyerGUI
+ QWidget
+
+ 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
-
-
-
-
- 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
+
+
+
+
+ morseKey
+ playLoop
+
+
+
+
+
+