Add Fox log ADIF export to the Fox Log window log table contextual pop up menu

This commit is contained in:
Bill Somerville 2018-12-30 12:35:41 +00:00
parent db5c9e1fe9
commit 12299957d7
5 changed files with 114 additions and 19 deletions

View File

@ -9,7 +9,9 @@
#include <QSqlRecord> #include <QSqlRecord>
#include <QSqlError> #include <QSqlError>
#include <QSqlQuery> #include <QSqlQuery>
#include <QTextStream>
#include <QDebug> #include <QDebug>
#include "Configuration.hpp"
#include "qt_db_helpers.hpp" #include "qt_db_helpers.hpp"
#include "pimpl_impl.hpp" #include "pimpl_impl.hpp"
@ -17,12 +19,15 @@ class FoxLog::impl final
: public QSqlTableModel : public QSqlTableModel
{ {
public: public:
impl (); impl (Configuration const * configuration);
Configuration const * configuration_;
QSqlQuery mutable dupe_query_; QSqlQuery mutable dupe_query_;
QSqlQuery mutable export_query_;
}; };
FoxLog::impl::impl () FoxLog::impl::impl (Configuration const * configuration)
: configuration_ {configuration}
{ {
if (!database ().tables ().contains ("fox_log")) if (!database ().tables ().contains ("fox_log"))
{ {
@ -43,6 +48,9 @@ FoxLog::impl::impl ()
SQL_error_check (dupe_query_, &QSqlQuery::prepare, SQL_error_check (dupe_query_, &QSqlQuery::prepare,
"SELECT COUNT(*) FROM fox_log WHERE call = :call AND band = :band"); "SELECT COUNT(*) FROM fox_log WHERE call = :call AND band = :band");
SQL_error_check (export_query_, &QSqlQuery::prepare,
"SELECT band, \"when\", call, grid, report_sent, report_rcvd FROM fox_log ORDER BY \"when\"");
setEditStrategy (QSqlTableModel::OnFieldChange); setEditStrategy (QSqlTableModel::OnFieldChange);
setTable ("fox_log"); setTable ("fox_log");
setHeaderData (fieldIndex ("when"), Qt::Horizontal, tr ("Date & Time(UTC)")); setHeaderData (fieldIndex ("when"), Qt::Horizontal, tr ("Date & Time(UTC)"));
@ -60,7 +68,8 @@ FoxLog::impl::impl ()
SQL_error_check (*this, &QSqlTableModel::select); SQL_error_check (*this, &QSqlTableModel::select);
} }
FoxLog::FoxLog () FoxLog::FoxLog (Configuration const * configuration)
: m_ {configuration}
{ {
} }
@ -142,3 +151,59 @@ void FoxLog::reset ()
m_->setEditStrategy (QSqlTableModel::OnFieldChange); m_->setEditStrategy (QSqlTableModel::OnFieldChange);
} }
} }
namespace
{
struct ADIF_field
{
explicit ADIF_field (QString const& name, QString const& value)
: name_ {name}
, value_ {value}
{
}
QString name_;
QString value_;
};
QTextStream& operator << (QTextStream& os, ADIF_field const& field)
{
if (field.value_.size ())
{
os << QString {"<%1:%2>%3 "}.arg (field.name_).arg (field.value_.size ()).arg (field.value_);
}
return os;
}
}
void FoxLog::export_qsos (QTextStream& out) const
{
out << "WSJT-X FT8 DXpedition Mode Fox Log\n<eoh>";
SQL_error_check (m_->export_query_, static_cast<bool (QSqlQuery::*) ()> (&QSqlQuery::exec));
auto record = m_->export_query_.record ();
auto band_index = record.indexOf ("band");
auto when_index = record.indexOf ("when");
auto call_index = record.indexOf ("call");
auto grid_index = record.indexOf ("grid");
auto sent_index = record.indexOf ("report_sent");
auto rcvd_index = record.indexOf ("report_rcvd");
while (m_->export_query_.next ())
{
auto when = QDateTime::fromMSecsSinceEpoch (m_->export_query_.value (when_index).toULongLong () * 1000ull, Qt::UTC);
out << '\n'
<< ADIF_field {"band", m_->export_query_.value (band_index).toString ()}
<< ADIF_field {"mode", "FT8"}
<< ADIF_field {"qso_date", when.toString ("yyyyMMdd")}
<< ADIF_field {"time_on", when.toString ("hhmmss")}
<< ADIF_field {"call", m_->export_query_.value (call_index).toString ()}
<< ADIF_field {"gridsquare", m_->export_query_.value (grid_index).toString ()}
<< ADIF_field {"rst_sent", m_->export_query_.value (sent_index).toString ()}
<< ADIF_field {"rst_rcvd", m_->export_query_.value (rcvd_index).toString ()}
<< ADIF_field {"station_callsign", m_->configuration_->my_callsign ()}
<< ADIF_field {"my_gridsquare", m_->configuration_->my_grid ()}
<< ADIF_field {"operator", m_->configuration_->opCall ()}
<< "<eor>";
}
out << endl;
}

