2018-11-07 12:49:45 -05:00
|
|
|
#include "FoxLog.hpp"
|
|
|
|
|
2018-11-11 21:06:44 -05:00
|
|
|
#include <stdexcept>
|
|
|
|
#include <utility>
|
2018-11-07 18:55:15 -05:00
|
|
|
#include <QString>
|
2018-11-07 12:49:45 -05:00
|
|
|
#include <QDateTime>
|
|
|
|
#include <QSqlDatabase>
|
|
|
|
#include <QSqlTableModel>
|
|
|
|
#include <QSqlRecord>
|
|
|
|
#include <QSqlError>
|
|
|
|
#include <QSqlQuery>
|
|
|
|
#include <QDebug>
|
2018-11-11 21:06:44 -05:00
|
|
|
#include "qt_db_helpers.hpp"
|
2018-11-07 12:49:45 -05:00
|
|
|
#include "pimpl_impl.hpp"
|
|
|
|
|
|
|
|
class FoxLog::impl final
|
|
|
|
: public QSqlTableModel
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
impl ();
|
2018-11-11 21:06:44 -05:00
|
|
|
|
|
|
|
QSqlQuery mutable dupe_query_;
|
2018-11-07 12:49:45 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
FoxLog::impl::impl ()
|
|
|
|
{
|
|
|
|
if (!database ().tables ().contains ("fox_log"))
|
|
|
|
{
|
|
|
|
QSqlQuery query;
|
2018-11-11 21:06:44 -05:00
|
|
|
SQL_error_check (query, static_cast<bool (QSqlQuery::*) (QString const&)> (&QSqlQuery::exec),
|
|
|
|
"CREATE TABLE fox_log ("
|
|
|
|
" id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"
|
2018-11-07 12:49:45 -05:00
|
|
|
" \"when\" DATETIME NOT NULL,"
|
|
|
|
" call VARCHAR(20) NOT NULL,"
|
|
|
|
" grid VARCHAR(4),"
|
|
|
|
" report_sent VARCHAR(3),"
|
|
|
|
" report_rcvd VARCHAR(3),"
|
|
|
|
" band VARCHAR(6) NOT NULL,"
|
|
|
|
" CONSTRAINT no_dupes UNIQUE (call, band)"
|
2018-11-11 21:06:44 -05:00
|
|
|
")");
|
2018-11-07 12:49:45 -05:00
|
|
|
}
|
|
|
|
|
2018-11-11 21:06:44 -05:00
|
|
|
SQL_error_check (dupe_query_, &QSqlQuery::prepare,
|
|
|
|
"SELECT COUNT(*) FROM fox_log WHERE call = :call AND band = :band");
|
|
|
|
|
2018-12-01 21:30:32 -05:00
|
|
|
setEditStrategy (QSqlTableModel::OnFieldChange);
|
2018-11-07 12:49:45 -05:00
|
|
|
setTable ("fox_log");
|
2018-11-11 23:00:55 -05:00
|
|
|
setHeaderData (fieldIndex ("when"), Qt::Horizontal, tr ("Date & Time(UTC)"));
|
2018-11-07 12:49:45 -05:00
|
|
|
setHeaderData (fieldIndex ("call"), Qt::Horizontal, tr ("Call"));
|
|
|
|
setHeaderData (fieldIndex ("grid"), Qt::Horizontal, tr ("Grid"));
|
|
|
|
setHeaderData (fieldIndex ("report_sent"), Qt::Horizontal, tr ("Sent"));
|
|
|
|
setHeaderData (fieldIndex ("report_rcvd"), Qt::Horizontal, tr ("Rcvd"));
|
|
|
|
setHeaderData (fieldIndex ("band"), Qt::Horizontal, tr ("Band"));
|
2018-12-06 00:41:16 -05:00
|
|
|
|
|
|
|
// This descending order by time is important, it makes the view
|
|
|
|
// place the latest row at the top, without this the model/view
|
|
|
|
// interactions are both sluggish and unhelpful.
|
|
|
|
setSort (fieldIndex ("when"), Qt::DescendingOrder);
|
|
|
|
|
2018-11-11 21:06:44 -05:00
|
|
|
SQL_error_check (*this, &QSqlTableModel::select);
|
2018-11-07 12:49:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
FoxLog::FoxLog ()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
FoxLog::~FoxLog ()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-11-25 17:19:41 -05:00
|
|
|
QSqlTableModel * FoxLog::model ()
|
2018-11-07 12:49:45 -05:00
|
|
|
{
|
|
|
|
return &*m_;
|
|
|
|
}
|
|
|
|
|
2018-11-11 21:06:44 -05:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-07 12:49:45 -05:00
|
|
|
bool FoxLog::add_QSO (QDateTime const& when, QString const& call, QString const& grid
|
2018-11-12 13:26:05 -05:00
|
|
|
, QString const& report_sent, QString const& report_received
|
2018-11-07 12:49:45 -05:00
|
|
|
, QString const& band)
|
|
|
|
{
|
|
|
|
auto record = m_->record ();
|
2018-11-22 20:18:39 -05:00
|
|
|
if (!when.isNull ())
|
|
|
|
{
|
|
|
|
record.setValue ("when", when.toMSecsSinceEpoch () / 1000);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
record.setNull ("when");
|
|
|
|
}
|
|
|
|
set_value_maybe_null (record, "call", call);
|
2018-11-11 21:06:44 -05:00
|
|
|
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);
|
2018-11-22 20:18:39 -05:00
|
|
|
set_value_maybe_null (record, "band", band);
|
2018-12-01 21:30:32 -05:00
|
|
|
if (m_->isDirty ())
|
|
|
|
{
|
|
|
|
m_->revert (); // discard any uncommitted changes
|
|
|
|
}
|
2018-12-06 00:41:16 -05:00
|
|
|
m_->setEditStrategy (QSqlTableModel::OnManualSubmit);
|
|
|
|
ConditionalTransaction transaction {*m_};
|
2018-11-25 17:19:41 -05:00
|
|
|
auto ok = m_->insertRecord (-1, record);
|
|
|
|
if (ok)
|
2018-11-07 12:49:45 -05:00
|
|
|
{
|
2018-12-06 00:41:16 -05:00
|
|
|
ok = transaction.submit (false);
|
2018-11-07 12:49:45 -05:00
|
|
|
}
|
2018-12-06 00:41:16 -05:00
|
|
|
m_->setEditStrategy (QSqlTableModel::OnFieldChange);
|
2018-11-25 17:19:41 -05:00
|
|
|
return ok;
|
2018-11-07 12:49:45 -05:00
|
|
|
}
|
2018-11-11 21:06:44 -05:00
|
|
|
|
|
|
|
bool FoxLog::dupe (QString const& call, QString const& band) const
|
|
|
|
{
|
|
|
|
m_->dupe_query_.bindValue (":call", call);
|
|
|
|
m_->dupe_query_.bindValue (":band", band);
|
|
|
|
SQL_error_check (m_->dupe_query_, static_cast<bool (QSqlQuery::*) ()> (&QSqlQuery::exec));
|
|
|
|
m_->dupe_query_.next ();
|
|
|
|
return m_->dupe_query_.value (0).toInt ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void FoxLog::reset ()
|
|
|
|
{
|
2018-11-11 23:00:55 -05:00
|
|
|
if (m_->rowCount ())
|
|
|
|
{
|
2018-11-25 17:19:41 -05:00
|
|
|
m_->setEditStrategy (QSqlTableModel::OnManualSubmit);
|
2018-11-11 23:00:55 -05:00
|
|
|
ConditionalTransaction transaction {*m_};
|
|
|
|
SQL_error_check (*m_, &QSqlTableModel::removeRows, 0, m_->rowCount (), QModelIndex {});
|
|
|
|
transaction.submit ();
|
2018-11-25 17:19:41 -05:00
|
|
|
m_->select (); // to refresh views
|
2018-12-01 21:30:32 -05:00
|
|
|
m_->setEditStrategy (QSqlTableModel::OnFieldChange);
|
2018-11-11 23:00:55 -05:00
|
|
|
}
|
2018-11-11 21:06:44 -05:00
|
|
|
}
|