mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-11-25 05:38:46 -05:00
Class abstracting LotW user lookups which includes asynchronous data loading
This commit is contained in:
parent
d9cf9bed3c
commit
62a4569a4c
@ -261,6 +261,7 @@ set (wsjt_qt_CXXSRCS
|
||||
EqualizationToolsDialog.cpp
|
||||
DoubleClickablePushButton.cpp
|
||||
DoubleClickableRadioButton.cpp
|
||||
LotWUsers.cpp
|
||||
)
|
||||
|
||||
set (wsjt_qtmm_CXXSRCS
|
||||
|
89
LotWUsers.cpp
Normal file
89
LotWUsers.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
#include "LotWUsers.hpp"
|
||||
|
||||
#include <future>
|
||||
|
||||
#include <QHash>
|
||||
#include <QString>
|
||||
#include <QDate>
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
#include <QDir>
|
||||
#include <QDebug>
|
||||
|
||||
#include "Configuration.hpp"
|
||||
|
||||
#include "pimpl_impl.hpp"
|
||||
|
||||
#include "moc_LotWUsers.cpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
// Dictionary mapping call sign to date of last upload to LotW
|
||||
using dictionary = QHash<QString, QDate>;
|
||||
|
||||
// Load the database from the given file name
|
||||
//
|
||||
// Expects the file to be in CSV format with no header with one
|
||||
// record per line. Record fields are call sign followed by upload
|
||||
// date in yyyy-MM-dd format followed by upload time (ignored)
|
||||
dictionary load (QString const& lotw_users_file)
|
||||
{
|
||||
dictionary result;
|
||||
QFile f {lotw_users_file};
|
||||
if (f.open (QFile::ReadOnly | QFile::Text))
|
||||
{
|
||||
QTextStream s {&f};
|
||||
for (auto l = s.readLine (); !l.isNull (); l = s.readLine ())
|
||||
{
|
||||
auto pos = l.indexOf (',');
|
||||
result[l.left (pos)] = QDate::fromString (l.mid (pos + 1, l.indexOf (',', pos + 1) - pos - 1), "yyyy-MM-dd");
|
||||
}
|
||||
qDebug () << "LotW User Data Loaded";
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error {QObject::tr ("Failed to open LotW users CSV file: '%1'").arg (f.fileName ()).toLocal8Bit ()};
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
class LotWUsers::impl final
|
||||
{
|
||||
public:
|
||||
std::future<dictionary> future_load_;
|
||||
dictionary last_uploaded_;
|
||||
};
|
||||
|
||||
LotWUsers::LotWUsers (Configuration const * configuration, QObject * parent)
|
||||
: QObject {parent}
|
||||
{
|
||||
// load the database asynchronously
|
||||
m_->future_load_ = std::async (std::launch::async, load, configuration->writeable_data_dir ().absoluteFilePath ("lotw-user-activity.csv"));
|
||||
}
|
||||
|
||||
LotWUsers::~LotWUsers ()
|
||||
{
|
||||
}
|
||||
|
||||
bool LotWUsers::user (QString const& call, qint64 uploaded_since_days) const
|
||||
{
|
||||
if (m_->future_load_.valid ())
|
||||
{
|
||||
try
|
||||
{
|
||||
// wait for the load to finish if necessary
|
||||
const_cast<dictionary&> (m_->last_uploaded_) = const_cast<std::future<dictionary>&> (m_->future_load_).get ();
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
Q_EMIT LotW_users_error (e.what ());
|
||||
}
|
||||
}
|
||||
auto p = m_->last_uploaded_.constFind (call);
|
||||
if (p != m_->last_uploaded_.end ())
|
||||
{
|
||||
return p.value ().daysTo (QDate::currentDate ()) <= uploaded_since_days;
|
||||
}
|
||||
return false;
|
||||
}
|
35
LotWUsers.hpp
Normal file
35
LotWUsers.hpp
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef LOTW_USERS_HPP_
|
||||
#define LOTW_USERS_HPP_
|
||||
|
||||
#include <boost/core/noncopyable.hpp>
|
||||
#include <QObject>
|
||||
#include "pimpl_h.hpp"
|
||||
|
||||
class QString;
|
||||
class QDate;
|
||||
class Configuration;
|
||||
|
||||
//
|
||||
// LotWUsers - Lookup Logbook of the World users
|
||||
//
|
||||
class LotWUsers final
|
||||
: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
LotWUsers (Configuration const * configuration, QObject * parent = 0);
|
||||
~LotWUsers ();
|
||||
|
||||
// returns true if the specified call sign 'call' has uploaded their
|
||||
// log to LotW in the last 'uploaded_since_days' days
|
||||
Q_SLOT bool user (QString const& call, qint64 uploaded_since_days) const;
|
||||
|
||||
Q_SIGNAL void LotW_users_error (QString const& reason) const;
|
||||
|
||||
private:
|
||||
class impl;
|
||||
pimpl<impl> m_;
|
||||
};
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -20,7 +20,6 @@ DecodedText::DecodedText (QString const& the_string)
|
||||
, message_ {string_.mid (column_qsoText + padding_).trimmed ()}
|
||||
, is_standard_ {false}
|
||||
{
|
||||
qDebug () << "DecodedText: the_string:" << the_string << "Nbsp pos:" << the_string.indexOf (QChar::Nbsp);
|
||||
if (message_.length() >= 1)
|
||||
{
|
||||
message0_ = message_.left(36);
|
||||
|
@ -1,5 +1,4 @@
|
||||
#include "displaytext.h"
|
||||
#include "mainwindow.h"
|
||||
#include <QMouseEvent>
|
||||
#include <QDateTime>
|
||||
#include <QTextCharFormat>
|
||||
@ -8,12 +7,14 @@
|
||||
#include <QMenu>
|
||||
#include <QAction>
|
||||
|
||||
#include "qt_helpers.hpp"
|
||||
#include "LotWUsers.hpp"
|
||||
|
||||
#include "qt_helpers.hpp"
|
||||
#include "moc_displaytext.cpp"
|
||||
|
||||
DisplayText::DisplayText(QWidget *parent)
|
||||
: QTextEdit(parent)
|
||||
, m_lotw_users {0}
|
||||
, erase_action_ {new QAction {tr ("&Erase"), this}}
|
||||
{
|
||||
setReadOnly (true);
|
||||
@ -76,7 +77,6 @@ void DisplayText::insertLineSpacer(QString const& line)
|
||||
void DisplayText::appendText(QString const& text, QColor bg,
|
||||
QString const& call1, QString const& call2)
|
||||
{
|
||||
qDebug () << "DisplayText::appendText: text:" << text << "Nbsp pos:" << text.indexOf (QChar::Nbsp);
|
||||
auto cursor = textCursor ();
|
||||
cursor.movePosition (QTextCursor::End);
|
||||
auto block_format = cursor.blockFormat ();
|
||||
@ -144,7 +144,7 @@ void DisplayText::appendText(QString const& text, QColor bg,
|
||||
}
|
||||
format.setBackground (bg);
|
||||
format.clearForeground ();
|
||||
if(call2.size()>0 and !m_LoTW.contains(call2)) {
|
||||
if(call2.size () && !m_lotw_users->user (call2, 365)) {
|
||||
format.setForeground(m_color_LoTW); //Mark LoTW non-users
|
||||
}
|
||||
cursor.insertText(text.mid (text_index), format);
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "decodedtext.h"
|
||||
|
||||
class QAction;
|
||||
class LotWUsers;
|
||||
|
||||
class DisplayText
|
||||
: public QTextEdit
|
||||
@ -19,7 +20,7 @@ class DisplayText
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DisplayText(QWidget *parent = 0);
|
||||
|
||||
void setLotWUsers (LotWUsers const * lotw_users) {m_lotw_users = lotw_users;}
|
||||
void setContentFont (QFont const&);
|
||||
void insertLineSpacer(QString const&);
|
||||
void displayDecodedText(DecodedText const& decodedText, QString const& myCall,
|
||||
@ -45,6 +46,7 @@ protected:
|
||||
void mouseDoubleClickEvent(QMouseEvent *e);
|
||||
|
||||
private:
|
||||
LotWUsers const * m_lotw_users;
|
||||
bool m_bPrincipalPrefix;
|
||||
QString appendWorkedB4(QString message, QString const& callsign, QString grid, QColor * bg,
|
||||
LogBook const& logBook, QString currentBand);
|
||||
|
@ -162,7 +162,6 @@ int fast_jhpeak {0};
|
||||
int fast_jh2 {0};
|
||||
int narg[15];
|
||||
QVector<QColor> g_ColorTbl;
|
||||
QHash<QString,int> m_LoTW;
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -204,6 +203,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
||||
m_settings {multi_settings->settings ()},
|
||||
ui(new Ui::MainWindow),
|
||||
m_config {temp_directory, m_settings, this},
|
||||
m_lotw_users {&m_config},
|
||||
m_WSPR_band_hopping {m_settings, &m_config, this},
|
||||
m_WSPR_tx_next {false},
|
||||
m_rigErrorMessageBox {MessageBox::Critical, tr ("Rig Control Error")
|
||||
@ -386,6 +386,8 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
||||
ui->dxGridEntry->setValidator (new MaidenheadLocatorValidator {this});
|
||||
ui->dxCallEntry->setValidator (new CallsignValidator {this});
|
||||
ui->sbTR->values ({5, 10, 15, 30});
|
||||
ui->decodedTextBrowser->setLotWUsers (&m_lotw_users);
|
||||
ui->decodedTextBrowser2->setLotWUsers (&m_lotw_users);
|
||||
|
||||
m_baseCall = Radio::base_callsign (m_config.my_callsign ());
|
||||
m_opCall = m_config.opCall();
|
||||
@ -555,6 +557,10 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
||||
m_equalizationToolsDialog->show ();
|
||||
});
|
||||
|
||||
connect (&m_lotw_users, &LotWUsers::LotW_users_error, this, [this] (QString const& reason) {
|
||||
MessageBox::warning_message (this, tr ("Error Loading LotW Users Data"), reason);
|
||||
}, Qt::QueuedConnection);
|
||||
|
||||
QButtonGroup* txMsgButtonGroup = new QButtonGroup {this};
|
||||
txMsgButtonGroup->addButton(ui->txrb1,1);
|
||||
txMsgButtonGroup->addButton(ui->txrb2,2);
|
||||
@ -919,31 +925,6 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
||||
ui->cbMenus->setChecked(false);
|
||||
}
|
||||
|
||||
QFile f{m_config.data_dir().absoluteFilePath ("lotw-user-activity.csv")};
|
||||
if(f.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
QTextStream s(&f);
|
||||
QString line,call;
|
||||
int nLoTW=0;
|
||||
int i1;
|
||||
QDateTime now=QDateTime::currentDateTime();
|
||||
QDateTime callDateTime;
|
||||
// Read and process the file of LoTW-active stations
|
||||
while(!s.atEnd()) {
|
||||
line=s.readLine();
|
||||
i1=line.indexOf(",");
|
||||
call=line.left(i1);
|
||||
line=line.mid(i1+1);
|
||||
i1=line.indexOf(",");
|
||||
callDateTime=QDateTime::fromString(line.left(i1),"yyyy-MM-dd");
|
||||
int ndays=callDateTime.daysTo(now);
|
||||
if(ndays < 366) {
|
||||
nLoTW++;
|
||||
m_LoTW[call]=ndays;
|
||||
}
|
||||
}
|
||||
f.close();
|
||||
}
|
||||
|
||||
// this must be the last statement of constructor
|
||||
if (!m_valid) throw std::runtime_error {"Fatal initialization exception"};
|
||||
}
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "astro.h"
|
||||
#include "MessageBox.hpp"
|
||||
#include "NetworkAccessManager.hpp"
|
||||
#include "LotWUsers.hpp"
|
||||
|
||||
#define NUM_JT4_SYMBOLS 206 //(72+31)*2, embedded sync
|
||||
#define NUM_JT65_SYMBOLS 126 //63 data + 63 sync
|
||||
@ -341,8 +342,8 @@ private:
|
||||
QSettings * m_settings;
|
||||
QScopedPointer<Ui::MainWindow> ui;
|
||||
|
||||
// other windows
|
||||
Configuration m_config;
|
||||
LotWUsers m_lotw_users;
|
||||
WSPRBandHopping m_WSPR_band_hopping;
|
||||
bool m_WSPR_tx_next;
|
||||
MessageBox m_rigErrorMessageBox;
|
||||
|
Loading…
Reference in New Issue
Block a user