diff --git a/CatRadio.pro b/CatRadio.pro new file mode 100644 index 0000000..4fdc6ae --- /dev/null +++ b/CatRadio.pro @@ -0,0 +1,51 @@ +QT += core gui + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# You can make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \ + dialogconfig.cpp \ + dialogsetup.cpp \ + guidata.cpp \ + main.cpp \ + mainwindow.cpp \ + rigcommand.cpp \ + rigdaemon.cpp \ + rigdata.cpp \ + smeter.cpp \ + submeter.cpp \ + vfodisplay.cpp + +HEADERS += \ + dialogconfig.h \ + dialogsetup.h \ + guidata.h \ + mainwindow.h \ + rigcommand.h \ + rigdaemon.h \ + rigdata.h \ + smeter.h \ + submeter.h \ + vfodisplay.h + +FORMS += \ + dialogconfig.ui \ + dialogsetup.ui \ + mainwindow.ui + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +LIBS += -L$$PWD/hamlib/ -llibhamlib +INCLUDEPATH += $$PWD/hamlib + +VERSION = 1.0.0 + +RC_ICONS = catradio.ico diff --git a/CatRadio.pro.user b/CatRadio.pro.user new file mode 100644 index 0000000..7239cd7 --- /dev/null +++ b/CatRadio.pro.user @@ -0,0 +1,426 @@ + + + + + + EnvironmentId + {3eda28a5-2ae6-4f98-9ee1-3326cb54ce82} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + false + true + false + 0 + true + true + 0 + 8 + true + false + 1 + true + true + true + *.md, *.MD, Makefile + false + true + + + + ProjectExplorer.Project.PluginSettings + + + true + false + true + true + true + true + + + 0 + true + + -fno-delayed-template-parsing + + true + Builtin.BuildSystem + + true + true + Builtin.DefaultTidyAndClazy + 4 + + + + true + + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop Qt 5.15.2 MinGW 32-bit + Desktop Qt 5.15.2 MinGW 32-bit + qt.qt5.5152.win32_mingw81_kit + 0 + 0 + 0 + + 0 + C:\Users\Johnny\Documents\QT\build-CatRadio-Desktop_Qt_5_15_2_MinGW_32_bit-Debug + C:/Users/Johnny/Documents/QT/build-CatRadio-Desktop_Qt_5_15_2_MinGW_32_bit-Debug + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + + Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + + + C:\Users\Johnny\Documents\QT\build-CatRadio-Desktop_Qt_5_15_2_MinGW_32_bit-Release + C:/Users/Johnny/Documents/QT/build-CatRadio-Desktop_Qt_5_15_2_MinGW_32_bit-Release + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + + Release + Qt4ProjectManager.Qt4BuildConfiguration + 0 + 0 + + + 0 + C:\Users\Johnny\Documents\QT\build-CatRadio-Desktop_Qt_5_15_2_MinGW_32_bit-Profile + C:/Users/Johnny/Documents/QT/build-CatRadio-Desktop_Qt_5_15_2_MinGW_32_bit-Profile + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + + Profile + Qt4ProjectManager.Qt4BuildConfiguration + 0 + 0 + 0 + + 3 + + + 0 + Deploy + Deploy + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + ProjectExplorer.DefaultDeployConfiguration + + 1 + + true + true + true + + 2 + + CatRadio2 + Qt4ProjectManager.Qt4RunConfiguration:C:/Users/Johnny/Documents/QT/CatRadio_1.0.0/CatRadio.pro + C:/Users/Johnny/Documents/QT/CatRadio_1.0.0/CatRadio.pro + false + true + true + false + true + C:/Users/Johnny/Documents/QT/build-CatRadio-Desktop_Qt_5_15_2_MinGW_32_bit-Debug + + 1 + + + + ProjectExplorer.Project.Target.1 + + Desktop + Desktop Qt 6.1.3 MinGW 64-bit + Desktop Qt 6.1.3 MinGW 64-bit + qt.qt6.613.win64_mingw81_kit + 1 + 0 + 0 + + 0 + C:\Users\Johnny\Documents\QT\build-CatRadio-Desktop_Qt_6_1_3_MinGW_64_bit-Debug + C:/Users/Johnny/Documents/QT/build-CatRadio-Desktop_Qt_6_1_3_MinGW_64_bit-Debug + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + + Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + + + C:\Users\Johnny\Documents\QT\build-CatRadio-Desktop_Qt_6_1_3_MinGW_64_bit-Release + C:/Users/Johnny/Documents/QT/build-CatRadio-Desktop_Qt_6_1_3_MinGW_64_bit-Release + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + + Release + Qt4ProjectManager.Qt4BuildConfiguration + 0 + 0 + + + 0 + C:\Users\Johnny\Documents\QT\build-CatRadio-Desktop_Qt_6_1_3_MinGW_64_bit-Profile + C:/Users/Johnny/Documents/QT/build-CatRadio-Desktop_Qt_6_1_3_MinGW_64_bit-Profile + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + + Profile + Qt4ProjectManager.Qt4BuildConfiguration + 0 + 0 + 0 + + 3 + + + 0 + Deploy + Deploy + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + ProjectExplorer.DefaultDeployConfiguration + + 1 + + true + true + true + + 2 + + Qt4ProjectManager.Qt4RunConfiguration:C:/Users/Johnny/Documents/QT/CatRadio/CatRadio.pro + C:/Users/Johnny/Documents/QT/CatRadio/CatRadio.pro + false + true + true + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 2 + + + ProjectExplorer.Project.Updater.FileVersion + 22 + + + Version + 22 + + diff --git a/CatRadio.qss b/CatRadio.qss new file mode 100644 index 0000000..b1463fe --- /dev/null +++ b/CatRadio.qss @@ -0,0 +1,1249 @@ +/*Copyright (c) DevSec Studio. All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +/*-----QWidget-----*/ +QWidget +{ + background-color: qlineargradient(spread:repeat, x1:1, y1:0, x2:1, y2:1, stop:0 rgba(102, 115, 140, 255),stop:1 rgba(56, 63, 77, 255)); + color: #ffffff; + border-color: #051a39; + +} + + +/*-----QLabel-----*/ +QLabel +{ + background-color: transparent; + color: #ffffff; + font-weight: bold; + +} + + +QLabel::disabled +{ + background-color: transparent; + color: #898988; + +} + + +/*-----QMenuBar-----*/ +QMenuBar +{ + background-color: #484c58; + color: #ffffff; + border-color: #051a39; + font-weight: bold; + +} + + +QMenuBar::disabled +{ + background-color: #404040; + color: #898988; + border-color: #051a39; + +} + + +QMenuBar::item +{ + background-color: transparent; + +} + + +QMenuBar::item:selected +{ + background-color: #c4c5c3; + color: #000000; + border: 1px solid #000000; + +} + + +QMenuBar::item:pressed +{ + background-color: #979796; + border: 1px solid #000; + margin-bottom: -1px; + padding-bottom: 1px; + +} + + +/*-----QMenu-----*/ +QMenu +{ + background-color: #c4c5c3; + border: 1px solid; + color: #000000; + font-weight: bold; + +} + + +QMenu::separator +{ + height: 1px; + background-color: #363942; + color: #ffffff; + padding-left: 4px; + margin-left: 10px; + margin-right: 5px; + +} + + +QMenu::item +{ + min-width : 150px; + padding: 3px 20px 3px 20px; + +} + + +QMenu::item:selected +{ + background-color: #363942; + color: #ffffff; + +} + + +QMenu::item:disabled +{ + color: #898988; +} + + +/*-----QToolTip-----*/ +QToolTip +{ + background-color: #bbbcba; + color: #000000; + border-color: #051a39; + border : 1px solid #000000; + border-radius: 2px; + +} + + +/*-----QPushButton-----*/ +QPushButton +{ + background-color: qlineargradient(spread:repeat, x1:0.486, y1:0, x2:0.505, y2:1, stop:0.00480769 rgba(170, 0, 0, 255),stop:1 rgba(122, 0, 0, 255)); + color: #ffffff; + font-weight: bold; + border-style: solid; + border-width: 1px; + border-radius: 3px; + border-color: #051a39; + padding: 5px; + +} + + +QPushButton::disabled +{ + background-color: #404040; + color: #656565; + border-color: #051a39; + +} + + +QPushButton::hover +{ + background-color: #9c0000; + color: #ffffff; + border-style: solid; + border-width: 1px; + border-radius: 3px; + border-color: #051a39; + padding: 5px; + +} + + +QPushButton::pressed +{ + background-color: #880000; + color: #ffffff; + border-style: solid; + border-width: 2px; + border-radius: 3px; + border-color: #000000; + padding: 5px; + +} + + +/*-----QToolButton-----*/ +QToolButton +{ + background-color: qlineargradient(spread:repeat, x1:1, y1:0, x2:1, y2:1, stop:0 rgba(177, 181, 193, 255),stop:1 rgba(159, 163, 174, 255)); + color: #ffffff; + font-weight: bold; + border-style: solid; + border-width: 1px; + border-radius: 3px; + border-color: #051a39; + padding: 5px; + +} + + +QToolButton::disabled +{ + background-color: #404040; + color: #656565; + border-color: #051a39; + +} + + +QToolButton::hover +{ + background-color: #9fa3ae; + color: #ffffff; + border-style: solid; + border-width: 1px; + border-radius: 3px; + border-color: #051a39; + padding: 5px; + +} + + +QToolButton::pressed +{ + background-color: #7b7e86; + color: #ffffff; + border-style: solid; + border-width: 2px; + border-radius: 3px; + border-color: #000000; + padding: 5px; + +} + + +/*-----QComboBox-----*/ +QComboBox +{ + background-color: qlineargradient(spread:repeat, x1:1, y1:0, x2:1, y2:1, stop:0 rgba(118, 118, 118, 255),stop:1 rgba(70, 70, 70, 255)); + border: 1px solid #333333; + border-radius: 3px; + padding-left: 6px; + color: lightgray; + font-weight: bold; + height: 20px; + +} + + +QComboBox::disabled +{ + background-color: #404040; + color: #656565; + border-color: #051a39; + +} + + +QComboBox:hover +{ + background-color: #646464; + +} + + +QComboBox:on +{ + background-color: #979796; + color: #000000; + +} + + +QComboBox QAbstractItemView +{ + background-color: #c4c5c3; + color: #000000; + border: 1px solid black; + selection-background-color: #363942; + selection-color: #ffffff; + outline: 0; + +} + + +QComboBox::drop-down +{ + subcontrol-origin: padding; + subcontrol-position: top right; + width: 15px; + border-left-width: 1px; + border-left-color: darkgray; + border-left-style: solid; + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; + +} + + +QComboBox::down-arrow +{ + image: url(://arrow-down.png); + width: 8px; + height: 8px; +} + + +/*-----QSpinBox & QDoubleSpinBox & QDateTimeEdit-----*/ +QSpinBox, +QDoubleSpinBox, +QDateTimeEdit +{ + background-color: #000000; + color: #00ff00; + font-weight: bold; + border: 1px solid #333333; + padding : 4px; + +} + + +QSpinBox::disabled, +QDoubleSpinBox::disabled, +QDateTimeEdit::disabled +{ + background-color: #404040; + color: #656565; + border-color: #051a39; + +} + + +QSpinBox:hover, +QDoubleSpinBox::hover, +QDateTimeEdit::hover +{ + border: 1px solid #00ff00; + +} + + +QSpinBox::up-button, QSpinBox::down-button, +QDoubleSpinBox::up-button, QDoubleSpinBox::down-button, +QDateTimeEdit::up-button, QDateTimeEdit::down-button +{ + background-color: qlineargradient(spread:repeat, x1:1, y1:0, x2:1, y2:1, stop:0 rgba(118, 118, 118, 255),stop:1 rgba(70, 70, 70, 255)); + border: 0px solid #333333; + +} + + +QSpinBox::disabled, +QDoubleSpinBox::disabled, +QDateTimeEdit::disabled +{ + background-color: #404040; + color: #656565; + border-color: #051a39; + +} + + +QSpinBox::up-button:hover, QSpinBox::down-button:hover, +QDoubleSpinBox::up-button:hover, QDoubleSpinBox::down-button:hover, +QDateTimeEdit::up-button:hover, QDateTimeEdit::down-button:hover +{ + background-color: #646464; + border: 1px solid #333333; + + +} + + +QSpinBox::up-button:disabled, QSpinBox::down-button:disabled, +QDoubleSpinBox::up-button:disabled, QDoubleSpinBox::down-button:disabled, +QDateTimeEdit::up-button:disabled, QDateTimeEdit::down-button:disabled +{ + background-color: #404040; + color: #656565; + border-color: #051a39; + +} + + +QSpinBox::up-button:pressed, QSpinBox::down-button:pressed, +QDoubleSpinBox::up-button:pressed, QDoubleSpinBox::down-button::pressed, +QDateTimeEdit::up-button:pressed, QDateTimeEdit::down-button::pressed +{ + background-color: #979796; + border: 1px solid #444444; + +} + + +QSpinBox::down-arrow, +QDoubleSpinBox::down-arrow, +QDateTimeEdit::down-arrow +{ + image: url(://arrow-down.png); + width: 7px; + +} + + +QSpinBox::up-arrow, +QDoubleSpinBox::up-arrow, +QDateTimeEdit::up-arrow +{ + image: url(://arrow-up.png); + width: 7px; + +} + + +/*-----QLineEdit-----*/ +QLineEdit +{ + background-color: #000000; + color: #00ff00; + font-weight: bold; + border: 1px solid #333333; + padding: 4px; + +} + + +QLineEdit:hover +{ + border: 1px solid #00ff00; + +} + + +QLineEdit::disabled +{ + background-color: #404040; + color: #656565; + border-width: 1px; + border-color: #051a39; + padding: 2px; + +} + + +/*-----QTextEdit-----*/ +QTextEdit +{ + background-color: #808080; + color: #fff; + border: 1px groove #333333; + +} + + +QTextEdit::disabled +{ + background-color: #404040; + color: #656565; + border-color: #051a39; + +} + + +/*-----QGroupBox-----*/ +QGroupBox +{ + border: 1px groove #333333; + border-radius: 2px; + margin-top: 20px; + +} + + +QGroupBox +{ + background-color: qlineargradient(spread:repeat, x1:0.486, y1:0, x2:0.505, y2:1, stop:0.00480769 rgba(170, 169, 169, 255),stop:1 rgba(122, 122, 122, 255)); + font-weight: bold; + +} + + +QGroupBox::title +{ + background-color: qlineargradient(spread:repeat, x1:1, y1:0, x2:1, y2:1, stop:0 rgba(71, 75, 87, 255),stop:1 rgba(35, 37, 43, 255)); + color: #ffffff; + border: 2px groove #333333; + subcontrol-origin: margin; + subcontrol-position: top left; + padding: 2px; + +} + + +QGroupBox::title::disabled +{ + background-color: #404040; + color: #656565; + subcontrol-origin: margin; + subcontrol-position: top left; + padding: 5px; + border-top-left-radius: 3px; + border-top-right-radius: 3px; + +} + + +/*-----QCheckBox-----*/ +QCheckBox{ + background-color: transparent; + font-weight: bold; + color: #fff; + +} + + +QCheckBox::indicator +{ + color: #b1b1b1; + background-color: #323232; + border: 2px solid #222222; + width: 12px; + height: 12px; + +} + + +QCheckBox::indicator:checked +{ + image:url(://checkbox.png); + border: 2px solid #00ff00; + +} + + +QCheckBox::indicator:unchecked:hover +{ + border: 2px solid #00ff00; + +} + + +QCheckBox::disabled +{ + color: #656565; + +} + + +QCheckBox::indicator:disabled +{ + background-color: #656565; + color: #656565; + border: 1px solid #656565; + +} + + +/*-----QRadioButton-----*/ +QRadioButton{ + background-color: transparent; + font-weight: bold; + color: #fff; + +} + + +QRadioButton::indicator::unchecked +{ + border: 2px inset #222222; + border-radius: 6px; + background-color: #323232; + width: 9px; + height: 9px; + +} + + +QRadioButton::indicator::unchecked:hover +{ + border: 2px solid #00ff00; + border-radius: 5px; + background-color: #323232; + width: 9px; + height: 9px; + +} + + +QRadioButton::indicator::checked +{ + border: 2px inset #222222; + border-radius: 5px; + background-color: #00ff00; + width: 9px; + height: 9px; + +} + + +QRadioButton::disabled +{ + color: #656565; + +} + + +QRadioButton::indicator:disabled +{ + background-color: #656565; + color: #656565; + border: 2px solid #656565; + +} + + +/*-----QTableView & QTableWidget-----*/ +QTableView +{ + background-color: #808080; + border: 1px groove #333333; + color: #f0f0f0; + font-weight: bold; + gridline-color: #333333; + outline : 0; + +} + + +QTableView::disabled +{ + background-color: #242526; + border: 1px solid #32414B; + color: #656565; + gridline-color: #656565; + outline : 0; + +} + + +QTableView::item:hover +{ + background-color: #484c58; + color: #f0f0f0; + +} + + +QTableView::item:selected +{ + background-color: #484c58; + border: 2px groove #00ff00; + color: #F0F0F0; + +} + + +QTableView::item:selected:disabled +{ + background-color: #1a1b1c; + border: 2px solid #525251; + color: #656565; + +} + + +QTableCornerButton::section +{ + background-color: #282830; + +} + + +QHeaderView::section +{ + background-color: #282830; + color: #fff; + font-weight: bold; + text-align: left; + padding: 4px; + +} + + +QHeaderView::section:disabled +{ + background-color: #525251; + color: #656565; + +} + + +QHeaderView::section:checked +{ + background-color: #00ff00; + +} + + +QHeaderView::section:checked:disabled +{ + color: #656565; + background-color: #525251; + +} + + +QHeaderView::section::vertical::first, +QHeaderView::section::vertical::only-one +{ + border-top: 0px; + +} + + +QHeaderView::section::vertical +{ + border-top: 0px; + +} + + +QHeaderView::section::horizontal::first, +QHeaderView::section::horizontal::only-one +{ + border-left: 0px; + +} + + +QHeaderView::section::horizontal +{ + border-left: 0px; + +} + + +/*-----QTabWidget-----*/ +QTabBar::tab +{ + background-color: transparent; + color: #ffffff; + font-weight: bold; + width: 80px; + height: 9px; + +} + + +QTabBar::tab:disabled +{ + background-color: #656565; + color: #656565; + +} + + +QTabWidget::pane +{ + background-color: transparent; + color: #ffffff; + border: 1px groove #333333; + +} + + +QTabBar::tab:selected +{ + background-color: #484c58; + color: #ffffff; + border: 1px groove #333333; + border-bottom: 0px; + +} + + +QTabBar::tab:selected:disabled +{ + background-color: #404040; + color: #656565; + +} + + +QTabBar::tab:!selected +{ + background-color: #a3a7b2; + +} + + +QTabBar::tab:!selected:hover +{ + background-color: #484c58; + +} + + +QTabBar::tab:top:!selected +{ + margin-top: 1px; + +} + + +QTabBar::tab:bottom:!selected +{ + margin-bottom: 3px; + +} + + +QTabBar::tab:top, QTabBar::tab:bottom +{ + min-width: 8ex; + margin-right: -1px; + padding: 5px 10px 5px 10px; + +} + + +QTabBar::tab:top:selected +{ + border-bottom-color: none; + +} + + +QTabBar::tab:bottom:selected +{ + border-top-color: none; + +} + + +QTabBar::tab:top:last, QTabBar::tab:bottom:last, +QTabBar::tab:top:only-one, QTabBar::tab:bottom:only-one +{ + margin-right: 0; + +} + + +QTabBar::tab:left:!selected +{ + margin-right: 2px; + +} + + +QTabBar::tab:right:!selected +{ + margin-left: 2px; + +} + + +QTabBar::tab:left, QTabBar::tab:right +{ + min-height: 15ex; + margin-bottom: -1px; + padding: 10px 5px 10px 5px; + +} + + +QTabBar::tab:left:selected +{ + border-left-color: none; + +} + + +QTabBar::tab:right:selected +{ + border-right-color: none; + +} + + +QTabBar::tab:left:last, QTabBar::tab:right:last, +QTabBar::tab:left:only-one, QTabBar::tab:right:only-one +{ + margin-bottom: 0; + +} + + +/*-----QSlider-----*/ +QSlider{ + background-color: transparent; + +} + + +QSlider::groove:horizontal +{ + background-color: transparent; + height: 6px; + +} + + +QSlider::sub-page:horizontal +{ + background-color: qlineargradient(spread:reflect, x1:1, y1:0, x2:1, y2:1, stop:0.00480769 rgba(201, 201, 201, 255),stop:1 rgba(72, 72, 72, 255)); + border: 1px solid #000; + +} + + +QSlider::add-page:horizontal +{ + background-color: #404040; + border: 1px solid #000; + +} + + +QSlider::handle:horizontal +{ + background-color: qlineargradient(spread:reflect, x1:1, y1:0, x2:1, y2:1, stop:0.00480769 rgba(201, 201, 201, 255),stop:1 rgba(72, 72, 72, 255)); + border: 1px solid #000; + width: 12px; + margin-top: -6px; + margin-bottom: -6px; + +} + + +QSlider::handle:horizontal:hover +{ + background-color: #808080; + +} + + +QSlider::sub-page:horizontal:disabled +{ + background-color: #bbb; + border-color: #999; + +} + + +QSlider::add-page:horizontal:disabled +{ + background-color: #eee; + border-color: #999; + +} + + +QSlider::handle:horizontal:disabled +{ + background-color: #eee; + border: 1px solid #aaa; + +} + + +QSlider::groove:vertical +{ + background-color: transparent; + width: 6px; + +} + + +QSlider::sub-page:vertical +{ + background-color: qlineargradient(spread:reflect, x1:0, y1:0.483, x2:1, y2:0.517, stop:0.00480769 rgba(201, 201, 201, 255),stop:1 rgba(72, 72, 72, 255)); + border: 1px solid #000; + +} + + +QSlider::add-page:vertical +{ + background-color: #404040; + border: 1px solid #000; + +} + + +QSlider::handle:vertical +{ + background-color: qlineargradient(spread:reflect, x1:0, y1:0.483, x2:1, y2:0.517, stop:0.00480769 rgba(201, 201, 201, 255),stop:1 rgba(72, 72, 72, 255)); + border: 1px solid #000; + height: 12px; + margin-left: -6px; + margin-right: -6px; + +} + + +QSlider::handle:vertical:hover +{ + background-color: #808080; + +} + + +QSlider::sub-page:vertical:disabled +{ + background-color: #bbb; + border-color: #999; + +} + + +QSlider::add-page:vertical:disabled +{ + background-color: #eee; + border-color: #999; + +} + + +QSlider::handle:vertical:disabled +{ + background-color: #eee; + border: 1px solid #aaa; + border-radius: 3px; + +} + + +/*-----QDial-----*/ +QDial +{ + background-color: #600000; + +} + + +QDial::disabled +{ + background-color: #404040; + +} + + +/*-----QScrollBar-----*/ +QScrollBar:horizontal +{ + border: 1px solid #222222; + background-color: #63676d; + height: 18px; + margin: 0px 18px 0 18px; + +} + + +QScrollBar::handle:horizontal +{ + background-color: #a6acb3; + border: 1px solid #656565; + border-radius: 2px; + min-height: 20px; + +} + + +QScrollBar::add-line:horizontal +{ + border: 1px solid #1b1b19; + background-color: #a6acb3; + width: 18px; + subcontrol-position: right; + subcontrol-origin: margin; + +} + + +QScrollBar::sub-line:horizontal +{ + border: 1px solid #1b1b19; + background-color: #a6acb3; + width: 18px; + subcontrol-position: left; + subcontrol-origin: margin; + +} + + +QScrollBar::right-arrow:horizontal +{ + image: url(://arrow-right.png); + width: 8px; + height: 8px; + +} + + +QScrollBar::left-arrow:horizontal +{ + image: url(://arrow-left.png); + width: 8px; + height: 8px; + +} + + +QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal +{ + background: none; + +} + + +QScrollBar:vertical +{ + background-color: #63676d; + width: 18px; + margin: 18px 0 18px 0; + border: 1px solid #222222; + +} + + +QScrollBar::handle:vertical +{ + background-color: #a6acb3; + border: 1px solid #656565; + border-radius: 2px; + min-height: 20px; + +} + + +QScrollBar::add-line:vertical +{ + border: 1px solid #1b1b19; + background-color: #a6acb3; + height: 18px; + subcontrol-position: bottom; + subcontrol-origin: margin; + +} + + +QScrollBar::sub-line:vertical +{ + border: 1px solid #1b1b19; + background-color: #a6acb3; + height: 18px; + subcontrol-position: top; + subcontrol-origin: margin; + +} + + +QScrollBar::up-arrow:vertical +{ + image: url(://arrow-up.png); + width: 8px; + height: 8px; + +} + + +QScrollBar::down-arrow:vertical +{ + image: url(://arrow-down.png); + width: 8px; + height: 8px; + +} + + +QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical +{ + background: none; + +} + + +/*-----QProgressBar-----*/ +QProgressBar +{ + background-color: #000; + color: #00ff00; + font-weight: bold; + border: 0px groove #000; + border-radius: 10px; + text-align: center; + +} + + +QProgressBar:disabled +{ + background-color: #404040; + color: #656565; + border-color: #051a39; + border: 1px solid #000; + border-radius: 10px; + text-align: center; + +} + + +QProgressBar::chunk { + background-color: #ffaf02; + border: 0px; + border-radius: 10px; + color: #000; + +} + + +QProgressBar::chunk:disabled { + background-color: #333; + border: 0px; + border-radius: 10px; + color: #656565; +} + + +/*-----QStatusBar-----*/ +QStatusBar +{ + background-color: qlineargradient(spread:repeat, x1:1, y1:0, x2:1, y2:1, stop:0 rgba(102, 115, 140, 255),stop:1 rgba(56, 63, 77, 255)); + color: #ffffff; + border-color: #051a39; + font-weight: bold; + +} + + diff --git a/catradio.ico b/catradio.ico new file mode 100644 index 0000000..37954a6 Binary files /dev/null and b/catradio.ico differ diff --git a/catradio.png b/catradio.png new file mode 100644 index 0000000..1b3c75d Binary files /dev/null and b/catradio.png differ diff --git a/dialogconfig.cpp b/dialogconfig.cpp new file mode 100644 index 0000000..2a0fe0f --- /dev/null +++ b/dialogconfig.cpp @@ -0,0 +1,115 @@ +/** + ** This file is part of the CatRadio project. + ** Copyright 2022 Gianfranco Sordetti IZ8EWD . + ** + ** 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, either 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 for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with this program. If not, see . + **/ + + +#include "dialogconfig.h" +#include "ui_dialogconfig.h" + +#include +#include +#include + +#include "rigdata.h" + +#include + + +extern rigConnect rigCom; + + +QString rigListFile = "rig.lst"; //Text file containing the list of rig supported by hamlib +QFile file(rigListFile); + + +DialogConfig::DialogConfig(QWidget *parent) : + QDialog(parent), + ui(new Ui::DialogConfig) +{ + ui->setupUi(this); + + //* rigModel comboBox + if (!file.exists()) //Create file rig.lst if not exists + { + file.open(QIODevice::ReadWrite); + rig_load_all_backends(); //Load all backends information + rig_list_foreach(printRigList, NULL); //Create the rig list + } + else file.open(QIODevice::ReadOnly); //Open file rig.lst and populate the combobox + file.seek(0); + ui->comboBox_rigModel->clear(); + while(!file.atEnd()) + { + QString line = file.readLine(); + ui->comboBox_rigModel->addItem(line.trimmed()); + } + file.close(); + + //* serialSpeed comboBox + ui->comboBox_serialSpeed->clear(); + ui->comboBox_serialSpeed->addItem("4800"); + ui->comboBox_serialSpeed->addItem("9600"); + ui->comboBox_serialSpeed->addItem("19200"); + ui->comboBox_serialSpeed->addItem("38400"); + ui->comboBox_serialSpeed->addItem("57600"); + ui->comboBox_serialSpeed->addItem("115200"); + + //* Update values in the GUI + ui->comboBox_rigModel->setCurrentIndex(ui->comboBox_rigModel->findText(QString::number(rigCom.rigModel),Qt::MatchStartsWith)); + ui->lineEdit_RigPath->setText(rigCom.rigPort); + ui->comboBox_serialSpeed->setCurrentText(QString::number(rigCom.serialSpeed)); + if (rigCom.civAddr) ui->lineEdit_civAddr->setText(QString::number(rigCom.civAddr)); + ui->spinBox_RefreshRate->setValue(rigCom.rigRefresh); + ui->checkBox_fullPoll->setChecked(rigCom.fullPoll); +} + +DialogConfig::~DialogConfig() +{ + delete ui; +} + +void DialogConfig::on_buttonBox_accepted() +{ + //* Read settings from GUI + QString rigModel = ui->comboBox_rigModel->currentText(); + QRegularExpression regexp("[0-9]+"); + QRegularExpressionMatch rigNumber = regexp.match(rigModel); + rigCom.rigModel = rigNumber.captured(0).toInt(); + + rigCom.rigPort = ui->lineEdit_RigPath->text(); + rigCom.serialSpeed = ui->comboBox_serialSpeed->currentText().toInt(); + rigCom.civAddr = ui->lineEdit_civAddr->text().toInt(); + rigCom.rigRefresh = ui->spinBox_RefreshRate->value(); + rigCom.fullPoll = ui->checkBox_fullPoll->isChecked(); + + //* Save settings in config.ini + QSettings configFile(QString("config.ini"), QSettings::IniFormat); + configFile.setValue("rigModel", rigCom.rigModel); + configFile.setValue("rigPort", ui->lineEdit_RigPath->text()); + configFile.setValue("serialSpeed", ui->comboBox_serialSpeed->currentText()); + configFile.setValue("civAddress", ui->lineEdit_civAddr->text()); + configFile.setValue("rigRefresh", ui->spinBox_RefreshRate->value()); + configFile.setValue("fullPolling", ui->checkBox_fullPoll->isChecked()); +} + +int printRigList(const struct rig_caps *rigCaps, void *data) //Load rig list from hamlib and save into file rig.lst +{ + if (data) return 0; + QTextStream stream(&file); + stream << rigCaps->rig_model << " " << rigCaps->mfg_name << " " << rigCaps->model_name << "\n"; + return 1; +} diff --git a/dialogconfig.h b/dialogconfig.h new file mode 100644 index 0000000..3afdf77 --- /dev/null +++ b/dialogconfig.h @@ -0,0 +1,46 @@ +/** + ** This file is part of the CatRadio project. + ** Copyright 2022 Gianfranco Sordetti IZ8EWD . + ** + ** 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, either 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 for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with this program. If not, see . + **/ + + +#ifndef DIALOGCONFIG_H +#define DIALOGCONFIG_H + +#include + +namespace Ui { +class DialogConfig; +} + +class DialogConfig : public QDialog +{ + Q_OBJECT + +public: + explicit DialogConfig(QWidget *parent = nullptr); + ~DialogConfig(); + +private slots: + void on_buttonBox_accepted(); + +private: + Ui::DialogConfig *ui; +}; + +int printRigList(const struct rig_caps *rigCaps, void *data); + +#endif // DIALOGCONFIG_H diff --git a/dialogconfig.ui b/dialogconfig.ui new file mode 100644 index 0000000..0447762 --- /dev/null +++ b/dialogconfig.ui @@ -0,0 +1,164 @@ + + + DialogConfig + + + + 0 + 0 + 400 + 300 + + + + Config + + + + + + Model + + + + + + + + + + Path + + + lineEdit_RigPath + + + + + + + + + + Speed + + + comboBox_serialSpeed + + + + + + + + + + Refresh Rate + + + spinBox_RefreshRate + + + + + + + 50 + + + 1000 + + + 50 + + + 200 + + + + + + + Options + + + + + + CI-V Address + + + + + + + Full polling + + + + + + + CI-V address (decimal, Icom only) + + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + lineEdit_RigPath + comboBox_serialSpeed + spinBox_RefreshRate + + + + + buttonBox + accepted() + DialogConfig + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + DialogConfig + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/dialogsetup.cpp b/dialogsetup.cpp new file mode 100644 index 0000000..ce6d7fb --- /dev/null +++ b/dialogsetup.cpp @@ -0,0 +1,43 @@ +#include "dialogsetup.h" +#include "ui_dialogsetup.h" + +#include "guidata.h" + +#include +#include + + +extern guiConfig guiConf; + + +DialogSetup::DialogSetup(QWidget *parent) : + QDialog(parent), + ui(new Ui::DialogSetup) +{ + ui->setupUi(this); + + if (guiConf.vfoDisplayMode) ui->radioButton_vfoDispMode_UD->setChecked(true); +} + +DialogSetup::~DialogSetup() +{ + delete ui; +} + +void DialogSetup::on_radioButton_vfoDispMode_LR_toggled(bool checked) +{ + if (checked) guiConf.vfoDisplayMode=0; +} + +void DialogSetup::on_radioButton_vfoDispMode_UD_toggled(bool checked) +{ + if (checked) guiConf.vfoDisplayMode=1; +} + +void DialogSetup::on_buttonBox_accepted() +{ + //* Save settings in config.ini + QSettings configFile(QString("config.ini"), QSettings::IniFormat); + configFile.setValue("vfoDisplayMode", guiConf.vfoDisplayMode); +} + diff --git a/dialogsetup.h b/dialogsetup.h new file mode 100644 index 0000000..c39b453 --- /dev/null +++ b/dialogsetup.h @@ -0,0 +1,31 @@ +#ifndef DIALOGSETUP_H +#define DIALOGSETUP_H + +#include + +namespace Ui { +class DialogSetup; +} + +class DialogSetup : public QDialog +{ + Q_OBJECT + +public: + explicit DialogSetup(QWidget *parent = nullptr); + ~DialogSetup(); + +private slots: + + + void on_radioButton_vfoDispMode_LR_toggled(bool checked); + + void on_radioButton_vfoDispMode_UD_toggled(bool checked); + + void on_buttonBox_accepted(); + +private: + Ui::DialogSetup *ui; +}; + +#endif // DIALOGSETUP_H diff --git a/dialogsetup.ui b/dialogsetup.ui new file mode 100644 index 0000000..9a40c03 --- /dev/null +++ b/dialogsetup.ui @@ -0,0 +1,103 @@ + + + DialogSetup + + + + 0 + 0 + 400 + 300 + + + + Setup + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + VFO Display Mode + + + + + + Left/Right buttons + + + true + + + + + + + Up/Down click + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + buttonBox + accepted() + DialogSetup + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + DialogSetup + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/guidata.cpp b/guidata.cpp new file mode 100644 index 0000000..d700faa --- /dev/null +++ b/guidata.cpp @@ -0,0 +1,22 @@ +/** + ** This file is part of the CatRadio project. + ** Copyright 2022 Gianfranco Sordetti IZ8EWD . + ** + ** 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, either 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 for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with this program. If not, see . + **/ + + +#include "guidata.h" + +guiConfig guiConf; diff --git a/guidata.h b/guidata.h new file mode 100644 index 0000000..2fdd987 --- /dev/null +++ b/guidata.h @@ -0,0 +1,10 @@ +#ifndef GUIDATA_H +#define GUIDATA_H + +#endif // GUIDATA_H + + +typedef struct { + int vfoDisplayMode; //0: use Left/Right mouse button, 1: click digit up or down + +} guiConfig; diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..f8a5cf6 --- /dev/null +++ b/main.cpp @@ -0,0 +1,43 @@ +/** + ** This file is part of the CatRadio project. + ** Copyright 2022 Gianfranco Sordetti IZ8EWD . + ** + ** 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, either 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 for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with this program. If not, see . + **/ + +#include "mainwindow.h" + +#include +#include +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow w; + +/* + QFile file("./CatRadio.qss"); //open qss file + //if(!file.open(QFile::ReadOnly)) + file.open(QFile::ReadOnly); + + QString styleSheet (file.readAll()); + file.close(); + + a.setStyleSheet(styleSheet); //setup stylesheet +*/ + + w.show(); + return a.exec(); +} diff --git a/mainwindow.cpp b/mainwindow.cpp new file mode 100644 index 0000000..36d1921 --- /dev/null +++ b/mainwindow.cpp @@ -0,0 +1,839 @@ +/** + ** This file is part of the CatRadio project. + ** Copyright 2022 Gianfranco Sordetti IZ8EWD . + ** + ** 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, either 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 for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with this program. If not, see . + **/ + + +#include "mainwindow.h" +#include "ui_mainwindow.h" +#include "dialogconfig.h" +#include "dialogsetup.h" +#include "rigdaemon.h" +#include "rigdata.h" +#include "guidata.h" +#include "rigcommand.h" + +#include +#include +#include +#include +#include + +#include //Hamlib + +extern RIG *my_rig; //Defined in rigdaemon.cpp + +extern rigConnect rigCom; +extern rigSettings rigGet; +extern rigSettings rigSet; +extern rigCommand rigCmd; +extern rigCommand rigCap; +extern guiConfig guiConf; + +int retcode; //Return code from function +int i; //Index +int prevDial; //Previous dial value +int fastDial; //Fast pushbutton state + +FILE* debugFile; + + +QThread workerThread; // +RigDaemon *rigDaemon = new RigDaemon; + + +//***** MainWindow ***** + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::MainWindow) +{ + ui->setupUi(this); + + timer = new QTimer(this); //timer for rigDaemon thread call + + //* Debug + rig_set_debug_level(RIG_DEBUG_WARN); + rig_set_debug_time_stamp(true); + if ((debugFile=fopen("debug.log","w+")) == NULL) rig_set_debug_level(RIG_DEBUG_NONE); + else rig_set_debug_file(debugFile); + + //* Signal and Slot connection for Slider and associated Label + connect(ui->horizontalSlider_RFpower, &QAbstractSlider::valueChanged, ui->label_RFpowerValue, qOverload(&QLabel::setNum)); + connect(ui->horizontalSlider_RFgain, &QAbstractSlider::valueChanged, ui->label_RFgainValue, qOverload(&QLabel::setNum)); + connect(ui->horizontalSlider_IFshift, &QAbstractSlider::valueChanged, ui->label_IFshiftValue, qOverload(&QLabel::setNum)); + + //* Signal and Slot connection for vfoDisplay + connect(ui->lineEdit_vfoMain, &vfoDisplay::on_valueChanged, this, &MainWindow::on_vfoDisplayValueChanged); + + //* Thread for RigDaemon + rigDaemon->moveToThread(&workerThread); // + connect(&workerThread, &QThread::finished, rigDaemon, &QObject::deleteLater); + connect(timer, &QTimer::timeout, rigDaemon, &RigDaemon::rigUpdate); + connect(rigDaemon, &RigDaemon::resultReady, this, &MainWindow::on_rigDaemonResultReady); + workerThread.start(); + + //* Load settings from config.ini + QSettings configFile(QString("config.ini"), QSettings::IniFormat); + rigCom.rigModel = configFile.value("rigModel", 0).toInt(); + rigCom.rigPort = configFile.value("rigPort").toString(); + rigCom.serialSpeed = configFile.value("serialSpeed", 9600).toInt(); + rigCom.civAddr = configFile.value("civAddress", 0).toInt(); + rigCom.rigRefresh = configFile.value("rigRefresh", 100).toInt(); + rigCom.fullPoll = configFile.value("fullPolling", false).toBool(); + guiConf.vfoDisplayMode = configFile.value("vfoDisplayMode", 0).toInt(); +} + +MainWindow::~MainWindow() +{ + workerThread.quit(); // + workerThread.wait(); + + if (rigCom.connected) + { + timer->stop(); + + rigCom.connected = 0; + rig_close(my_rig); //Close the communication to the rig + } + + rig_cleanup(my_rig); //Release rig handle and free associated memory + + fclose(debugFile); //Close debug.log + + delete ui; +} + + +//***** GUI function ***** + +void MainWindow::guiInit() +{ + ui->statusbar->showMessage(my_rig->caps->model_name); + + if (rig_has_set_func(my_rig, RIG_FUNCTION_SET_POWERSTAT)==0) //Power pushbutton + { + ui->pushButton_Power->setDisabled(true); + rigCap.onoff = 0; + } + else + { + ui->pushButton_Power->setDisabled(false); + rigCap.onoff = 1; + } + + if (rig_has_set_func(my_rig, RIG_FUNCTION_SET_PTT)==0) //PTT pushbutton + { + ui->pushButton_PTT->setDisabled(true); + rigCap.ptt = 0; + } + else + { + ui->pushButton_PTT->setDisabled(false); + rigCap.ptt = 1; + } + + //* Mode combobox + if (my_rig->state.mode_list==RIG_MODE_NONE) + { + ui->comboBox_Mode->setDisabled(true); + ui->comboBox_ModeSub->setDisabled(true); + } + else + { + ui->comboBox_Mode->clear(); //Clear old contents + ui->comboBox_ModeSub->clear(); + for (i=0; istate.mode_list & (1ULL << i)) + { + ui->comboBox_Mode->addItem(rig_strrmode(my_rig->state.mode_list & (1ULL << i))); + ui->comboBox_ModeSub->addItem(rig_strrmode(my_rig->state.mode_list & (1ULL << i))); + } + } + rigCmd.bwidthList = 1; //Command to populate BW combobox in guiUpdate() + } + + //* AGC level comboBox + ui->comboBox_AGC->clear(); + /* It seems that has_set_level or has_get_level is not well implemented in Hamlib, at the moment it is skipped in favour of fix values entry + agc_level_e agcLevel; + for (i = 0; i < 7; i++) + { + agcLevel = levelagcvalue(i); + if (rig_has_set_level(my_rig, agcLevel)) + { + ui->comboBox_AGC->addItem(rig_stragclevel(agcLevel)); + } + }*/ + ui->comboBox_AGC->addItem(rig_stragclevel(RIG_AGC_OFF)); + ui->comboBox_AGC->addItem(rig_stragclevel(RIG_AGC_AUTO)); + ui->comboBox_AGC->addItem(rig_stragclevel(RIG_AGC_FAST)); + ui->comboBox_AGC->addItem(rig_stragclevel(RIG_AGC_MEDIUM)); + ui->comboBox_AGC->addItem(rig_stragclevel(RIG_AGC_SLOW)); + + //* Meter comboBox + ui->comboBox_Meter->clear(); + if (rig_has_get_level(my_rig, RIG_METER_SWR)) ui->comboBox_Meter->addItem("SWR"); + if (rig_has_get_level(my_rig, RIG_METER_ALC)) ui->comboBox_Meter->addItem("ALC"); + rigSet.meter = levelmeterstr (ui->comboBox_Meter->currentText()); + setSubMeter(); + + //* Attenuator comboBox + ui->comboBox_Att->clear(); + ui->comboBox_Att->addItem("0"); + for (i = 0; i < HAMLIB_MAXDBLSTSIZ && my_rig->state.attenuator[i] != 0; i++) + { + ui->comboBox_Att->addItem(QString::number(my_rig->state.attenuator[i])); + } + + //* Preamp comboBox + ui->comboBox_Preamp->clear(); + ui->comboBox_Preamp->addItem("0"); + for (i = 0; i < HAMLIB_MAXDBLSTSIZ && my_rig->state.preamp[i] != 0; i++) + { + ui->comboBox_Preamp->addItem(QString::number(my_rig->state.preamp[i])); + } + + rigCmd.rangeList = 1; + rigCmd.antList = 1; +} + +void MainWindow::guiUpdate() +{ + //* Power button + if (rigGet.onoff == RIG_POWER_ON) ui->pushButton_Power->setChecked(true); + + //* VFOs + ui->lineEdit_vfoMain->setValue(rigGet.freqMain); + ui->lineEdit_vfoSub->setText(QString::number(rigGet.freqSub/1000,'f',2)); + + ui->label_vfoMain->setText(rig_strvfo(rigGet.vfoMain)); + switch (rigGet.vfoMain) + { + case RIG_VFO_A: rigGet.vfoSub = RIG_VFO_B; break; + case RIG_VFO_B: rigGet.vfoSub = RIG_VFO_A; break; + case RIG_VFO_MAIN: rigGet.vfoSub = RIG_VFO_SUB; break; + case RIG_VFO_SUB: rigGet.vfoSub = RIG_VFO_MAIN; break; + } + ui->label_vfoSub->setText(rig_strvfo(rigGet.vfoSub)); + + //* Mode + ui->comboBox_Mode->setCurrentText(rig_strrmode(rigGet.mode)); + ui->comboBox_ModeSub->setCurrentText(rig_strrmode(rigGet.modeSub)); + + //* BW combobox + if (rigCmd.bwidthList) + { + ui->comboBox_BW->clear(); + filter_list bwidth_list; //IF filter bandwidth per mode + for (i=0; istate.filters[i]); i++) + { + char modeslist[1000] = ""; + QString modes, mode; + bwidth_list = my_rig->state.filters[i]; + rig_strrmodes(bwidth_list.modes, modeslist, sizeof(modeslist)); + modes = modeslist; + modes.append(" "); + //qDebug() << modes << bwidth_list.width; + mode = rig_strrmode(rigGet.mode); + QRegularExpression rx("\\b"+mode+"?\\s"); + if (modes.contains (rx) && bwidth_list.width != RIG_FLT_ANY) ui->comboBox_BW->addItem(QString::number(bwidth_list.width)); + } + ui->comboBox_BW->model()->sort(0, Qt::DescendingOrder); + rigCmd.bwidthList = 0; + } + + ui->comboBox_BW->setCurrentText(QString::number(rigGet.bwidth)); + ui->checkBox_NAR->setChecked(rigGet.bwNarrow); + + //* Range list + if (rigCmd.rangeList) + { + for (i=0; i= my_rig->state.tx_range_list[i].startf && rigGet.freqMain <= my_rig->state.tx_range_list[i].endf) break; + } + rigGet.rangeListTxIndex = i; + + for (i=0; i= my_rig->state.rx_range_list[i].startf && rigGet.freqMain <= my_rig->state.rx_range_list[i].endf) break; + } + if (rigGet.rangeListRxIndex != i) rigCmd.antList = 1; + rigGet.rangeListRxIndex = i; + + rigCmd.rangeList = 0; + } + + //* Antenna comboBox + if (rigCmd.antList) + { + ui->comboBox_Ant->clear(); + if (my_rig->state.tx_range_list[rigGet.rangeListRxIndex].ant == RIG_ANT_NONE) ui->comboBox_Ant->addItem("NONE"); //RIG_ANT_NONE + else for (i=0; i < RIG_ANT_MAX; i++) + { + if (my_rig->state.tx_range_list[rigGet.rangeListRxIndex].ant & (1UL << i)) + { + switch (i) + { + case 0: ui->comboBox_Ant->addItem("ANT1"); break; //RIG_ANT_1 + case 1: ui->comboBox_Ant->addItem("ANT2"); break; //RIG_ANT_2 + case 2: ui->comboBox_Ant->addItem("ANT3"); break; //RIG_ANT_3 + case 3: ui->comboBox_Ant->addItem("ANT4"); break; //RIG_ANT_4 + case 4: ui->comboBox_Ant->addItem("ANT5"); break; //RIG_ANT_5 + case 30: ui->comboBox_Ant->addItem("UNK"); break; //RIG_ANT_UNKNOWN + case 31: ui->comboBox_Ant->addItem("CURR"); break; //RIG_ANT_CURR + default: ui->comboBox_Ant->addItem("UNK"); break; + } + } + } + rigCmd.antList = 0; + } + + //* Split + if (rigGet.split == RIG_SPLIT_ON) + { + ui->pushButton_Split->setChecked(true); + if (rigGet.vfoSub == rigGet.vfoTx) + { + ui->label_vfoMainRxTx->setText("RX"); + ui->label_vfoSubRxTx->setText("TX"); + } + else + { + ui->label_vfoMainRxTx->setText("TX"); + ui->label_vfoSubRxTx->setText("RX"); + } + } + else + { + ui->pushButton_Split->setChecked(false); + ui->label_vfoMainRxTx->setText("RX TX"); + ui->label_vfoSubRxTx->setText(""); + } + + //* PTT & Meter + if (rigGet.ptt == RIG_PTT_ON) + { + ui->pushButton_PTT->setChecked(true); + + ui->progressBar_Smeter->setTx(true); + ui->progressBar_Smeter->setValue(rigGet.powerMeter.f*100); + ui->progressBar_subMeter->setValue(rigGet.subMeter.f); + } + else + { + ui->pushButton_PTT->setChecked(false); + + ui->progressBar_Smeter->setTx(false); + ui->progressBar_Smeter->setValue(rigGet.sMeter.i); + if (rigSet.meter == RIG_LEVEL_SWR) ui->progressBar_subMeter->setValue(1.0); + else ui->progressBar_subMeter->setValue(0.0); + } + + //* + if (!ui->horizontalSlider_RFpower->isSliderDown()) ui->horizontalSlider_RFpower->setValue((int)(rigGet.rfPower*100)); + + //* + ui->radioButton_Tuner->setChecked(rigGet.tuner); + + ui->checkBox_BKIN->setChecked(rigGet.bkin); + + ui->comboBox_AGC->setCurrentText(rig_stragclevel(rigGet.agc)); + + ui->comboBox_Att->setCurrentText(QString::number(rigGet.att)); + + ui->comboBox_Preamp->setCurrentText(QString::number(rigGet.pre)); +} + + +//* RigDaemon handle results +void MainWindow::on_rigDaemonResultReady() +{ + guiUpdate(); +} + +//* SubMeter +void MainWindow::setSubMeter() +{ + if (rigSet.meter == RIG_LEVEL_SWR) + { + ui->progressBar_subMeter->setMaxValue(5.0); + ui->progressBar_subMeter->setMinValue(1.0); + ui->progressBar_subMeter->setGateValue(2.0); + ui->progressBar_subMeter->setPrecision(1); + ui->progressBar_subMeter->setLongStep(0.5); + ui->progressBar_subMeter->setShortStep(0.1); + ui->progressBar_subMeter->setValue(1); + } + else + { + ui->progressBar_subMeter->setMaxValue(1.0); + ui->progressBar_subMeter->setMinValue(0.0); + ui->progressBar_subMeter->setGateValue(0.5); + ui->progressBar_subMeter->setPrecision(1); + ui->progressBar_subMeter->setLongStep(0.5); + ui->progressBar_subMeter->setShortStep(0.1); + ui->progressBar_subMeter->setValue(0); + } +} + + +//***** PushButton ***** + +void MainWindow::on_pushButton_Connect_toggled(bool checked) +{ + if (checked && rigCom.connected == 0) + { + retcode = rigDaemon->rigConnect(); //Open Rig connection + + if (retcode != RIG_OK) //Connection error + { + rigCom.connected = 0; + ui->statusbar->showMessage(rigerror(retcode)); + ui->pushButton_Connect->setChecked(false); //Uncheck the button + } + else //Rig connected + { + rigCom.connected = 1; + guiInit(); + if (rigCap.onoff == 0 || rigGet.onoff == RIG_POWER_ON) timer->start(rigCom.rigRefresh); + } + } + else if (rigCom.connected) //Button unchecked + { + rigCom.connected = 0; + timer->stop(); + rig_close(my_rig); //Close the communication to the rig + //rig_cleanup(my_rig); //Release rig handle and free associated memory + } +} + +void MainWindow::on_pushButton_Power_toggled(bool checked) +{ + if (checked && !rigGet.onoff) + { + retcode = rig_set_powerstat(my_rig, RIG_POWER_ON); + if (retcode != RIG_OK) + { + ui->pushButton_Power->setChecked(false); //Uncheck the button + ui->statusbar->showMessage(rigerror(retcode)); + } + else timer->start(rigCom.rigRefresh); + } + else if (!checked && rigGet.onoff) + { + retcode = rig_set_powerstat(my_rig, RIG_POWER_OFF); + if (retcode != RIG_OK) + { + ui->pushButton_Power->setChecked(false); //Uncheck the button + timer->stop(); + } + } +} + +void MainWindow::on_pushButton_PTT_toggled(bool checked) +{ + if (checked && !rigGet.ptt) + { + rigSet.ptt = RIG_PTT_ON; + rigCmd.ptt = 1; + } + else if (!checked && rigGet.ptt) + { + rigSet.ptt = RIG_PTT_OFF; + rigCmd.ptt = 1; + } +} + +void MainWindow::on_pushButton_Split_toggled(bool checked) +{ + if (checked && !rigGet.split) + { + rigSet.split = RIG_SPLIT_ON; + rigCmd.split = 1; + } + else if (!checked && rigGet.split) + { + rigSet.split = RIG_SPLIT_OFF; + rigCmd.split = 1; + } +} + +void MainWindow::on_pushButton_QSplit_clicked() +{ + quick_split(); +} + +void MainWindow::on_pushButton_AB_clicked() +{ + rigCmd.vfoXchange = 1; +} + +void MainWindow::on_pushButton_AeqB_clicked() +{ + rigCmd.vfoCopy = 1; +} + +void MainWindow::on_pushButton_Fast_toggled(bool checked) +{ + if (checked) fastDial = 1; + else fastDial = 0; +} + +void MainWindow::on_pushButton_Tune_clicked() +{ + rigCmd.tune = 1; +} + +void MainWindow::on_pushButton_Band160_clicked() +{ + set_band(160); +} + +void MainWindow::on_pushButton_Band80_clicked() +{ + set_band(80); +} + +void MainWindow::on_pushButton_Band60_clicked() +{ + set_band(60); +} + +void MainWindow::on_pushButton_Band40_clicked() +{ + set_band(40); +} + +void MainWindow::on_pushButton_Band30_clicked() +{ + set_band(30); +} + +void MainWindow::on_pushButton_Band20_clicked() +{ + set_band(20); +} + +void MainWindow::on_pushButton_Band17_clicked() +{ + set_band(17); +} + +void MainWindow::on_pushButton_Band15_clicked() +{ + set_band(15); +} + +void MainWindow::on_pushButton_Band12_clicked() +{ + set_band(12); +} + +void MainWindow::on_pushButton_Band10_clicked() +{ + set_band(10); +} + +void MainWindow::on_pushButton_Band6_clicked() +{ + set_band(6); +} + +void MainWindow::on_pushButton_Band2_clicked() +{ + set_band(2); +} + +void MainWindow::on_pushButton_Band70_clicked() +{ + set_band(70); +} + +void MainWindow::on_pushButton_BandGen_clicked() +{ + set_band(1); +} + +void MainWindow::on_pushButton_BandDown_clicked() +{ + rigCmd.bandDown = 1; +} + +void MainWindow::on_pushButton_BandUp_clicked() +{ + rigCmd.bandUp = 1; +} + +//***** CheckBox ***** + +void MainWindow::on_checkBox_NAR_toggled(bool checked) +{ + if (checked && !rigGet.bwNarrow) + { + rigSet.bwidth = rig_passband_narrow(my_rig, rigGet.mode); + rigCmd.bwidth = 1; + } + else if (!checked && rigGet.bwNarrow) + { + rigSet.bwidth = RIG_PASSBAND_NORMAL; + rigCmd.bwidth = 1; + } +} + +void MainWindow::on_checkBox_BKIN_toggled(bool checked) +{ + if (checked && !rigGet.bkin) + { + rigSet.bkin = 1; + rigCmd.bkin = 1; + } + else if (!checked && rigGet.bkin) + { + rigSet.bkin = 0; + rigCmd.bkin = 1; + } +} + +void MainWindow::on_checkBox_NB_toggled(bool checked) +{ + if (checked && !rigGet.noiseBlanker) + { + rigSet.noiseBlanker = 1; + rigCmd.noiseBlanker = 1; + } + else if (!checked && rigGet.noiseBlanker) + { + rigSet.noiseBlanker = 0; + rigCmd.noiseBlanker = 1; + } +} + +void MainWindow::on_checkBox_NR_toggled(bool checked) +{ + if (checked && !rigGet.noiseReduction) + { + rigSet.noiseReduction = 1; + rigCmd.noiseReduction = 1; + } + else if (!checked && rigGet.noiseReduction) + { + rigSet.noiseReduction = 0; + rigCmd.noiseReduction = 1; + } +} + +void MainWindow::on_checkBox_NF_toggled(bool checked) +{ + if (checked && !rigGet.notchFilter) + { + rigSet.notchFilter = 1; + rigCmd.notchFilter = 1; + } + else if (!checked && rigGet.notchFilter) + { + rigSet.notchFilter = 0; + rigCmd.notchFilter = 1; + } +} + + +//***** RadioButton ***** + +void MainWindow::on_radioButton_Tuner_toggled(bool checked) +{ + if (checked && !rigGet.tuner) + { + rigSet.tuner = 1; + rigCmd.tuner = 1; + } + else if (!checked && rigGet.tuner) + { + rigSet.tuner = 0; + rigCmd.tuner = 1; + } +} + + +//***** Dial ***** + +void MainWindow::on_dial_valueChanged(int value) +{ + int step; + + step = value - prevDial; + if (step<=99 && step>50) step = value - 100 - prevDial; + if (step>=-99 && step<-50) step = value + 100 - prevDial; + prevDial = value; + + if (ui->radioButton_VFOSub->isChecked()) //dial VFO Sub + { + rigSet.freqSub = rigGet.freqSub + step*(!fastDial*10+fastDial*100); + rigCmd.freqSub = 1; + } + else //dial VFO Main + { + rigSet.freqMain = rigGet.freqMain + step*(!fastDial*10+fastDial*100); + rigCmd.freqMain = 1; + } +} + +void MainWindow::on_vfoDisplayValueChanged(int value) +{ + rigSet.freqMain = value; + rigCmd.freqMain = 1; +} + +//***** ComboBox ***** + +void MainWindow::on_comboBox_Mode_activated(int index) +{ + rigSet.mode = rig_parse_mode(ui->comboBox_Mode->itemText(index).toLatin1()); + rigCmd.mode = 1; +} + +void MainWindow::on_comboBox_BW_activated(int index) +{ + rigSet.bwidth = ui->comboBox_BW->itemText(index).toInt(); + rigCmd.bwidth = 1; +} + +void MainWindow::on_comboBox_AGC_activated(int index) +{ + rigSet.agc = levelagcstr(ui->comboBox_AGC->itemText(index)); + rigCmd.agc = 1; +} + +void MainWindow::on_comboBox_Att_activated(int index) +{ + rigSet.att = ui->comboBox_Att->itemText(index).toInt(); + rigCmd.att = 1; +} + +void MainWindow::on_comboBox_Preamp_activated(int index) +{ + rigSet.pre = ui->comboBox_Preamp->itemText(index).toInt(); + rigCmd.pre = 1; +} + +void MainWindow::on_comboBox_Ant_activated(int index) +{ + rigSet.ant = antstr(ui->comboBox_Ant->itemText(index)); + rigCmd.ant = 1; +} + +void MainWindow::on_comboBox_Meter_activated(int index) +{ + rigSet.meter = levelmeterstr (ui->comboBox_Meter->itemText(index)); + setSubMeter(); +} + + +//***** Spin Box ***** + +void MainWindow::on_spinBox_NR_valueChanged(int arg1) +{ + rigSet.noiseReductionLevel = arg1; + rigCmd.noiseReductionLevel = 1; +} + + +//***** Slider ***** + +void MainWindow::on_horizontalSlider_RFpower_valueChanged(int value) +{ + if (!rigCmd.rfPower) + { + if (value < 5) value = 5; + rigSet.rfPower = (float)(value)/100; + if (rigSet.rfPower != rigGet.rfPower) rigCmd.rfPower = 1; + } +} + +void MainWindow::on_horizontalSlider_RFgain_valueChanged(int value) +{ + if (!rigCmd.rfGain) + { + rigSet.rfGain = (float)(value)/100; + if (rigSet.rfGain != rigGet.rfGain) rigCmd.rfGain = 1; + } +} + +void MainWindow::on_horizontalSlider_IFshift_valueChanged(int value) +{ + if (!rigCmd.ifShift) + { + rigSet.ifShift = value; + if (rigSet.ifShift != rigGet.ifShift) rigCmd.ifShift = 1; + } +} + + +//***** Menu ***** + +void MainWindow::on_action_Connection_triggered() +{ + DialogConfig config; + config.setModal(true); + config.exec(); +} + +void MainWindow::on_action_Setup_triggered() +{ + DialogSetup setup; + setup.setModal(true); + setup.exec(); +} + +void MainWindow::on_action_AboutCatRadio_triggered() +{ + QMessageBox msgBox; + msgBox.setWindowTitle("About"); + msgBox.setTextFormat(Qt::RichText); + QString version = QString::number(VERSION_MAJ)+"."+QString::number(VERSION_MIN)+"."+QString::number(VERSION_MIC); + msgBox.setText("CatRadio Radio control software
version "+version+" "+RELEASE_DATE); + msgBox.setInformativeText("Copyright (C) 2022 Gianfranco Sordetti IZ8EWD
" + "www.pianetaradio.it