View File

@ -7,12 +7,14 @@
class QDateTime; class QDateTime;
class QString; class QString;
class QSqlTableModel; class QSqlTableModel;
class QTextStream;
class Configuration;
class FoxLog final class FoxLog final
: private boost::noncopyable : private boost::noncopyable
{ {
public: public:
explicit FoxLog (); explicit FoxLog (Configuration const *);
~FoxLog (); ~FoxLog ();
// returns false if insert fails, dupe call+band // returns false if insert fails, dupe call+band
@ -23,6 +25,7 @@ public:
QSqlTableModel * model (); QSqlTableModel * model ();
void reset (); void reset ();
void export_qsos (QTextStream&) const;
private: private:
class impl; class impl;

View File

@ -1,15 +1,17 @@
#include "FoxLogWindow.hpp" #include "FoxLogWindow.hpp"
#include <QApplication> #include <QApplication>
#include <QSqlTableModel>
#include <QAction> #include <QAction>
#include <QFile> #include <QFile>
#include <QDir> #include <QDir>
#include <QSqlTableModel>
#include <QFileDialog>
#include "SettingsGroup.hpp" #include "SettingsGroup.hpp"
#include "Configuration.hpp" #include "Configuration.hpp"
#include "MessageBox.hpp" #include "MessageBox.hpp"
#include "models/Bands.hpp" #include "models/Bands.hpp"
#include "models/FoxLog.hpp"
#include "item_delegates/ForeignKeyDelegate.hpp" #include "item_delegates/ForeignKeyDelegate.hpp"
#include "item_delegates/DateTimeAsSecsSinceEpochDelegate.hpp" #include "item_delegates/DateTimeAsSecsSinceEpochDelegate.hpp"
#include "item_delegates/CallsignDelegate.hpp" #include "item_delegates/CallsignDelegate.hpp"
@ -22,23 +24,23 @@
class FoxLogWindow::impl final class FoxLogWindow::impl final
{ {
public: public:
explicit impl (QSqlTableModel * log_model) explicit impl (FoxLog * log)
: log_model_ {log_model} : log_ {log}
{ {
} }
QSqlTableModel * log_model_; FoxLog * log_;
Ui::FoxLogWindow ui_; Ui::FoxLogWindow ui_;
}; };
FoxLogWindow::FoxLogWindow (QSettings * settings, Configuration const * configuration FoxLogWindow::FoxLogWindow (QSettings * settings, Configuration const * configuration
, QSqlTableModel * fox_log_model, QWidget * parent) , FoxLog * fox_log, QWidget * parent)
: AbstractLogWindow {"Fox Log Window", settings, configuration, parent} : AbstractLogWindow {"Fox Log Window", settings, configuration, parent}
, m_ {fox_log_model} , m_ {fox_log}
{ {
setWindowTitle (QApplication::applicationName () + " - Fox Log"); setWindowTitle (QApplication::applicationName () + " - Fox Log");
m_->ui_.setupUi (this); m_->ui_.setupUi (this);
m_->ui_.log_table_view->setModel (m_->log_model_); m_->ui_.log_table_view->setModel (m_->log_->model ());
set_log_view (m_->ui_.log_table_view); set_log_view (m_->ui_.log_table_view);
m_->ui_.log_table_view->setItemDelegateForColumn (1, new DateTimeAsSecsSinceEpochDelegate {this}); 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 (2, new CallsignDelegate {this});
@ -50,6 +52,31 @@ FoxLogWindow::FoxLogWindow (QSettings * settings, Configuration const * configur
m_->ui_.callers_label->setNum (0); m_->ui_.callers_label->setNum (0);
// actions // actions
auto export_action = new QAction {tr ("&Export ADIF ..."), m_->ui_.log_table_view};
m_->ui_.log_table_view->insertAction (nullptr, export_action);
connect (export_action, &QAction::triggered, [this, configuration] (bool /*checked*/) {
auto file_name = QFileDialog::getSaveFileName (this
, tr ("Export ADIF Log File")
, configuration->writeable_data_dir ().absolutePath ()
, tr ("ADIF Log (*.adi)"));
if (file_name.size () && m_->log_)
{
QFile ADIF_file {file_name};
if (ADIF_file.open (QIODevice::WriteOnly | QIODevice::Text))
{
QTextStream output_stream {&ADIF_file};
m_->log_->export_qsos (output_stream);
}
else
{
MessageBox::warning_message (this
, tr ("Export ADIF File Error")
, tr ("Cannot open \"%1\" for writing: %2")
.arg (ADIF_file.fileName ()).arg (ADIF_file.errorString ()));
}
}
});
auto reset_action = new QAction {tr ("&Reset ..."), m_->ui_.log_table_view}; auto reset_action = new QAction {tr ("&Reset ..."), m_->ui_.log_table_view};
m_->ui_.log_table_view->insertAction (nullptr, reset_action); m_->ui_.log_table_view->insertAction (nullptr, reset_action);
connect (reset_action, &QAction::triggered, [this, configuration] (bool /*checked*/) { connect (reset_action, &QAction::triggered, [this, configuration] (bool /*checked*/) {
@ -88,10 +115,10 @@ void FoxLogWindow::log_model_changed (int row)
{ {
if (row >= 0) if (row >= 0)
{ {
m_->log_model_->selectRow (row); m_->log_->model ()->selectRow (row);
} }
else else
{ {
m_->log_model_->select (); m_->log_->model ()->select ();
} }
} }

View File

@ -7,7 +7,7 @@
class QSettings; class QSettings;
class Configuration; class Configuration;
class QFont; class QFont;
class QSqlTableModel; class FoxLog;
class FoxLogWindow final class FoxLogWindow final
: public AbstractLogWindow : public AbstractLogWindow
@ -15,7 +15,7 @@ class FoxLogWindow final
Q_OBJECT Q_OBJECT
public: public:
explicit FoxLogWindow (QSettings *, Configuration const *, QSqlTableModel * fox_log_model explicit FoxLogWindow (QSettings *, Configuration const *, FoxLog * fox_log
, QWidget * parent = nullptr); , QWidget * parent = nullptr);
~FoxLogWindow (); ~FoxLogWindow ();

View File

@ -2453,15 +2453,15 @@ void MainWindow::on_actionAstronomical_data_toggled (bool checked)
void MainWindow::on_fox_log_action_triggered() void MainWindow::on_fox_log_action_triggered()
{ {
if (!m_foxLog) m_foxLog.reset (new FoxLog); if (!m_foxLog) m_foxLog.reset (new FoxLog {&m_config});
if (!m_foxLogWindow) if (!m_foxLogWindow)
{ {
m_foxLogWindow.reset (new FoxLogWindow {m_settings, &m_config, m_foxLog->model ()}); m_foxLogWindow.reset (new FoxLogWindow {m_settings, &m_config, m_foxLog.data ()});
// Connect signals from fox log window // Connect signals from fox log window
connect (this, &MainWindow::finished, m_foxLogWindow.data (), &FoxLogWindow::close); connect (this, &MainWindow::finished, m_foxLogWindow.data (), &FoxLogWindow::close);
connect (m_foxLogWindow.data (), &FoxLogWindow::reset_log_model, [this] () { connect (m_foxLogWindow.data (), &FoxLogWindow::reset_log_model, [this] () {
if (!m_foxLog) m_foxLog.reset (new FoxLog); if (!m_foxLog) m_foxLog.reset (new FoxLog {&m_config});
m_foxLog->reset (); m_foxLog->reset ();
}); });
} }
@ -8236,7 +8236,7 @@ list2Done:
m_hisGrid=m_foxQSO[hc1].grid; m_hisGrid=m_foxQSO[hc1].grid;
m_rptSent=m_foxQSO[hc1].sent; m_rptSent=m_foxQSO[hc1].sent;
m_rptRcvd=m_foxQSO[hc1].rcvd; m_rptRcvd=m_foxQSO[hc1].rcvd;
if (!m_foxLog) m_foxLog.reset (new FoxLog); if (!m_foxLog) m_foxLog.reset (new FoxLog {&m_config});
if (!m_foxLogWindow) on_fox_log_action_triggered (); if (!m_foxLogWindow) on_fox_log_action_triggered ();
if (m_foxLog->add_QSO (QSO_time, m_hisCall, m_hisGrid, m_rptSent, m_rptRcvd, m_lastBand)) if (m_foxLog->add_QSO (QSO_time, m_hisCall, m_hisGrid, m_rptSent, m_rptRcvd, m_lastBand))
{ {