From c81b3c8e6541cb0cfd4a657e912a92a72dce0ac8 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Fri, 23 Nov 2018 01:18:39 +0000 Subject: [PATCH] Validate contest QSO details before allowing logging Basic validation, must have non-empty exchange sent and received. Abstracted log view window widget behaviour into a base class. Turned on auto resize to row height in log view windows and enabled alternating colours. Convert empty fields to NULL when inserting new log table rows to signify missing data. Trap insert row errors when adding to contest log table so that logging can be held back if constraints are not met. Re-factored log QSO processing to try insert row into log table first and pop up a message box if constraints are not met, this pops up the Log QSO window in case it was initiated by an auto log event. --- CMakeLists.txt | 1 + models/CabrilloLog.cpp | 41 ++++++++++--- models/CabrilloLog.hpp | 2 +- models/FoxLog.cpp | 13 ++++- widgets/AbstractLogWindow.cpp | 76 ++++++++++++++++++++++++ widgets/AbstractLogWindow.hpp | 32 +++++++++++ widgets/CabrilloLogWindow.cpp | 105 ++++++++++++++++------------------ widgets/CabrilloLogWindow.hpp | 26 ++------- widgets/CabrilloLogWindow.ui | 20 ++++++- widgets/FoxLogWindow.cpp | 84 ++++++++------------------- widgets/FoxLogWindow.hpp | 23 ++------ widgets/FoxLogWindow.ui | 20 ++++++- widgets/logqso.cpp | 57 +++++++++++++----- widgets/logqso.h | 6 +- widgets/mainwindow.cpp | 40 +++++++------ widgets/widgets.pri | 10 ++-- 16 files changed, 349 insertions(+), 207 deletions(-) create mode 100644 widgets/AbstractLogWindow.cpp create mode 100644 widgets/AbstractLogWindow.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 39411f8a2..1cf9d88ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -265,6 +265,7 @@ set (wsjt_qt_CXXSRCS models/DecodeHighlightingModel.cpp widgets/DecodeHighlightingListView.cpp models/FoxLog.cpp + widgets/AbstractLogWindow.cpp widgets/FoxLogWindow.cpp widgets/CabrilloLogWindow.cpp item_delegates/CallsignDelegate.cpp diff --git a/models/CabrilloLog.cpp b/models/CabrilloLog.cpp index 055f8ae07..f447bca79 100644 --- a/models/CabrilloLog.cpp +++ b/models/CabrilloLog.cpp @@ -78,19 +78,46 @@ QAbstractItemModel * CabrilloLog::model () return &*m_; } -void CabrilloLog::add_QSO (Frequency frequency, QDateTime const& when, QString const& call +namespace +{ + void set_value_maybe_null (QSqlRecord& record, QString const& name, QString const& value) + { + if (value.size ()) + { + record.setValue (name, value); + } + else + { + record.setNull (name); + } + } +} + +bool CabrilloLog::add_QSO (Frequency frequency, QDateTime const& when, QString const& call , QString const& exchange_sent, QString const& exchange_received) { ConditionalTransaction transaction {*m_}; auto record = m_->record (); record.setValue ("frequency", frequency / 1000ull); // kHz - record.setValue ("when", when.toMSecsSinceEpoch () / 1000ull); - record.setValue ("call", call); - record.setValue ("exchange_sent", exchange_sent); - record.setValue ("exchange_rcvd", exchange_received); - record.setValue ("band", m_->configuration_->bands ()->find (frequency)); + if (!when.isNull ()) + { + record.setValue ("when", when.toMSecsSinceEpoch () / 1000ull); + } + else + { + record.setNull ("when"); + } + set_value_maybe_null (record, "call", call); + set_value_maybe_null (record, "exchange_sent", exchange_sent); + set_value_maybe_null (record, "exchange_rcvd", exchange_received); + set_value_maybe_null (record, "band", m_->configuration_->bands ()->find (frequency)); SQL_error_check (*m_, &QSqlTableModel::insertRecord, -1, record); - transaction.submit (); + if (!transaction.submit (false)) + { + transaction.revert (); + return false; + } + return true; } bool CabrilloLog::dupe (Frequency frequency, QString const& call) const diff --git a/models/CabrilloLog.hpp b/models/CabrilloLog.hpp index 9571adeeb..e328d0633 100644 --- a/models/CabrilloLog.hpp +++ b/models/CabrilloLog.hpp @@ -21,7 +21,7 @@ public: ~CabrilloLog (); // returns false if insert fails - void add_QSO (Frequency, QDateTime const&, QString const& call + bool add_QSO (Frequency, QDateTime const&, QString const& call , QString const& report_sent, QString const& report_received); bool dupe (Frequency, QString const& call) const; diff --git a/models/FoxLog.cpp b/models/FoxLog.cpp index 81763d9be..43cdd2b8f 100644 --- a/models/FoxLog.cpp +++ b/models/FoxLog.cpp @@ -88,12 +88,19 @@ bool FoxLog::add_QSO (QDateTime const& when, QString const& call, QString const& { ConditionalTransaction transaction {*m_}; auto record = m_->record (); - record.setValue ("when", when.toMSecsSinceEpoch () / 1000); - record.setValue ("call", call); + if (!when.isNull ()) + { + record.setValue ("when", when.toMSecsSinceEpoch () / 1000); + } + else + { + record.setNull ("when"); + } + set_value_maybe_null (record, "call", call); set_value_maybe_null (record, "grid", grid); set_value_maybe_null (record, "report_sent", report_sent); set_value_maybe_null (record, "report_rcvd", report_received); - record.setValue ("band", band); + set_value_maybe_null (record, "band", band); SQL_error_check (*m_, &QSqlTableModel::insertRecord, -1, record); if (!transaction.submit (false)) { diff --git a/widgets/AbstractLogWindow.cpp b/widgets/AbstractLogWindow.cpp new file mode 100644 index 000000000..ebc901cd8 --- /dev/null +++ b/widgets/AbstractLogWindow.cpp @@ -0,0 +1,76 @@ +#include "AbstractLogWindow.hpp" + +#include +#include +#include +#include +#include "Configuration.hpp" +#include "SettingsGroup.hpp" +#include "models/FontOverrideModel.hpp" +#include "pimpl_impl.hpp" + +class AbstractLogWindow::impl final +{ +public: + impl (QString const& settings_key, QSettings * settings, Configuration const * configuration) + : settings_key_ {settings_key} + , settings_ {settings} + , configuration_ {configuration} + , log_view_ {nullptr} + { + } + + QString settings_key_; + QSettings * settings_; + Configuration const * configuration_; + QTableView * log_view_; + FontOverrideModel model_; +}; + +AbstractLogWindow::AbstractLogWindow (QString const& settings_key, QSettings * settings + , Configuration const * configuration + , QWidget * parent) + : QWidget {parent} + , m_ {settings_key, settings, configuration} +{ + // ensure view scrolls to latest new row + connect (&m_->model_, &QAbstractItemModel::rowsInserted, [this] (QModelIndex const& /*parent*/, int /*first*/, int /*last*/) { + if (m_->log_view_) m_->log_view_->scrollToBottom (); + }); +} + +AbstractLogWindow::~AbstractLogWindow () +{ + SettingsGroup g {m_->settings_, m_->settings_key_}; + m_->settings_->setValue ("window/geometry", saveGeometry ()); +} + +void AbstractLogWindow::set_log_model (QAbstractItemModel * log_model) +{ + m_->model_.setSourceModel (log_model); +} + +void AbstractLogWindow::set_log_view (QTableView * log_view) +{ + // do this here because we know the UI must be setup before this + SettingsGroup g {m_->settings_, m_->settings_key_}; + restoreGeometry (m_->settings_->value ("window/geometry").toByteArray ()); + + m_->log_view_ = log_view; + m_->log_view_->setModel (&m_->model_); + m_->log_view_->setColumnHidden (0, true); + auto horizontal_header = log_view->horizontalHeader (); + horizontal_header->setSectionResizeMode (QHeaderView::ResizeToContents); + horizontal_header->setSectionsMovable (true); + m_->log_view_->verticalHeader ()->setSectionResizeMode (QHeaderView::ResizeToContents); + set_log_view_font (m_->configuration_->decoded_text_font ()); + m_->log_view_->scrollToBottom (); +} + +void AbstractLogWindow::set_log_view_font (QFont const& font) +{ + // m_->log_view_->setFont (font); + // m_->log_view_->horizontalHeader ()->setFont (font); + // m_->log_view_->verticalHeader ()->setFont (font); + m_->model_.set_font (font); +} diff --git a/widgets/AbstractLogWindow.hpp b/widgets/AbstractLogWindow.hpp new file mode 100644 index 000000000..35d5d27cf --- /dev/null +++ b/widgets/AbstractLogWindow.hpp @@ -0,0 +1,32 @@ +#ifndef ABSTRACT_LOG_WINDOW_HPP_ +#define ABSTRACT_LOG_WINDOW_HPP_ + +#include +#include "pimpl_h.hpp" + +class QString; +class QSettings; +class Configuration; +class QAbstractItemModel; +class QTableView; +class QFont; + +class AbstractLogWindow + : public QWidget +{ +public: + AbstractLogWindow (QString const& settings_key, QSettings * settings + , Configuration const * configuration + , QWidget * parent = nullptr); + virtual ~AbstractLogWindow () = 0; + + void set_log_model (QAbstractItemModel *); + void set_log_view (QTableView *); + void set_log_view_font (QFont const&); + +private: + class impl; + pimpl m_; +}; + +#endif diff --git a/widgets/CabrilloLogWindow.cpp b/widgets/CabrilloLogWindow.cpp index 4a86b4509..ab83a79f2 100644 --- a/widgets/CabrilloLogWindow.cpp +++ b/widgets/CabrilloLogWindow.cpp @@ -1,77 +1,68 @@ #include "CabrilloLogWindow.hpp" -#include #include -#include -#include -#include -#include -#include - -#include "SettingsGroup.hpp" +#include #include "Configuration.hpp" #include "models/Bands.hpp" #include "item_delegates/ForeignKeyDelegate.hpp" #include "item_delegates/DateTimeAsSecsSinceEpochDelegate.hpp" #include "item_delegates/CallsignDelegate.hpp" -#include "item_delegates/MaidenheadLocatorDelegate.hpp" -#include "widgets/MessageBox.hpp" -#include "qt_helpers.hpp" +#include "pimpl_impl.hpp" #include "ui_CabrilloLogWindow.h" +namespace +{ + class FormatProxyModel final + : public QIdentityProxyModel + { + public: + explicit FormatProxyModel (QObject * parent = nullptr) + : QIdentityProxyModel {parent} + { + } + + QVariant data (QModelIndex const& index, int role) const override + { + if (Qt::TextAlignmentRole == role && index.isValid ()) + { + switch (index.column ()) + { + case 1: + case 6: + return Qt::AlignRight + Qt::AlignVCenter; + default: + break; + } + } + return QIdentityProxyModel::data (index, role); + } + }; +} + +class CabrilloLogWindow::impl final +{ +public: + explicit impl () = default; + FormatProxyModel format_model_; + Ui::CabrilloLogWindow ui_; +}; + CabrilloLogWindow::CabrilloLogWindow (QSettings * settings, Configuration const * configuration , QAbstractItemModel * cabrillo_log_model, QWidget * parent) - : QWidget {parent} - , settings_ {settings} - , configuration_ {configuration} - , ui_ {new Ui::CabrilloLogWindow} + : AbstractLogWindow {"Cabrillo Log Window", settings, configuration, parent} { - cabrillo_log_model_.setSourceModel (cabrillo_log_model); setWindowTitle (QApplication::applicationName () + " - Cabrillo Log"); - ui_->setupUi (this); - read_settings (); - change_font (configuration_->decoded_text_font ()); - ui_->log_table_view->setModel (&cabrillo_log_model_); - ui_->log_table_view->setColumnHidden (0, true); - ui_->log_table_view->setItemDelegateForColumn (2, new DateTimeAsSecsSinceEpochDelegate {this}); - ui_->log_table_view->setItemDelegateForColumn (3, new CallsignDelegate {this}); - ui_->log_table_view->setItemDelegateForColumn (6, new ForeignKeyDelegate {configuration_->bands (), &cabrillo_log_model_, 0, 6, this}); - ui_->log_table_view->setSelectionMode (QTableView::SingleSelection); - auto horizontal_header = ui_->log_table_view->horizontalHeader (); - horizontal_header->setStretchLastSection (true); - horizontal_header->setSectionResizeMode (QHeaderView::ResizeToContents); - horizontal_header->setSectionsMovable (true); - horizontal_header->moveSection (6, 1); // band to first column - ui_->log_table_view->scrollToBottom (); - - // ensure view scrolls to latest new row - connect (&cabrillo_log_model_, &QAbstractItemModel::rowsInserted, [this] (QModelIndex const& /*parent*/, int /*first*/, int /*last*/) { - ui_->log_table_view->scrollToBottom (); - }); + m_->ui_.setupUi (this); + m_->format_model_.setSourceModel (cabrillo_log_model); + set_log_model (&m_->format_model_); + set_log_view (m_->ui_.log_table_view); + m_->ui_.log_table_view->setItemDelegateForColumn (2, new DateTimeAsSecsSinceEpochDelegate {this}); + m_->ui_.log_table_view->setItemDelegateForColumn (3, new CallsignDelegate {this}); + m_->ui_.log_table_view->setItemDelegateForColumn (6, new ForeignKeyDelegate {configuration->bands (), cabrillo_log_model, 0, 6, this}); + m_->ui_.log_table_view->horizontalHeader ()->moveSection (6, 1); // band to first column } CabrilloLogWindow::~CabrilloLogWindow () { - write_settings (); -} - -void CabrilloLogWindow::read_settings () -{ - SettingsGroup g {settings_, "Cabrillo Log Window"}; - restoreGeometry (settings_->value ("window/geometery").toByteArray ()); -} - -void CabrilloLogWindow::write_settings () const -{ - SettingsGroup g {settings_, "Cabrillo Log Window"}; - settings_->setValue ("window/geometery", saveGeometry ()); -} - -void CabrilloLogWindow::change_font (QFont const& font) -{ - // ui_->log_table_view->setFont (font); - // ui_->log_table_view->horizontalHeader ()->setFont (font); - // ui_->log_table_view->verticalHeader ()->setFont (font); - cabrillo_log_model_.set_font (font); } diff --git a/widgets/CabrilloLogWindow.hpp b/widgets/CabrilloLogWindow.hpp index 9a352ce9d..c0a964ce5 100644 --- a/widgets/CabrilloLogWindow.hpp +++ b/widgets/CabrilloLogWindow.hpp @@ -1,39 +1,25 @@ #ifndef CABRILLO_LOG_WINDOW_HPP_ #define CABRILLO_LOG_WINDOW_HPP_ -#include -#include -#include -#include "models/FontOverrideModel.hpp" +#include "AbstractLogWindow.hpp" +#include "pimpl_h.hpp" class QSettings; class Configuration; class QFont; -class QDateTime; class QAbstractItemModel; -namespace Ui -{ - class CabrilloLogWindow; -} class CabrilloLogWindow final - : public QWidget + : public AbstractLogWindow { public: explicit CabrilloLogWindow (QSettings *, Configuration const *, QAbstractItemModel * cabrillo_log_model - , QWidget * parent = nullptr); + , QWidget * parent = nullptr); ~CabrilloLogWindow (); - void change_font (QFont const&); - private: - void read_settings (); - void write_settings () const; - - QSettings * settings_; - Configuration const * configuration_; - FontOverrideModel cabrillo_log_model_; - QScopedPointer ui_; + class impl; + pimpl m_; }; #endif diff --git a/widgets/CabrilloLogWindow.ui b/widgets/CabrilloLogWindow.ui index eb25d1a6b..43061f132 100644 --- a/widgets/CabrilloLogWindow.ui +++ b/widgets/CabrilloLogWindow.ui @@ -2,12 +2,30 @@ CabrilloLogWindow + + + 0 + 0 + 274 + 210 + + Contest Log - + + + true + + + QAbstractItemView::SingleSelection + + + true + + diff --git a/widgets/FoxLogWindow.cpp b/widgets/FoxLogWindow.cpp index 252045359..f5e7e517d 100644 --- a/widgets/FoxLogWindow.cpp +++ b/widgets/FoxLogWindow.cpp @@ -1,12 +1,6 @@ #include "FoxLogWindow.hpp" -#include #include -#include -#include -#include -#include -#include #include "SettingsGroup.hpp" #include "Configuration.hpp" @@ -15,82 +9,50 @@ #include "item_delegates/DateTimeAsSecsSinceEpochDelegate.hpp" #include "item_delegates/CallsignDelegate.hpp" #include "item_delegates/MaidenheadLocatorDelegate.hpp" -#include "widgets/MessageBox.hpp" -#include "qt_helpers.hpp" +#include "pimpl_impl.hpp" #include "ui_FoxLogWindow.h" +class FoxLogWindow::impl final +{ +public: + explicit impl () = default; + Ui::FoxLogWindow ui_; +}; + FoxLogWindow::FoxLogWindow (QSettings * settings, Configuration const * configuration , QAbstractItemModel * fox_log_model, QWidget * parent) - : QWidget {parent} - , settings_ {settings} - , configuration_ {configuration} - , ui_ {new Ui::FoxLogWindow} + : AbstractLogWindow {"Fox Log Window", settings, configuration, parent} { - fox_log_model_.setSourceModel (fox_log_model); setWindowTitle (QApplication::applicationName () + " - Fox Log"); - ui_->setupUi (this); - read_settings (); - change_font (configuration_->decoded_text_font ()); - ui_->log_table_view->setModel (&fox_log_model_); - ui_->log_table_view->setColumnHidden (0, true); - ui_->log_table_view->setItemDelegateForColumn (1, new DateTimeAsSecsSinceEpochDelegate {this}); - ui_->log_table_view->setItemDelegateForColumn (2, new CallsignDelegate {this}); - ui_->log_table_view->setItemDelegateForColumn (3, new MaidenheadLocatorDelegate {this}); - ui_->log_table_view->setItemDelegateForColumn (6, new ForeignKeyDelegate {configuration_->bands (), &fox_log_model_, 0, 6, this}); - ui_->log_table_view->setSelectionMode (QTableView::SingleSelection); - auto horizontal_header = ui_->log_table_view->horizontalHeader (); - horizontal_header->setStretchLastSection (true); - horizontal_header->setSectionResizeMode (QHeaderView::ResizeToContents); - horizontal_header->setSectionsMovable (true); - horizontal_header->moveSection (6, 1); // move band to first column - ui_->rate_label->setNum (0); - ui_->queued_label->setNum (0); - ui_->callers_label->setNum (0); - ui_->log_table_view->scrollToBottom (); - - // ensure view scrolls to latest new row - connect (&fox_log_model_, &QAbstractItemModel::rowsInserted, [this] (QModelIndex const& /*parent*/, int /*first*/, int /*last*/) { - ui_->log_table_view->scrollToBottom (); - }); + m_->ui_.setupUi (this); + set_log_model (fox_log_model); + set_log_view (m_->ui_.log_table_view); + m_->ui_.log_table_view->setItemDelegateForColumn (1, new DateTimeAsSecsSinceEpochDelegate {this}); + m_->ui_.log_table_view->setItemDelegateForColumn (2, new CallsignDelegate {this}); + m_->ui_.log_table_view->setItemDelegateForColumn (3, new MaidenheadLocatorDelegate {this}); + m_->ui_.log_table_view->setItemDelegateForColumn (6, new ForeignKeyDelegate {configuration->bands (), fox_log_model, 0, 6, this}); + m_->ui_.log_table_view->horizontalHeader ()->moveSection (6, 1); // move band to first column + m_->ui_.rate_label->setNum (0); + m_->ui_.queued_label->setNum (0); + m_->ui_.callers_label->setNum (0); } FoxLogWindow::~FoxLogWindow () { - write_settings (); -} - -void FoxLogWindow::read_settings () -{ - SettingsGroup g {settings_, "Fox Log Window"}; - restoreGeometry (settings_->value ("window/geometery").toByteArray ()); -} - -void FoxLogWindow::write_settings () const -{ - SettingsGroup g {settings_, "Fox Log Window"}; - settings_->setValue ("window/geometery", saveGeometry ()); -} - -void FoxLogWindow::change_font (QFont const& font) -{ - // ui_->log_table_view->setFont (font); - // ui_->log_table_view->horizontalHeader ()->setFont (font); - // ui_->log_table_view->verticalHeader ()->setFont (font); - fox_log_model_.set_font (font); } void FoxLogWindow::callers (int n) { - ui_->callers_label->setNum (n); + m_->ui_.callers_label->setNum (n); } void FoxLogWindow::queued (int n) { - ui_->queued_label->setNum (n); + m_->ui_.queued_label->setNum (n); } void FoxLogWindow::rate (int n) { - ui_->rate_label->setNum (n); + m_->ui_.rate_label->setNum (n); } diff --git a/widgets/FoxLogWindow.hpp b/widgets/FoxLogWindow.hpp index 62895a763..d27ccdea6 100644 --- a/widgets/FoxLogWindow.hpp +++ b/widgets/FoxLogWindow.hpp @@ -1,42 +1,29 @@ #ifndef FOX_LOG_WINDOW_HPP_ #define FOX_LOG_WINDOW_HPP_ -#include -#include -#include -#include "models/FontOverrideModel.hpp" +#include "AbstractLogWindow.hpp" +#include "pimpl_h.hpp" class QSettings; class Configuration; class QFont; -class QDateTime; class QAbstractItemModel; -namespace Ui -{ - class FoxLogWindow; -} class FoxLogWindow final - : public QWidget + : public AbstractLogWindow { public: explicit FoxLogWindow (QSettings *, Configuration const *, QAbstractItemModel * fox_log_model , QWidget * parent = nullptr); ~FoxLogWindow (); - void change_font (QFont const&); void callers (int); void queued (int); void rate (int); private: - void read_settings (); - void write_settings () const; - - QSettings * settings_; - Configuration const * configuration_; - FontOverrideModel fox_log_model_; - QScopedPointer ui_; + class impl; + pimpl m_; }; #endif diff --git a/widgets/FoxLogWindow.ui b/widgets/FoxLogWindow.ui index 2a3e84aba..96ef8b112 100644 --- a/widgets/FoxLogWindow.ui +++ b/widgets/FoxLogWindow.ui @@ -2,12 +2,30 @@ FoxLogWindow + + + 0 + 0 + 331 + 238 + + Fox Log - + + + true + + + QAbstractItemView::SingleSelection + + + true + + diff --git a/widgets/logqso.cpp b/widgets/logqso.cpp index 77324e52b..b6412cb59 100644 --- a/widgets/logqso.cpp +++ b/widgets/logqso.cpp @@ -10,6 +10,7 @@ #include "MessageBox.hpp" #include "Configuration.hpp" #include "models/Bands.hpp" +#include "models/CabrilloLog.hpp" #include "validators/MaidenheadLocatorValidator.hpp" #include "ui_logqso.h" @@ -57,11 +58,10 @@ void LogQSO::storeSettings () const void LogQSO::initLogQSO(QString const& hisCall, QString const& hisGrid, QString mode, QString const& rptSent, QString const& rptRcvd, QDateTime const& dateTimeOn, QDateTime const& dateTimeOff, - Radio::Frequency dialFreq, bool noSuffix, QString xSent, QString xRcvd) + Radio::Frequency dialFreq, bool noSuffix, QString xSent, QString xRcvd, + CabrilloLog * cabrillo_log) { if(!isHidden()) return; - m_xSent=xSent; - m_xRcvd=xRcvd; ui->call->setText(hisCall); ui->grid->setText(hisGrid); ui->name->setText(""); @@ -87,17 +87,23 @@ void LogQSO::initLogQSO(QString const& hisCall, QString const& hisGrid, QString m_myGrid=m_config->my_grid(); ui->band->setText (m_config->bands ()->find (dialFreq)); ui->loggedOperator->setText(m_config->opCall()); - ui->exchSent->setText(m_xSent); - ui->exchRcvd->setText(m_xRcvd); + ui->exchSent->setText (xSent); + ui->exchRcvd->setText (xRcvd); + m_cabrilloLog = cabrillo_log; using SpOp = Configuration::SpecialOperatingActivity; - if( SpOp::FOX == m_config->special_op_id() or - (m_config->autoLog() and SpOp::NONE < m_config->special_op_id() and - m_xSent!="" and m_xRcvd!="")) { - accept(); - } else { - show(); - } + auto special_op = m_config->special_op_id (); + if (SpOp::FOX == special_op + || (m_config->autoLog () + && SpOp::NONE < special_op && special_op < SpOp::FOX)) + { + // allow auto logging in Fox mode and contests + accept(); + } + else + { + show(); + } } void LogQSO::accept() @@ -120,6 +126,29 @@ void LogQSO::accept() QString strDialFreq(QString::number(m_dialFreq / 1.e6,'f',6)); operator_call = ui->loggedOperator->text(); + // validate + using SpOp = Configuration::SpecialOperatingActivity; + auto special_op = m_config->special_op_id (); + if (SpOp::NONE < special_op && special_op < SpOp::FOX) + { + if (ui->exchSent->text ().isEmpty () || ui->exchRcvd->text ().isEmpty ()) + { + show (); + MessageBox::warning_message (this, tr ("Invalid QSO Data"), + tr ("Check exchange sent and received")); + return; // without accepting + } + + if (!m_cabrilloLog->add_QSO (m_dialFreq, QDateTime::currentDateTimeUtc (), hisCall, + ui->exchSent->text (), ui->exchRcvd->text ())) + { + show (); + MessageBox::warning_message (this, tr ("Invalid QSO Data"), + tr ("Check all fields")); + return; // without accepting + } + } + //Log this QSO to file "wsjtx.log" static QFile f {QDir {QStandardPaths::writableLocation (QStandardPaths::DataLocation)}.absoluteFilePath ("wsjtx.log")}; if(!f.open(QIODevice::Text | QIODevice::Append)) { @@ -169,8 +198,8 @@ void LogQSO::accept() , m_myGrid , m_txPower , operator_call - , m_xSent - , m_xRcvd)); + , ui->exchSent->text () + , ui->exchRcvd->text ())); QDialog::accept(); } diff --git a/widgets/logqso.h b/widgets/logqso.h index 2f2e4c29e..b0e703a93 100644 --- a/widgets/logqso.h +++ b/widgets/logqso.h @@ -17,6 +17,7 @@ namespace Ui { class QSettings; class Configuration; class QByteArray; +class CabrilloLog; class LogQSO : public QDialog { @@ -28,7 +29,7 @@ public: void initLogQSO(QString const& hisCall, QString const& hisGrid, QString mode, QString const& rptSent, QString const& rptRcvd, QDateTime const& dateTimeOn, QDateTime const& dateTimeOff, Radio::Frequency dialFreq, - bool noSuffix, QString xSent, QString xRcvd); + bool noSuffix, QString xSent, QString xRcvd, CabrilloLog *); public slots: void accept(); @@ -56,10 +57,9 @@ private: Radio::Frequency m_dialFreq; QString m_myCall; QString m_myGrid; - QString m_xSent; - QString m_xRcvd; QDateTime m_dateTimeOn; QDateTime m_dateTimeOff; + CabrilloLog * m_cabrilloLog; }; #endif // LogQSO_H diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index 186f5f40c..c1a09c227 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -1228,10 +1228,10 @@ void MainWindow::setDecodedTextFont (QFont const& font) m_msgAvgWidget->changeFont (font); } if (m_foxLogWindow) { - m_foxLogWindow->change_font (font); + m_foxLogWindow->set_log_view_font (font); } if (m_contestLogWindow) { - m_contestLogWindow->change_font (font); + m_contestLogWindow->set_log_view_font (font); } updateGeometry (); } @@ -5331,9 +5331,16 @@ void MainWindow::on_logQSOButton_clicked() //Log QSO button default: break; } + using SpOp = Configuration::SpecialOperatingActivity; + auto special_op = m_config.special_op_id (); + if (SpecOp::NONE < special_op && special_op < SpecOp::FOX) + { + if (!m_cabrilloLog) m_cabrilloLog.reset (new CabrilloLog {&m_config}); + } m_logDlg->initLogQSO (m_hisCall, grid, m_modeTx, m_rptSent, m_rptRcvd, m_dateTimeQSOOn, dateTimeQSOOff, m_freqNominal + - ui->TxFreqSpinBox->value(), m_noSuffix, m_xSent, m_xRcvd); + ui->TxFreqSpinBox->value(), m_noSuffix, m_xSent, m_xRcvd, + m_cabrilloLog.data ()); } void MainWindow::acceptQSO (QDateTime const& QSO_date_off, QString const& call, QString const& grid @@ -5350,15 +5357,6 @@ void MainWindow::acceptQSO (QDateTime const& QSO_date_off, QString const& call, tr ("Cannot open \"%1\"").arg (m_logBook.path ())); } - - if (SpecOp::NONE < m_config.special_op_id() && SpecOp::FOX > m_config.special_op_id()) { - if (!m_cabrilloLog) m_cabrilloLog.reset (new CabrilloLog {&m_config}); - m_cabrilloLog->add_QSO (m_freqNominal, QDateTime::currentDateTimeUtc (), m_hisCall, m_xSent, m_xRcvd); - m_xSent=""; - m_xRcvd=""; - ui->sbSerialNumber->setValue (ui->sbSerialNumber->value () + 1); - } - m_messageClient->qso_logged (QSO_date_off, call, grid, dial_freq, mode, rpt_sent, rpt_received , tx_power, comments, name, QSO_date_on, operator_call, my_call, my_grid); m_messageClient->logged_ADIF (ADIF); @@ -5378,6 +5376,15 @@ void MainWindow::acceptQSO (QDateTime const& QSO_date_off, QString const& call, if (m_config.clear_DX () and SpecOp::HOUND != m_config.special_op_id()) clearDX (); m_dateTimeQSOOn = QDateTime {}; + using SpOp = Configuration::SpecialOperatingActivity; + auto special_op = m_config.special_op_id (); + if (SpecOp::NONE < special_op && special_op < SpecOp::FOX) + { + ui->sbSerialNumber->setValue (ui->sbSerialNumber->value () + 1); + } + + m_xSent.clear (); + m_xRcvd.clear (); } qint64 MainWindow::nWidgets(QString t) @@ -6125,11 +6132,12 @@ void MainWindow::on_reset_fox_log_action_triggered () void MainWindow::on_reset_cabrillo_log_action_triggered () { - if (MessageBox::Yes == MessageBox::query_message(this, tr("Confirm Erase"), - tr("Are you sure you want to erase file cabrillo.log" - " and start a new Cabrillo log?"))) + if (MessageBox::Yes == MessageBox::query_message (this, tr ("Confirm Reset"), + tr ("Are you sure you want to erase your contest log?"), + tr ("Doing this will remove all QSO records for the current contest. " + "They will be kept in the ADIF log file but will not be available " + "for export in your Cabrillo log."))) { - QFile {m_config.writeable_data_dir ().absoluteFilePath ("cabrillo.log")}.remove (); ui->sbSerialNumber->setValue (1); if (!m_cabrilloLog) m_cabrilloLog.reset (new CabrilloLog {&m_config}); m_cabrilloLog->reset (); diff --git a/widgets/widgets.pri b/widgets/widgets.pri index 019fdcd17..e70c5cb9e 100644 --- a/widgets/widgets.pri +++ b/widgets/widgets.pri @@ -7,7 +7,8 @@ SOURCES += \ widgets/echoplot.cpp widgets/echograph.cpp widgets/fastgraph.cpp \ widgets/fastplot.cpp widgets/MessageBox.cpp \ widgets/colorhighlighting.cpp widgets/ExportCabrillo.cpp \ - widgets/CabrilloLogWindow.cpp + widgets/AbstractLogWindow.cpp \ + widgets/FoxLogWindow.cpp widgets/CabrilloLogWindow.cpp HEADERS += \ widgets/mainwindow.h widgets/plotter.h \ @@ -17,8 +18,8 @@ HEADERS += \ widgets/meterwidget.h widgets/messageaveraging.h \ widgets/echoplot.h widgets/echograph.h widgets/fastgraph.h \ widgets/fastplot.h widgets/MessageBox.hpp widgets/colorhighlighting.h \ - widgets/ExportCabrillo.h \ - widgets/CabrilloLogWindow.cpp + widgets/ExportCabrillo.h widgets/AbstractLogWindow.hpp \ + widgets/FoxLogWindow.cpp widgets/CabrilloLogWindow.cpp FORMS += \ widgets/mainwindow.ui widgets/about.ui \ @@ -26,5 +27,4 @@ FORMS += \ widgets/logqso.ui widgets/messageaveraging.ui \ widgets/echograph.ui widgets/fastgraph.ui \ widgets/colorhighlighting.ui widgets/ExportCabrillo.ui \ - widgets/FoxLogWindow.ui \ - widgets/CabrilloLogWindow.ui + widgets/FoxLogWindow.ui widgets/CabrilloLogWindow.ui