" + "

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, either 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 for more details.
" + "You should have received a copy of the GNU General Public License along with this program. If not, see www.gnu.org/licenses."); + msgBox.setIcon(QMessageBox::NoIcon); + msgBox.setStandardButtons(QMessageBox::Ok); + + QPixmap icon("catradio.png"); + msgBox.setIconPixmap(icon); + + msgBox.exec(); +} + +void MainWindow::on_action_AboutQT_triggered() +{ + QMessageBox::aboutQt(this); +} + +void MainWindow::on_action_AboutHamLib_triggered() +{ + QMessageBox msgBox; + msgBox.setWindowTitle("About Hamlib"); + msgBox.setText(rig_version()); + msgBox.setInformativeText(rig_copyright()); + //msgBox.setDetailedText(rig_license()); + msgBox.setIcon(QMessageBox::Information); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.exec(); +} diff --git a/mainwindow.h b/mainwindow.h new file mode 100644 index 0000000..a095a46 --- /dev/null +++ b/mainwindow.h @@ -0,0 +1,153 @@ +/** + ** This file is part of the CatRadio project. + ** Copyright 2022 Gianfranco Sordetti IZ8EWD . + ** + ** 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, either 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 for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with this program. If not, see . + **/ + + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include + +#define RELEASE_DATE __DATE__ +#define VERSION_MAJ 1 +#define VERSION_MIN 0 +#define VERSION_MIC 0 + + +QT_BEGIN_NAMESPACE +namespace Ui { class MainWindow; } +QT_END_NAMESPACE + + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow(QWidget *parent = nullptr); + ~MainWindow(); + +public slots: + void guiUpdate(); + void on_rigDaemonResultReady(); //Slot for rigDaemon resultReady + void on_vfoDisplayValueChanged(int value); //Slot for vfoDisplay valueChanged + +signals: + +private slots: + void on_pushButton_Connect_toggled(bool checked); + void on_pushButton_Power_toggled(bool checked); + void on_pushButton_PTT_toggled(bool checked); + void on_pushButton_Split_toggled(bool checked); + void on_pushButton_AB_clicked(); + void on_pushButton_AeqB_clicked(); + + void on_dial_valueChanged(int value); + + void on_action_AboutQT_triggered(); + void on_action_AboutHamLib_triggered(); + + + + void on_comboBox_Mode_activated(int index); + + void on_pushButton_Fast_toggled(bool checked); + + void on_horizontalSlider_RFpower_valueChanged(int value); + + void on_pushButton_Band160_clicked(); + + void on_pushButton_Band80_clicked(); + + void on_pushButton_Band60_clicked(); + + void on_pushButton_Band40_clicked(); + + void on_pushButton_Band30_clicked(); + + void on_pushButton_Band20_clicked(); + + void on_pushButton_Band17_clicked(); + + void on_pushButton_Band15_clicked(); + + void on_pushButton_Band12_clicked(); + + void on_pushButton_Band10_clicked(); + + void on_pushButton_Band6_clicked(); + + void on_pushButton_Tune_clicked(); + + void on_radioButton_Tuner_toggled(bool checked); + + void on_pushButton_BandDown_clicked(); + + void on_pushButton_BandUp_clicked(); + + void on_pushButton_QSplit_clicked(); + + void on_action_Connection_triggered(); + + void on_comboBox_BW_activated(int index); + + void on_checkBox_NAR_toggled(bool checked); + + void on_checkBox_BKIN_toggled(bool checked); + + void on_comboBox_AGC_activated(int index); + + void on_comboBox_Att_activated(int index); + + void on_comboBox_Preamp_activated(int index); + + void on_comboBox_Ant_activated(int index); + + void on_action_AboutCatRadio_triggered(); + + void on_checkBox_NB_toggled(bool checked); + + void on_checkBox_NR_toggled(bool checked); + + void on_checkBox_NF_toggled(bool checked); + + void on_comboBox_Meter_activated(int index); + + void on_horizontalSlider_RFgain_valueChanged(int value); + + void on_spinBox_NR_valueChanged(int arg1); + + void on_horizontalSlider_IFshift_valueChanged(int value); + + void on_pushButton_Band2_clicked(); + + void on_pushButton_Band70_clicked(); + + void on_pushButton_BandGen_clicked(); + + void on_action_Setup_triggered(); + +private: + Ui::MainWindow *ui; + QTimer *timer; + + void guiInit(); + void setSubMeter(); +}; + +#endif // MAINWINDOW_H diff --git a/mainwindow.ui b/mainwindow.ui new file mode 100644 index 0000000..eb08f7b --- /dev/null +++ b/mainwindow.ui @@ -0,0 +1,1353 @@ + + + MainWindow + + + true + + + + 0 + 0 + 600 + 560 + + + + CatRadio + + + + catradio.icocatradio.ico + + + + + + 10 + 10 + 91 + 401 + + + + + + + Connect + + + true + + + + + + + Power + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Tuner + + + + + + + Tune + + + + + + + Antenna + + + comboBox_Ant + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + AGC + + + comboBox_AGC + + + + + + + + + + Attenuator + + + comboBox_Att + + + + + + + + + + Preamp + + + comboBox_Preamp + + + + + + + + + + + true + + + + 110 + 80 + 481 + 131 + + + + QFrame::Box + + + QFrame::Raised + + + 0 + + + + + 200 + 10 + 40 + 16 + + + + VFO + + + + + + 400 + 10 + 40 + 16 + + + + VFO + + + + + true + + + + 10 + 60 + 81 + 24 + + + + + + + 100 + 60 + 81 + 24 + + + + + + + 10 + 100 + 80 + 20 + + + + A / B + + + + + + 100 + 100 + 80 + 20 + + + + A = B + + + + + + 190 + 100 + 80 + 20 + + + + Split + + + true + + + + + + 280 + 100 + 80 + 20 + + + + Q Split + + + + + + 200 + 30 + 41 + 16 + + + + RX TX + + + + + + 400 + 30 + 41 + 16 + + + + RX TX + + + + + true + + + + 250 + 10 + 140 + 40 + + + + + 0 + 0 + + + + + 18 + + + + Qt::RightToLeft + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + true + + + + + true + + + + 250 + 60 + 81 + 24 + + + + false + + + + + + 10 + 9 + 181 + 41 + + + + + + + + 110 + 220 + 151 + 191 + + + + Band + + + + + + + 0 + 0 + + + + + 20 + 20 + + + + + 16 + 16 + + + + 1.8 + + + + + + + + 0 + 0 + + + + + 20 + 20 + + + + + 16 + 16 + + + + 3.5 + + + + + + + + 0 + 0 + + + + + 20 + 20 + + + + + 16 + 16 + + + + 5.3 + + + + + + + + 0 + 0 + + + + + 20 + 20 + + + + + 16 + 16 + + + + 7 + + + + + + + + 0 + 0 + + + + + 20 + 20 + + + + + 16 + 16 + + + + 10 + + + + + + + + 0 + 0 + + + + + 20 + 20 + + + + + 16 + 16 + + + + 14 + + + + + + + + 0 + 0 + + + + + 20 + 20 + + + + + 16 + 16 + + + + 18 + + + + + + + + 0 + 0 + + + + + 20 + 20 + + + + + 16 + 16 + + + + 21 + + + + + + + + 0 + 0 + + + + + 20 + 20 + + + + + 16 + 16 + + + + 24.5 + + + + + + + + 0 + 0 + + + + + 20 + 20 + + + + + 16 + 16 + + + + 28 + + + + + + + + 0 + 0 + + + + + 20 + 20 + + + + + 16 + 16 + + + + Gen + + + + + + + + 0 + 0 + + + + + 20 + 20 + + + + + 16 + 16 + + + + 50 + + + + + + + + 0 + 0 + + + + + 20 + 20 + + + + + 16 + 16 + + + + << + + + + + + + + 0 + 0 + + + + + 20 + 20 + + + + + 16 + 16 + + + + 144 + + + + + + + + 0 + 0 + + + + + 20 + 20 + + + + + 16 + 16 + + + + 430 + + + + + + + + 0 + 0 + + + + + 20 + 20 + + + + + 16 + 16 + + + + >> + + + + + + + + + 470 + 230 + 121 + 181 + + + + Filter + + + + + 10 + 30 + 51 + 22 + + + + Noise Blanking + + + NB + + + + + + 10 + 60 + 51 + 22 + + + + Noise Reduction + + + NR + + + + + + 10 + 90 + 51 + 22 + + + + Notch Filter + + + NF + + + + + + 70 + 60 + 46 + 25 + + + + 1 + + + 15 + + + + + + 10 + 120 + 51 + 22 + + + + BW Narrow + + + NAR + + + + + + 10 + 160 + 101 + 18 + + + + -1200 + + + 1200 + + + 10 + + + 100 + + + false + + + Qt::Horizontal + + + + + + 10 + 150 + 55 + 16 + + + + IF-Shift + + + horizontalSlider_IFshift + + + + + true + + + + 40 + 140 + 41 + 16 + + + + 0 + + + Qt::AlignCenter + + + + + + + 470 + 420 + 120 + 91 + + + + CW + + + + + 10 + 30 + 71 + 22 + + + + Break-In + + + BK IN + + + + + + 10 + 60 + 71 + 22 + + + + APF + + + + + + + 270 + 220 + 191 + 191 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + 10 + 150 + 171 + 31 + + + + PTT + + + \ + + + true + + + + + + 20 + 0 + 150 + 150 + + + + 100 + + + false + + + true + + + 10.000000000000000 + + + false + + + + + + 10 + 110 + 31 + 25 + + + + Fast + + + true + + + + + + 10 + 0 + 51 + 22 + + + + Main + + + true + + + + + + 130 + 0 + 51 + 22 + + + + Qt::RightToLeft + + + Sub + + + + + + + 110 + 9 + 481 + 61 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + 0 + 0 + 191 + 61 + + + + + + + 250 + 0 + 151 + 61 + + + + + + + 400 + 20 + 75 + 24 + + + + + + + + 10 + 420 + 451 + 91 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + 10 + 10 + 55 + 16 + + + + RF Gain + + + horizontalSlider_RFgain + + + + + + 10 + 50 + 55 + 16 + + + + RF Power + + + horizontalSlider_RFpower + + + + + + 60 + 10 + 200 + 20 + + + + 0 + + + 100 + + + 100 + + + true + + + Qt::Horizontal + + + QSlider::TicksBothSides + + + 10 + + + + + + 60 + 50 + 200 + 20 + + + + 0 + + + 100 + + + 100 + + + true + + + Qt::Horizontal + + + QSlider::TicksBothSides + + + 10 + + + + + true + + + + 270 + 10 + 31 + 16 + + + + 100 + + + + + true + + + + 270 + 50 + 31 + 16 + + + + 100 + + + + frame_2 + frame + verticalLayoutWidget + groupBox_Band + groupBox_filter + groupBox_CW + frame_3 + frame_4 + + + + + 0 + 0 + 600 + 25 + + + + + Config + + + + + + + Help + + + + + + + + + + + + Connection + + + + + About CatRadio + + + + + About HamLib + + + + + About QT + + + + + Setup + + + + + + SMeter + QWidget +

smeter.h
+ 1 + + + SubMeter + QWidget +
submeter.h
+ 1 +
+ + vfoDisplay + QWidget +
vfodisplay.h
+ 1 +
+ + + + diff --git a/rigcommand.cpp b/rigcommand.cpp new file mode 100644 index 0000000..a56a9c5 --- /dev/null +++ b/rigcommand.cpp @@ -0,0 +1,153 @@ +/** + ** This file is part of the CatRadio project. + ** Copyright 2022 Gianfranco Sordetti IZ8EWD . + ** + ** 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, either 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 for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with this program. If not, see . + **/ + + +#include "rigcommand.h" +#include "rigdata.h" + +#include //Hamlib + +#include + +extern rigSettings rigGet; +extern rigSettings rigSet; +extern rigCommand rigCmd; +extern rigCommand rigCap; + +void set_band (int band) +{ + freq_t freq; + + switch (band) + { + case 160: freq = 1840000; break; + case 80: freq = 3600000; break; + case 60: freq = 5355000; break; + case 40: freq = 7100000; break; + case 30: freq = 10130000; break; + case 20: freq = 14100000; break; + case 17: freq = 18120000; break; + case 15: freq = 21150000; break; + case 12: freq = 24940000; break; + case 10: freq = 28320000; break; + case 6: freq = 50150000; break; + case 2: freq = 144300000; break; + case 70: freq = 432200000; break; + default: freq = rigSet.freqMain; break; + } + + rigSet.freqMain = freq; + rigCmd.freqMain = 1; + rigCmd.bandChange = 1; +} + +void quick_split () +{ + if (rigGet.vfoMain == RIG_VFO_A) + { + rigSet.freqSub = rigGet.freqMain + 5000; + //rigSet.modeSub = rigGet.modeMain; + rigCmd.freqSub = 1; + //rigCmd.modeSub = 1; + } + else + { + rigSet.freqMain = rigGet.freqSub + 5000; + rigCmd.freqMain = 1; + } + rigCmd.split = 1; +} + +agc_level_e levelagcvalue (int agcValue) +{ + agc_level_e agcLevel; + + switch (agcValue) + { + case 0: agcLevel = RIG_AGC_OFF; break; + case 1: agcLevel = RIG_AGC_SUPERFAST; break; + case 2: agcLevel = RIG_AGC_FAST; break; + case 3: agcLevel = RIG_AGC_SLOW; break; + case 4: agcLevel = RIG_AGC_USER; break; + case 5: agcLevel = RIG_AGC_MEDIUM; break; + case 6: agcLevel = RIG_AGC_AUTO; break; + default: agcLevel = RIG_AGC_AUTO; break; + } + + return agcLevel; +} + +agc_level_e levelagcstr (QString agcString) +{ + agc_level_e agcLevel; + + if (agcString == "OFF") agcLevel = RIG_AGC_OFF; + else if (agcString == "SUPERFAST") agcLevel = RIG_AGC_SUPERFAST; + else if (agcString == "FAST") agcLevel = RIG_AGC_FAST; + else if (agcString == "SLOW") agcLevel = RIG_AGC_SLOW; + else if (agcString == "USER") agcLevel = RIG_AGC_USER; + else if (agcString == "MEDIUM") agcLevel = RIG_AGC_MEDIUM; + else agcLevel = RIG_AGC_AUTO; + + return agcLevel; +} + +value_t valueagclevel (agc_level_e agcLevel) +{ + value_t value; + + if (agcLevel == RIG_AGC_OFF) value.i = 0; + else if (agcLevel == RIG_AGC_SUPERFAST) value.i = 1; + else if (agcLevel == RIG_AGC_FAST) value.i = 2; + else if (agcLevel == RIG_AGC_SLOW) value.i = 3; + else if (agcLevel == RIG_AGC_USER) value.i = 4; + else if (agcLevel == RIG_AGC_MEDIUM) value.i = 5; + else value.i = 6; //RIG_AGC_AUTO + + return value; +} + +ant_t antstr (QString antString) +{ + ant_t ant; + + if (antString == "NONE") ant = RIG_ANT_NONE; + else if (antString == "ANT1") ant = RIG_ANT_1; + else if (antString == "ANT2") ant = RIG_ANT_2; + else if (antString == "ANT3") ant = RIG_ANT_3; + else if (antString == "ANT4") ant = RIG_ANT_4; + else if (antString == "ANT5") ant = RIG_ANT_5; + else if (antString == "UNK") ant = RIG_ANT_UNKNOWN; + else if (antString == "CURR") ant = RIG_ANT_CURR; + else ant = RIG_ANT_UNKNOWN; + + return ant; +} + +unsigned levelmeterstr (QString meterString) +{ + unsigned levelMeter; + + if (meterString == "SWR") levelMeter = RIG_LEVEL_SWR; + else if (meterString == "COMP") levelMeter = RIG_LEVEL_COMP; + else if (meterString == "ALC") levelMeter = RIG_LEVEL_ALC; + //... + else levelMeter = RIG_METER_NONE; + + return levelMeter; +} diff --git a/rigcommand.h b/rigcommand.h new file mode 100644 index 0000000..7c76aeb --- /dev/null +++ b/rigcommand.h @@ -0,0 +1,36 @@ +/** + ** This file is part of the CatRadio project. + ** Copyright 2022 Gianfranco Sordetti IZ8EWD . + ** + ** 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, either 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 for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with this program. If not, see . + **/ + + +#ifndef RIGCOMMAND_H +#define RIGCOMMAND_H + +#endif // RIGCOMMAND_H + +#include + +#include + + +void set_band (int band); +void quick_split (); +agc_level_e levelagcvalue (int agcValue); +agc_level_e levelagcstr (QString agcString); +value_t valueagclevel (agc_level_e agcLevel); +ant_t antstr (QString antString); +unsigned levelmeterstr (QString meterString); diff --git a/rigdaemon.cpp b/rigdaemon.cpp new file mode 100644 index 0000000..408a278 --- /dev/null +++ b/rigdaemon.cpp @@ -0,0 +1,424 @@ +/** + ** This file is part of the CatRadio project. + ** Copyright 2022 Gianfranco Sordetti IZ8EWD . + ** + ** 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, either 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 for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with this program. If not, see . + **/ + + +#include "rigdaemon.h" +#include "rigdata.h" +#include "rigcommand.h" + +#include +#include +#include + +#include + + +RIG *my_rig; + +extern rigConnect rigCom; +extern rigSettings rigGet; +extern rigSettings rigSet; +extern rigCommand rigCmd; +extern rigCommand rigCap; + +int commandPriority = 0; + + +RigDaemon::RigDaemon(QObject *parent) : QObject(parent) +{ + +} + +int RigDaemon::rigConnect() +{ + int retcode; + + my_rig = rig_init(rigCom.rigModel); //Allocate rig handle + + if (!my_rig) //Wrong Rig number + { + QMessageBox msgBox; //Show error MessageBox + msgBox.setWindowTitle("Warning"); + msgBox.setText("Rig model error"); + msgBox.setIcon(QMessageBox::Warning); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.exec(); + + return -1; //RIG_EINVAL, Invalid parameter + } + else + { + if (rigCom.rigModel == 2) //Rigctld + { + //myport.type.rig = RIG_PORT_NETWORK; + strncpy(my_rig->state.rigport.pathname, rigCom.rigPort.toLatin1(), HAMLIB_FILPATHLEN - 1); + //strncpy(my_rig->state.rigport.pathname, RIG_FILE, HAMLIB_FILPATHLEN - 1); + } + else + { + //myport.type.rig = RIG_PORT_SERIAL; + strncpy(my_rig->state.rigport.pathname, rigCom.rigPort.toLatin1(), HAMLIB_FILPATHLEN - 1); + my_rig->state.rigport.parm.serial.rate = rigCom.serialSpeed; + if (rigCom.civAddr) //CI-V address Icom + { + std::string civaddrS = std::to_string(rigCom.civAddr); //Convert int to string + char const *civaddr = civaddrS.c_str(); //Convert string to char* + rig_set_conf(my_rig, rig_token_lookup(my_rig, "civaddr"), civaddr); + } + } + + retcode = rig_open(my_rig); + + if (retcode != RIG_OK) return retcode; //Rig not connected + else //Rig connected + { + rig_get_powerstat(my_rig, &rigGet.onoff); + return 0; + } + + } +} + +void RigDaemon::rigUpdate() +{ + int retcode; + value_t retvalue; + + //***** Command execution ***** + //* PTT + if (rigCmd.ptt) + { + retcode = rig_set_ptt(my_rig, RIG_VFO_CURR, rigSet.ptt); + if (retcode == RIG_OK) rigGet.ptt = rigSet.ptt; + rigCmd.ptt = 0; + } + + //* VFO + if (rigCmd.freqMain) //VFO Main + { + retcode = rig_set_freq(my_rig, RIG_VFO_CURR, rigSet.freqMain); + if (retcode == RIG_OK) rigGet.freqMain = rigSet.freqMain; + rigCmd.freqMain = 0; + rigCmd.rangeList = 1; + } + + else if (rigCmd.freqSub) //VFO Sub + { + retcode = rig_set_freq(my_rig, rigGet.vfoSub, rigSet.freqSub); + if (retcode == RIG_OK) rigGet.freqSub = rigSet.freqSub; + rigCmd.freqSub = 0; + } + + else + { + freq_t retfreq; + retcode = rig_get_freq(my_rig, RIG_VFO_CURR, &retfreq); + if (retcode == RIG_OK) rigGet.freqMain = retfreq; + retcode = rig_get_freq(my_rig, rigGet.vfoSub, &retfreq); + if (retcode == RIG_OK) rigGet.freqSub = retfreq; + + ptt_t retptt; + retcode = rig_get_ptt(my_rig, RIG_VFO_CURR, &retptt); + if (retcode == RIG_OK) rigGet.ptt = retptt; + + //* Meter + if (rigGet.ptt==1) + { + rig_get_level(my_rig, RIG_VFO_CURR, RIG_LEVEL_RFPOWER_METER, &rigGet.powerMeter); + rig_get_level(my_rig, RIG_VFO_CURR, rigSet.meter, &rigGet.subMeter); + } + else + { + retcode = rig_get_level(my_rig, RIG_VFO_CURR, RIG_LEVEL_STRENGTH, &retvalue); + if (retcode == RIG_OK) rigGet.sMeter = retvalue; + } + + if (!rigGet.ptt) + { + //* Mode + if (rigCmd.mode) + { + retcode = rig_set_mode(my_rig, RIG_VFO_CURR, rigSet.mode, RIG_PASSBAND_NOCHANGE); + if (retcode == RIG_OK) + { + rigCmd.bwidthList = 1; //Update BWidth list + commandPriority = 0; + //rig_get_mode(my_rig, RIG_VFO_CURR, &rigGet.mode, &rigGet.bwidth); //Get BW + } + rigCmd.mode = 0; + } + + //* BandWidth + if (rigCmd.bwidth) + { + retcode = rig_set_mode(my_rig, RIG_VFO_CURR, rigGet.mode, rigSet.bwidth); + if (retcode == RIG_OK) rigGet.bwidth = rigSet.bwidth; + rigCmd.bwidth = 0; + } + + //* Split + if (rigCmd.split) + { + retcode = rig_set_split_vfo(my_rig, RIG_VFO_RX, rigSet.split, RIG_VFO_TX); + if (retcode == RIG_OK) rigGet.split = rigSet.split; + rigCmd.split = 0; + } + + //* VFO Exchange + if (rigCmd.vfoXchange) + { + retcode = rig_vfo_op(my_rig, RIG_VFO_CURR, RIG_OP_XCHG); + if (retcode == RIG_OK) commandPriority = 0; + rigCmd.vfoXchange = 0; + } + + //* VFO Copy + if (rigCmd.vfoCopy) + { + rig_vfo_op(my_rig, RIG_VFO_CURR, RIG_OP_CPY); + rigCmd.vfoCopy = 0; + } + + //* Band Up + if (rigCmd.bandUp) + { + retcode = rig_vfo_op(my_rig, RIG_VFO_CURR, RIG_OP_BAND_UP); + if (retcode == RIG_OK) commandPriority = 0; + rigCmd.bandUp = 0; + } + + //* Band Down + if (rigCmd.bandDown) + { + retcode = rig_vfo_op(my_rig, RIG_VFO_CURR, RIG_OP_BAND_DOWN); + if (retcode == RIG_OK) commandPriority = 0; + rigCmd.bandDown = 0; + } + + //* Band change + if (rigCmd.bandChange) commandPriority = 0; + + //* Tune + if (rigCmd.tune) + { + rig_vfo_op(my_rig, RIG_VFO_CURR, RIG_OP_TUNE); + rigCmd.tune = 0; + } + + //* Antenna + if (rigCmd.ant) + { + retcode = rig_set_ant(my_rig, RIG_VFO_CURR, rigSet.ant, retvalue); + if (retcode == RIG_OK) rigGet.ant = rigSet.ant; + rigCmd.ant = 0; + } + + //* AGC + if (rigCmd.agc) + { + retcode = rig_set_level(my_rig, RIG_VFO_CURR, RIG_LEVEL_AGC, valueagclevel(rigSet.agc)); + if (retcode == RIG_OK) rigGet.agc = rigSet.agc; + rigCmd.agc = 0; + } + + //* Attenuator + if (rigCmd.att) + { + retvalue.i = rigSet.att; + retcode = rig_set_level(my_rig, RIG_VFO_CURR, RIG_LEVEL_ATT, retvalue); + if (retcode == RIG_OK) rigGet.att = rigSet.att; + rigCmd.att = 0; + } + + //* Preamp + if (rigCmd.pre) + { + retvalue.i = rigSet.pre; + retcode = rig_set_level(my_rig, RIG_VFO_CURR, RIG_LEVEL_PREAMP, retvalue); + if (retcode == RIG_OK) rigGet.pre = rigSet.pre; + rigCmd.pre = 0; + } + + //* RF gain + if (rigCmd.rfGain) + { + retvalue.f = rigSet.rfGain; + retcode = rig_set_level(my_rig, RIG_VFO_CURR, RIG_LEVEL_RF, retvalue); + if (retcode == RIG_OK) rigGet.rfGain = rigSet.rfGain; + rigCmd.rfGain = 0; + } + + //* NB noise blanker + if (rigCmd.noiseBlanker) + { + retcode = rig_set_func(my_rig, RIG_VFO_CURR, RIG_FUNC_NB, rigSet.noiseBlanker); + if (retcode == RIG_OK) rigGet.noiseBlanker = rigSet.noiseBlanker; + rigCmd.noiseBlanker = 0; + } + + //* NR noise reduction + if (rigCmd.noiseReduction) + { + retcode = rig_set_func(my_rig, RIG_VFO_CURR, RIG_FUNC_NR, rigSet.noiseReduction); + if (retcode == RIG_OK) rigGet.noiseReduction = rigSet.noiseReduction; + rigCmd.noiseReduction = 0; + } + + if (rigCmd.noiseReductionLevel) + { + retvalue.i = rigSet.noiseReductionLevel; + retcode = rig_set_level(my_rig, RIG_VFO_CURR, RIG_LEVEL_NR, retvalue); + if (retcode == RIG_OK) rigGet.noiseReductionLevel = rigSet.noiseReductionLevel; + rigCmd.noiseReductionLevel = 0; + } + + //* NF notch filter + if (rigCmd.notchFilter) + { + retcode = rig_set_func(my_rig, RIG_VFO_CURR, RIG_FUNC_ANF, rigSet.notchFilter); + if (retcode == RIG_OK) rigGet.notchFilter = rigSet.notchFilter; + rigCmd.notchFilter = 0; + } + + //* IF Shift + if (rigCmd.ifShift) + { + retvalue.i = rigSet.ifShift; + retcode = rig_set_level(my_rig, RIG_VFO_CURR, RIG_LEVEL_IF, retvalue); + if (retcode == RIG_OK) rigGet.ifShift = rigSet.ifShift; + rigCmd.ifShift = 0; + } + } //end if (!rigGet.ptt) + + //* Tuner + if (rigCmd.tuner) + { + retcode = rig_set_func(my_rig, RIG_VFO_CURR, RIG_FUNC_TUNER, rigSet.tuner); + if (retcode == RIG_OK) rigGet.tuner = rigSet.tuner; + rigCmd.tune = 0; + } + + //* RF power + if (rigCmd.rfPower) + { + retvalue.f = rigSet.rfPower; + retcode = rig_set_level(my_rig, RIG_VFO_CURR, RIG_LEVEL_RFPOWER, retvalue); + if (retcode == RIG_OK) rigGet.rfPower = rigSet.rfPower; + rigCmd.rfPower = 0; + } + + //***** Poll execution ***** + if ((commandPriority == 1 && !rigGet.ptt && rigCom.fullPoll) || commandPriority == 0) + { + //* Mode and BW + rig_get_mode(my_rig, RIG_VFO_CURR, &rigGet.mode, &rigGet.bwidth); + //rig_get_mode(my_rig, rigGet.vfoSub, &rigGet.modeSub, &rigGet.bwidthSub); + if (rigGet.bwidth == rig_passband_narrow(my_rig, rigGet.mode)) rigGet.bwNarrow = 1; + else rigGet.bwNarrow = 0; + } + + if ((commandPriority == 2 && !rigGet.ptt && rigCom.fullPoll) || commandPriority == 0) + { + //* Split + rig_get_split_vfo(my_rig, RIG_VFO_CURR, &rigGet.split, &rigGet.vfoTx); + //else rig_get_split(my_rig, RIG_VFO_CURR, &rigGet.split); + + rig_get_vfo(my_rig, &rigGet.vfoMain); + } + + //* Tuner + if ((commandPriority == 3 && !rigGet.ptt && rigCom.fullPoll) || commandPriority == 0) rig_get_func(my_rig, RIG_VFO_CURR, RIG_FUNC_TUNER, &rigGet.tuner); + + //* Antenna + if ((commandPriority == 4 && !rigGet.ptt && rigCom.fullPoll) || commandPriority == 0) rig_get_ant(my_rig, RIG_VFO_CURR, RIG_ANT_CURR, &retvalue, &rigGet.ant, &rigGet.antTx, &rigGet.antRx); + + //* AGC + if ((commandPriority == 5 && !rigGet.ptt && rigCom.fullPoll) || commandPriority == 0) + { + rig_get_level(my_rig, RIG_VFO_CURR, RIG_LEVEL_AGC, &retvalue); + rigGet.agc = levelagcvalue(retvalue.i); + } + + //* Attenuator + if ((commandPriority == 6 && !rigGet.ptt && rigCom.fullPoll) || commandPriority == 0) + { + rig_get_level(my_rig, RIG_VFO_CURR, RIG_LEVEL_ATT, &retvalue); + rigGet.att = retvalue.i; + } + + //* Preamp + if ((commandPriority == 7 && !rigGet.ptt && rigCom.fullPoll) || commandPriority == 0) + { + rig_get_level(my_rig, RIG_VFO_CURR, RIG_LEVEL_PREAMP, &retvalue); + rigGet.pre = retvalue.i; + } + + //* RF power + if ((commandPriority == 8 && !rigGet.ptt && rigCom.fullPoll) || commandPriority == 0) + { + rig_get_level(my_rig, RIG_VFO_CURR, RIG_LEVEL_RFPOWER, &retvalue); + rigGet.rfPower = retvalue.f; + } + + //* RF gain + if ((commandPriority == 9 && !rigGet.ptt && rigCom.fullPoll) || commandPriority == 0) + { + rig_get_level(my_rig, RIG_VFO_CURR, RIG_LEVEL_RF, &retvalue); + rigGet.rfGain = retvalue.f; + } + + //* NB noise blanker + if ((commandPriority == 10 && !rigGet.ptt && rigCom.fullPoll) || commandPriority == 0) rig_get_func(my_rig, RIG_VFO_CURR, RIG_FUNC_NB, &rigGet.noiseBlanker); + + //* NR noise reduction + if ((commandPriority == 11 && !rigGet.ptt && rigCom.fullPoll) || commandPriority == 0) + { + rig_get_func(my_rig, RIG_VFO_CURR, RIG_FUNC_NR, &rigGet.noiseReduction); + rig_get_level(my_rig, RIG_VFO_CURR, RIG_LEVEL_NR, &retvalue); + rigGet.noiseReductionLevel = retvalue.i; + } + + //* NF notch filter + if ((commandPriority == 12 && !rigGet.ptt && rigCom.fullPoll) || commandPriority == 0) rig_get_func(my_rig, RIG_VFO_CURR, RIG_FUNC_ANF, &rigGet.notchFilter); + + //* IF Shift + if ((commandPriority == 13 && !rigGet.ptt && rigCom.fullPoll) || commandPriority == 0) + { + rig_get_level(my_rig, RIG_VFO_CURR, RIG_LEVEL_IF, &retvalue); + rigGet.ifShift = retvalue.i; + } + + if ((commandPriority == 14 && !rigGet.ptt && rigCom.fullPoll) || commandPriority == 0) //&& mode=CW + { + //* CW Full Break-in + if (rigCmd.bkin) + { + retcode = rig_set_func(my_rig, RIG_VFO_CURR, RIG_FUNC_FBKIN, rigSet.bkin); + if (retcode == RIG_OK) rigGet.bkin = rigSet.bkin; + rigCmd.bkin = 0; + } + else rig_get_func(my_rig, RIG_VFO_CURR, RIG_FUNC_FBKIN, &rigGet.bkin); + } + + commandPriority ++; + if (commandPriority == 15) commandPriority = 1; + + } + + emit resultReady(); +} diff --git a/rigdaemon.h b/rigdaemon.h new file mode 100644 index 0000000..4020535 --- /dev/null +++ b/rigdaemon.h @@ -0,0 +1,42 @@ +/** + ** This file is part of the CatRadio project. + ** Copyright 2022 Gianfranco Sordetti IZ8EWD . + ** + ** 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, either 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 for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with this program. If not, see . + **/ + + +#ifndef RIGDAEMON_H +#define RIGDAEMON_H + +#include +#include + +class RigDaemon : public QObject +{ + Q_OBJECT + +public: + explicit RigDaemon(QObject *parent = nullptr); + int rigConnect(); + +public slots: + void rigUpdate(); + +signals: + void resultReady(); + +}; + +#endif // RIGDAEMON_H diff --git a/rigdata.cpp b/rigdata.cpp new file mode 100644 index 0000000..84560e7 --- /dev/null +++ b/rigdata.cpp @@ -0,0 +1,26 @@ +/** + ** This file is part of the CatRadio project. + ** Copyright 2022 Gianfranco Sordetti IZ8EWD . + ** + ** 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, either 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 for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with this program. If not, see . + **/ + + +#include "rigdata.h" + +rigConnect rigCom; +rigSettings rigGet; +rigSettings rigSet; +rigCommand rigCmd; +rigCommand rigCap; diff --git a/rigdata.h b/rigdata.h new file mode 100644 index 0000000..87fe302 --- /dev/null +++ b/rigdata.h @@ -0,0 +1,100 @@ +/** + ** This file is part of the CatRadio project. + ** Copyright 2022 Gianfranco Sordetti IZ8EWD . + ** + ** 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, either 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 for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with this program. If not, see . + **/ + + +#ifndef RIGDATA_H +#define RIGDATA_H + +#endif // RIGDATA_H + +#include //Hamlib + +#include + +typedef struct { + unsigned rigModel; //Hamlib rig model + QString rigPort; //COM port or IP address + unsigned serialSpeed; //Serial port baud rate + int civAddr; //CI-V address (decimal, Icom radio) + unsigned rigRefresh; //GUI refresh interval (ms) + int connected; //connected flag + bool fullPoll; //full polling flag +} rigConnect; + +typedef struct { + powerstat_t onoff; //on/off status + freq_t freqMain, freqSub; //Frequency + rmode_t mode, modeSub; //Mode + pbwidth_t bwidth, bwidthSub; //IF filter bandwidth + int bwNarrow; //IF narrow filter + vfo_t vfoMain, vfoSub; //VFO + vfo_t vfoTx; + split_t split; //Split + ptt_t ptt; //PTT + value_t sMeter; //Smeter signal strenght + value_t powerMeter; //RF power meter + value_t subMeter; //secondary meter + unsigned meter; //secondary meter type + float rfPower; //RF power output level + float rfGain; //RF gain rx + agc_level_e agc; //AGC level + int att; //Attenuator + int pre; //Preamplifier + ant_t ant, antTx, antRx; //Antenna + int rangeListTxIndex, rangeListRxIndex; + int tuner; //Tuner + int bkin; //CW Break-in + int apf; + int noiseBlanker; + int noiseReduction, noiseReductionLevel; + int notchFilter; + int ifShift; +} rigSettings; + +typedef struct { + int onoff; + int freqMain; + int freqSub; + int mode; + int bwidth; + int bwidthList; + int vfo; + int split; + int vfoXchange; + int vfoCopy; + int ptt; + int rfPower; + int rfGain; + int agc; + int att; + int pre; + int ant; + int antList; + int rangeList; + int tuner; + int tune; + int bandUp; + int bandDown; + int bandChange; + int bkin; + int apf; + int noiseBlanker; + int noiseReduction, noiseReductionLevel; + int notchFilter; + int ifShift; +} rigCommand; diff --git a/smeter.cpp b/smeter.cpp new file mode 100644 index 0000000..442f1a8 --- /dev/null +++ b/smeter.cpp @@ -0,0 +1,318 @@ +/** + ** This file is part of the CatRadio project. + ** Copyright 2022 Gianfranco Sordetti IZ8EWD . + ** + ** 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, either 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 for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with this program. If not, see . + **/ + + +#include "smeter.h" +#include + +SMeter::SMeter(QWidget *parent) : QWidget(parent) +{ + lineColor = QColor(Qt::black); + bgColor = QColor(Qt::white); + progressColor = QColor(Qt::green); + + //Default value + minValue = 0; + maxValue = 100; + gateValue = 80; + longStep = 20; + shortStep = 10; + precision = 0; + + meterTx = 0; + + currentValue = -54; +} + +void SMeter::paintEvent(QPaintEvent *) +{ + QPainter painter(this); + painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); + + QFont font; + font = painter.font(); + font.setPointSize(font.pointSize() - 2); + painter.setFont(font); + + drawMeter(&painter); + drawProgress(&painter); + drawScaleSMeter(&painter); + drawScalePWRMeter(&painter); +} + +void SMeter::drawMeter(QPainter *painter) +{ + painter->save(); + + QPen pen(lineColor, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin); + painter->setPen(pen); + painter->setBrush(bgColor); + painter->drawRect(0, height()/3+2, width()-12, height()/3-4); + painter->restore(); +} + +void SMeter::drawProgress(QPainter *painter) +{ + double max, min; + double gate; + + painter->save(); + painter->setPen(Qt::NoPen); + painter->setBrush(progressColor); + + if (meterTx) //RF power meter + { + max = maxValue; + min = minValue; + gate = gateValue; + } + else //SMeter + { + max = 60; + min = -54; + gate = 0; + } + + double length = width()-14; + double increment = length / (max - min); + double initX, initXX; + + if (currentValue>gate) + { + initX = (gate - min) * increment; + QRect rect(1, height()/3+2+1, initX, height()/3-4-2); + painter->drawRect(rect); + + //Red bar + initXX = (currentValue - gate) * increment; + QRect rect2(initX+1, height()/3+2+1, initXX, height()/3-4-2); + painter->setBrush(Qt::red); + painter->drawRect(rect2); + } + else + { + initX = (currentValue - min) * increment; + QRect rect(1, height()/3+2+1, initX, height()/3-4-2); + painter->drawRect(rect); + } + + painter->restore(); +} + +void SMeter::drawScalePWRMeter(QPainter *painter) +{ + painter->save(); + painter->setPen(lineColor); + + double initX = 0; + double initTopY = height()*2/3-2; + double length = width()-12; + double increment = length / (maxValue - minValue); + + int longLineLen = 6; + int shortLineLen = 3; + + QFontMetrics meterFont(painter->font()); + double textHeight = meterFont.height(); + + //Draw scale values and scale values based on range values Long lines + int stepNumber = (maxValue - minValue) / shortStep; + for (int i = 0; i <= stepNumber; i++) + { + double j = i * shortStep + minValue; + if (fmod(j,longStep) == 0) + { + if (j == minValue) //Do not draw the first value + { + QPointF textPot = QPointF(initX, initTopY + textHeight); + painter->drawText(textPot, "PO"); + + initX += increment * shortStep; + continue; + } + + QPointF topPot = QPointF(initX, initTopY); + QPointF bottomPot = QPointF(initX, initTopY + longLineLen); + painter->drawLine(topPot, bottomPot); + + QString strValue = QString("%1").arg(j, 0, 'f', precision); + double textWidth = fontMetrics().horizontalAdvance(strValue); + + QPointF textPot = QPointF(initX - textWidth / 2, initTopY + textHeight + longLineLen); + painter->drawText(textPot, strValue); + } + else + { + + QPointF topPot = QPointF(initX, initTopY); + QPointF bottomPot = QPointF(initX, initTopY + shortLineLen); + painter->drawLine(topPot, bottomPot); + } + + initX += increment * shortStep; + } + + painter->restore(); +} + +void SMeter::drawScaleSMeter(QPainter *painter) +{ + int minValue = -54; //Set min and max value according to Hamlib SMeter definition + int maxValue = 60; + + int longLineLen = 6; + int shortLineLen = 3; + + double initX = 0; + int sUnit = 0; + + double initBottomY = height()/3+2; + double length = width()-12; + double increment = length / (maxValue - minValue); + + QFontMetrics meterFont(painter->font()); + double textHeight = meterFont.height(); + + painter->save(); + painter->setPen(lineColor); + + //Draw scale values and scale values based on range values + int longStep = 12; + int shortStep = 6; + + for (int i = minValue; i <= 0; i = i + shortStep) //S0 to S9 + { + if (i == minValue) + { + QPointF textPot = QPointF(initX, initBottomY - 2); + painter->drawText(textPot, "S"); + + initX += increment * shortStep; + sUnit = sUnit + 1; + continue; + } + + if (i % longStep == 0) + { + QPointF topPot = QPointF(initX, initBottomY); + QPointF bottomPot = QPointF(initX, initBottomY - longLineLen); + painter->drawLine(topPot, bottomPot); + + QString strValue = QString::number(sUnit); + double textWidth = fontMetrics().horizontalAdvance(strValue); + QPointF textPot = QPointF(initX - textWidth / 2, initBottomY - textHeight / 2 - longLineLen + 2); + painter->drawText(textPot, strValue); + } + else + { + QPointF topPot = QPointF(initX, initBottomY); + QPointF bottomPot = QPointF(initX, initBottomY - shortLineLen); + painter->drawLine(topPot, bottomPot); + } + + sUnit = sUnit + 1; + initX += increment * shortStep; + } + initX -= increment * shortStep; + + shortStep = 10; + longStep = 20; + + for (int i = 0; i <= maxValue; i = i + shortStep) //S9+ to S9+60 + { + if (i % longStep == 0) + { + QPointF topPot = QPointF(initX, initBottomY); + QPointF bottomPot = QPointF(initX, initBottomY - longLineLen); + painter->drawLine(topPot, bottomPot); + + if (i == 0) //Do not draw the first value + { + initX += increment * shortStep; + continue; + } + + QString strValue = "+" + QString::number(i); + double textWidth = fontMetrics().horizontalAdvance(strValue); + + QPointF textPot = QPointF(initX - textWidth / 2, initBottomY - textHeight / 2 - longLineLen + 2); + painter->drawText(textPot, strValue); + } + else + { + QPointF topPot = QPointF(initX, initBottomY); + QPointF bottomPot = QPointF(initX, initBottomY - shortLineLen); + painter->drawLine(topPot, bottomPot); + } + + initX += increment * shortStep; + } + + painter->restore(); +} + +void SMeter::setMinValue(double value) +{ + minValue = value; + update(); +} + +void SMeter::setMaxValue(double value) +{ + maxValue = value; + update(); +} + +void SMeter::setGateValue(double value) +{ + gateValue = value; +} + +void SMeter::setLongStep(double value) +{ + longStep = value; + update(); +} + +void SMeter::setShortStep(double value) +{ + shortStep = value; + update(); +} + +void SMeter::setPrecision(int value) +{ + precision = value; + update(); +} + +void SMeter::setValue(double value) +{ + currentValue = value; + update(); +} + +void SMeter::setValue(int value) +{ + setValue(double(value)); +} + +void SMeter::setTx(bool Tx) +{ + meterTx = Tx; +} diff --git a/smeter.h b/smeter.h new file mode 100644 index 0000000..f35c0f3 --- /dev/null +++ b/smeter.h @@ -0,0 +1,73 @@ +/** + ** This file is part of the CatRadio project. + ** Copyright 2022 Gianfranco Sordetti IZ8EWD . + ** + ** 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, either 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 for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with this program. If not, see . + **/ + + +#ifndef SMETER_H +#define SMETER_H + +#include + +class SMeter : public QWidget +{ + Q_OBJECT + +public: + explicit SMeter(QWidget *parent = nullptr); + +public slots: + void setMinValue(double value); + void setMaxValue(double value); + void setGateValue(double value); + void setLongStep(double value); + void setShortStep(double value); + void setPrecision(int value); + + void setValue(double value); + void setValue(int value); + + void setTx(bool Tx); + +protected: + void paintEvent(QPaintEvent *); + void drawMeter(QPainter *painter); + void drawProgress(QPainter *painter); + void drawScaleSMeter(QPainter *painter); + void drawScalePWRMeter(QPainter *painter); + +private: + double minValue; //Minimum scale value + double maxValue; //Maximum scale value + double gateValue; //Gate value to bar color change + double longStep; //Long lines with equal steps + double shortStep; //Short lines with equal steps + int precision; //Precision, the last few decimal places + + double value; //target value + double currentValue; //current value + + bool meterTx; //Switch between SMeter or PowerMeter + + QColor bgColor; //background color + QColor lineColor; //line color + QColor progressColor; //progress color + +signals: + +}; + +#endif // SMETER_H diff --git a/submeter.cpp b/submeter.cpp new file mode 100644 index 0000000..5052a38 --- /dev/null +++ b/submeter.cpp @@ -0,0 +1,195 @@ +/** + ** This file is part of the CatRadio project. + ** Copyright 2022 Gianfranco Sordetti IZ8EWD . + ** + ** 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, either 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 for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with this program. If not, see . + **/ + + +#include "submeter.h" +#include +#include + +SubMeter::SubMeter(QWidget *parent) : QWidget(parent) +{ + lineColor = QColor(Qt::black); + bgColor = QColor(Qt::white); + progressColor = QColor(Qt::green); + + //Default value + minValue = 0; + maxValue = 10; + gateValue = 10; + longStep = 5; + shortStep = 1; + precision = 0; + + currentValue = 0; +} + +void SubMeter::paintEvent(QPaintEvent *) +{ + QPainter painter(this); + painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); + + QFont font; + font = painter.font(); + font.setPointSize(font.pointSize() - 2); + painter.setFont(font); + + drawMeter(&painter); + drawProgress(&painter); + drawScale(&painter); +} + +void SubMeter::drawMeter(QPainter *painter) +{ + painter->save(); + QPen pen(lineColor, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin); + painter->setPen(pen); + painter->setBrush(bgColor); + painter->drawRect(0, height()/3+2, width()-12, height()/3-4); + painter->restore(); +} + +void SubMeter::drawProgress(QPainter *painter) +{ + painter->save(); + painter->setPen(Qt::NoPen); + painter->setBrush(progressColor); + + double length = width()-14; + double increment = length / (maxValue - minValue); + + double initX, initXX; + + if (currentValue>gateValue) + { + initX = (gateValue - minValue) * increment; + QRect rect(1, height()/3+2+1, initX, height()/3-4-2); + painter->drawRect(rect); + + //Red bar + initXX = (currentValue - gateValue) * increment; + QRect rect2(initX+1, height()/3+2+1, initXX, height()/3-4-2); + painter->setBrush(Qt::red); + painter->drawRect(rect2); + } + else + { + initX = (currentValue - minValue) * increment; + QRect rect(1, height()/3+2+1, initX, height()/3-4-2); + painter->drawRect(rect); + } + + painter->restore(); +} + +void SubMeter::drawScale(QPainter *painter) +{ + painter->save(); + painter->setPen(lineColor); + + double initX = 0; + double initTopY = height()*2/3-2; + double length = width()-12; + double increment = length / (maxValue - minValue); + + int longLineLen = 6; + int shortLineLen = 3; + + QFontMetrics meterFont(painter->font()); + double textHeight = meterFont.height(); + + //Draw scale values and scale values based on range values + int stepNumber = (maxValue - minValue) / shortStep; + for (int i = 0; i <= stepNumber; i++) + { + double j = i * shortStep + minValue; + if (fmod(j,longStep) == 0) + { + if (j == minValue) //Do not draw the first value + { + initX += increment * shortStep; + continue; + } + + QPointF topPot = QPointF(initX, initTopY); + QPointF bottomPot = QPointF(initX, initTopY + longLineLen); + painter->drawLine(topPot, bottomPot); + + QString strValue = QString("%1").arg(j, 0, 'f', precision); + double textWidth = fontMetrics().horizontalAdvance(strValue); + + QPointF textPot = QPointF(initX - textWidth / 2, initTopY + textHeight + longLineLen); + painter->drawText(textPot, strValue); + } + else + { + QPointF topPot = QPointF(initX, initTopY); + QPointF bottomPot = QPointF(initX, initTopY + shortLineLen); + painter->drawLine(topPot, bottomPot); + } + + initX += increment * shortStep; + } + + painter->restore(); +} + +void SubMeter::setMinValue(double value) +{ + minValue = value; + update(); +} + +void SubMeter::setMaxValue(double value) +{ + maxValue = value; + update(); +} + +void SubMeter::setGateValue(double value) +{ + gateValue = value; +} + +void SubMeter::setLongStep(double value) +{ + longStep = value; + update(); +} + +void SubMeter::setShortStep(double value) +{ + shortStep = value; + update(); +} + +void SubMeter::setPrecision(int value) +{ + precision = value; + update(); +} + +void SubMeter::setValue(double value) +{ + currentValue = value; + update(); +} + +void SubMeter::setValue(int value) +{ + setValue(double(value)); +} diff --git a/submeter.h b/submeter.h new file mode 100644 index 0000000..f65573d --- /dev/null +++ b/submeter.h @@ -0,0 +1,67 @@ +/** + ** This file is part of the CatRadio project. + ** Copyright 2022 Gianfranco Sordetti IZ8EWD . + ** + ** 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, either 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 for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with this program. If not, see . + **/ + + +#ifndef SUBMETER_H +#define SUBMETER_H + +#include + +class SubMeter : public QWidget +{ + Q_OBJECT +public: + explicit SubMeter(QWidget *parent = nullptr); + +public slots: + void setMinValue(double value); + void setMaxValue(double value); + void setGateValue(double value); + void setLongStep(double value); + void setShortStep(double value); + void setPrecision(int value); + + void setValue(double value); + void setValue(int value); + +protected: + void paintEvent(QPaintEvent *); + void drawMeter(QPainter *painter); + void drawProgress(QPainter *painter); + void drawScale(QPainter *painter); + +private: + double minValue; //Minimum scale value + double maxValue; //Maximum scale value + double gateValue; //Gate value to bar color change + double longStep; //Long lines with equal steps + double shortStep; //Short lines with equal steps + int precision; //Precision, the last few decimal places + + double value; //target value + double currentValue; //current value + + QColor bgColor; //background color + QColor lineColor; //line color + QColor progressColor; //progress color + +signals: + +}; + +#endif // SUBMETER_H diff --git a/vfodisplay.cpp b/vfodisplay.cpp new file mode 100644 index 0000000..67c6d7c --- /dev/null +++ b/vfodisplay.cpp @@ -0,0 +1,152 @@ +/** + ** This file is part of the CatRadio project. + ** Copyright 2022 Gianfranco Sordetti IZ8EWD . + ** + ** 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, either 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 for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with this program. If not, see . + **/ + + +#include "vfodisplay.h" +#include "guidata.h" + +#include +#include +#include + + +extern guiConfig guiConf; + + +vfoDisplay::vfoDisplay(QWidget *parent) : QWidget(parent) +{ + lineColor = QColor(Qt::black); + bgColor = QColor(Qt::white); + textColor = QColor(Qt::black); +} + +void vfoDisplay::paintEvent(QPaintEvent *) +{ + //setMouseTracking(true); + + QPainter painter(this); + painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); + + QFont font; + font = painter.font(); + font.setPointSize(height() - 18); + painter.setFont(font); + + drawDisplay(&painter); + drawText(&painter); +} + +void vfoDisplay::drawDisplay(QPainter *painter) +{ + painter->save(); + + QPen pen(lineColor, 1, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin); + painter->setPen(pen); + painter->setBrush(bgColor); + painter->drawRect(1, 1, width()-3, height()-2); + painter->restore(); +} + +void vfoDisplay::drawText(QPainter *painter) +{ + painter->save(); + painter->setPen(textColor); + + QFontMetrics meterFont(painter->font()); + double textHeight = meterFont.ascent(); + textWidth = meterFont.horizontalAdvance("0",-1); + + QPointF textPot; + + long val = currentValue; + + for (int i = 1; i < 10; i++) + { + val = qFloor(val/10); + int d = val % 10; + + if (i==2) + { + textPot = QPointF(width()-3-(textWidth+2)*i-4, textHeight); + painter->drawText(textPot, "."); + } + + textPot = QPointF(width()-3-(textWidth+2)*i, textHeight); + + if (val==0 && d==0) painter->drawText(textPot, " "); + else painter->drawText(textPot, QString::number(d)); + } + + painter->restore(); +} + +void vfoDisplay::setValue(unsigned long value) +{ + currentValue = value; + update(); +} + +//* Tuning using mouse buttons +void vfoDisplay::mousePressEvent(QMouseEvent *event) +{ + event->accept(); + + QPoint pointerPos = event->pos(); + + for (int i = 1; i < 10; i ++) + { + if (pointerPos.x() > (width()-3-(textWidth+2)*i+1) && pointerPos.x() < (width()-3-(textWidth+2)*(i-1)-1)) + { + if (guiConf.vfoDisplayMode && event->button() == Qt::LeftButton) //Up/Down mode + { + if (pointerPos.y() < height()/2) currentValue = currentValue + pow(10,i); //Up + else if (currentValue - pow(10,i) > 0) currentValue = currentValue - pow(10,i); //Down + } + else if (!guiConf.vfoDisplayMode) //Left/Right mode + { + if (event->button() == Qt::LeftButton) currentValue = currentValue + pow(10,i); //LeftButton + else if (currentValue - pow(10,i) > 0) currentValue = currentValue - pow(10,i); //RightButton + } + + break; + } + } + + update(); + emit on_valueChanged(currentValue); +} + +//* Tuning using mouse wheel +void vfoDisplay::wheelEvent(QWheelEvent *event) +{ + event->accept(); + + QPointF pointerPos = event->position(); + + for (int i = 1; i < 10; i ++) + { + if (pointerPos.x() > (width()-3-(textWidth+2)*i+1) && pointerPos.x() < (width()-3-(textWidth+2)*(i-1)-1)) + { + if (event->angleDelta().y() > 0) currentValue = currentValue + pow(10,i); //Wheel up + else if (currentValue - pow(10,i) > 0) currentValue = currentValue - pow(10,i); //Wheel down + } + } + + update(); + emit on_valueChanged(currentValue); +} diff --git a/vfodisplay.h b/vfodisplay.h new file mode 100644 index 0000000..9dee447 --- /dev/null +++ b/vfodisplay.h @@ -0,0 +1,37 @@ +#ifndef VFODISPLAY_H +#define VFODISPLAY_H + +#include + +class vfoDisplay : public QWidget +{ + Q_OBJECT + +public: + explicit vfoDisplay(QWidget *parent = nullptr); + +public slots: + void setValue(unsigned long value); + +signals: + void on_valueChanged(int value); + +protected: + void paintEvent(QPaintEvent *); + void drawDisplay(QPainter *painter); + void drawText(QPainter *painter); + void mousePressEvent(QMouseEvent *event); //Mouse buttons + void wheelEvent(QWheelEvent *event); //Mouse wheel + +private: + QColor bgColor; //background color + QColor lineColor; //line color + QColor textColor; //text color + + unsigned long currentValue; //current frequency value (Hz) + unsigned long value; //target value + + int textWidth; //number width +}; + +#endif // VFODISPLAY_H