Removing a QSO of ClubLog

This commit is contained in:
jaime 2015-05-03 11:19:18 +00:00
parent bf89405776
commit 1dd670d4da
8 changed files with 242 additions and 42 deletions

View File

@ -4,7 +4,8 @@
- KLog is able to import QSOs with no BAND field if FREQ field is present.
- KLog offers the user a default value if RST_TX or RST_RX field is not present when importing.
- GUI: Added some shortcuts in the preference widget.
- Support of realtime log upload to ClubLog.org
- Support of realtime upload & deletion removal of a single QSO from ClubLog.org.
- Updated the DB with the PROP_MODE options.
April-2015 - 0.9.1.1
- Bugfix: Editing a QSO with satellite data was not properly done and caused some errors.

6
TODO
View File

@ -2,6 +2,11 @@ This is a kind of roadmap for KLog development.
It is not fixed... new features may be prioritized or not added without any notice ;-)
Feel free to request any roadmap change if you have any suggestion.
TODO: Add a ComboBox with the PROP_MODE to select, it so ClubLog & LOTW accept the QSOs
KLog 0.9.2
Bug: An ADIF file with one blank line and one QSO freezes KLog.
Bug?: Check if if is possible to import a ONE line log
@ -51,6 +56,7 @@ TODO: Integrate with www.clublog.org (http://www.clublog.org/docs/pages/viewpage
KLog 0.9.8
TODO: Integrate with eqsl.cc
https://www.eqsl.cc/qslcard/ADIFContentSpecs.cfm
KLog 0.9.9
TODO: Server to log all the QSO in real time (through the network) from N1MM

View File

@ -500,11 +500,7 @@ confirmed = 1 Set as Confirmed
"shortname VARCHAR(1) NOT NULL, "
"name VARCHAR(15) NOT NULL)");
query.exec("CREATE TABLE prop_mode_enumeration ("
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
"shortname VARCHAR(8) NOT NULL, "
"name VARCHAR(55) NOT NULL)");
createTablePropModes();
createTableLogs();
/*
@ -574,6 +570,8 @@ confirmed = 1 Set as Confirmed
query.exec("INSERT INTO continent (shortname, name) VALUES ('AN', 'Antartica')");
populateContestData();
populatePropagationModes();
//To add a band, just create another line:
query.exec("INSERT INTO band (name, lower, upper, cabrillo) VALUES ('0', '0', '0', 'Light')");
@ -695,10 +693,6 @@ query.exec("INSERT INTO award_enumeration (name) VALUES (CQDXFIELD')");
query.exec("INSERT INTO award_enumeration (name) VALUES (DXCC')");
query.exec("INSERT INTO award_enumeration (name) VALUES (TPEA')");
query.exec("INSERT INTO prop_mode_enumeration (shortname, name) VALUES ('AUR', 'Aurora')");
query.exec("INSERT INTO prop_mode_enumeration (shortname, name) VALUES ('AUE', 'Aurora-E')");
query.exec("INSERT INTO prop_mode_enumeration (shortname, name) VALUES ('BS', 'Back scatter')");
query.exec("INSERT INTO qsl_via (shortname, name) VALUES ('B', 'Bureau')");
query.exec("INSERT INTO qsl_via (shortname, name) VALUES ('D', 'Direct')");
@ -1236,7 +1230,7 @@ bool DataBase::updateToLatest()
*
*/
//qDebug() << "DataBase::updateToLatest-005 " << endl;
return updateTo005();
return updateTo006();
}
bool DataBase::updateTo003()
@ -1498,8 +1492,8 @@ bool DataBase::updateTo005()
msgBox.exec();
}
return IAmIn005;
}
bool DataBase::recreateContestData()
{
QSqlQuery query;
@ -1521,8 +1515,6 @@ bool DataBase::updateLog()
//qDebug() << "DataBase::updateLog" << endl;
QSqlQuery query;
bool sqlOk = false;
}
bool DataBase::createTableLogs()
@ -1539,6 +1531,16 @@ bool DataBase::createTableLogs()
"FOREIGN KEY (logtype) REFERENCES supportedcontests(name))");
}
bool DataBase::createTablePropModes()
{
QSqlQuery query;
query.exec("CREATE TABLE prop_mode_enumeration ("
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
"shortname VARCHAR(8) NOT NULL, "
"name VARCHAR(55) NOT NULL)");
}
bool DataBase::createTableContest()
{
QSqlQuery query;
@ -1628,6 +1630,31 @@ bool DataBase::createTableContest()
}
bool DataBase::populatePropagationModes()
{
QSqlQuery query;
query.exec("INSERT INTO prop_mode_enumeration (shortname, name) VALUES ('AUR', 'Aurora')");
query.exec("INSERT INTO prop_mode_enumeration (shortname, name) VALUES ('AUE', 'Aurora-E')");
query.exec("INSERT INTO prop_mode_enumeration (shortname, name) VALUES ('BS', 'Back scatter')");
query.exec("INSERT INTO prop_mode_enumeration (shortname, name) VALUES ('ECH', 'EchoLink')");
query.exec("INSERT INTO prop_mode_enumeration (shortname, name) VALUES ('EME', 'Earth-Moon-Earth')");
query.exec("INSERT INTO prop_mode_enumeration (shortname, name) VALUES ('ES', 'Sporadic E')");
query.exec("INSERT INTO prop_mode_enumeration (shortname, name) VALUES ('FAI', 'Field Aligned Irregularities')");
query.exec("INSERT INTO prop_mode_enumeration (shortname, name) VALUES ('F2', 'F2 Reflection')");
query.exec("INSERT INTO prop_mode_enumeration (shortname, name) VALUES ('INTERNET', 'Internet-assisted')");
query.exec("INSERT INTO prop_mode_enumeration (shortname, name) VALUES ('ION', 'Ionoscatter')");
query.exec("INSERT INTO prop_mode_enumeration (shortname, name) VALUES ('IRL', 'IRLP')");
query.exec("INSERT INTO prop_mode_enumeration (shortname, name) VALUES ('MS', 'Meteor scatter')");
query.exec("INSERT INTO prop_mode_enumeration (shortname, name) VALUES (RPT'', 'Terrestrial or atmospheric repeater or transponder')");
query.exec("INSERT INTO prop_mode_enumeration (shortname, name) VALUES ('RS', 'Rain scatter')");
query.exec("INSERT INTO prop_mode_enumeration (shortname, name) VALUES ('SAT', 'Satellite')");
query.exec("INSERT INTO prop_mode_enumeration (shortname, name) VALUES ('TEP', 'Trans-equatorial')");
query.exec("INSERT INTO prop_mode_enumeration (shortname, name) VALUES ('TR', 'Tropospheric ducting')");
return true;
}
bool DataBase::populateContestData()
{
@ -1719,5 +1746,71 @@ bool DataBase::howManyQSOsInLog(const int i)
}
}
bool DataBase::updateTo006()
{// Updates the DB to 0.0.6
/*
* This function should be used as a template to create the all the update functions implementing the needed changes
* in the dB to update from one version to the following one.
*
* // dbVersion shows the DB version that is being deployed
* // latestReaded shows the DB version that is currently deployed.
*i.e.:
* QString stringQuery = QString ("ALTER TABLE award_enumeration ADD COLUMN dxcc INTEGER;");
*
*/
//qDebug() << "DataBase::updateTo004" << endl;
bool IAmIn006 = false;
bool IAmIn005 = false;
bool ErrorUpdating = false;
QString stringQuery = QString();
QString dateString = (date.currentDateTime()).toString("yyyyMMdd");
QSqlQuery query;
bool sqlOk = false;
if (latestReaded >= 0.006)
{
return true;
}
else
{
IAmIn006 = false;
}
while (!IAmIn006 && !ErrorUpdating)
{
while (!IAmIn005 && !ErrorUpdating)
{
IAmIn005 = true;
}
if (ErrorUpdating)
{
return false;
}
sqlOk = query.exec("INSERT INTO softwarecontrol (dateupgrade, softversion, dbversion) VALUES ('" + dateString + "', '" + softVersion + "', '" + QString::number(dbVersion) + "')");
if (sqlOk)
{ // Version updated
sqlOk = query.exec("DROP TABLE prop_mode_enumeration");
sqlOk = createTablePropModes();
sqlOk = populatePropagationModes();
if (!sqlOk)
{
//qDebug() << "DataBase::updateTo006 - prop_mode table do not created" << endl;
}
}
else
{ // Version not updated
}
//DO ALL THE TASKS TO BE IN 0.006 from 0.005 HERE and set ErrorUpdating if it is not possible.
IAmIn006 = true;
}
return IAmIn006;
}

View File

@ -37,9 +37,9 @@
class QSqlRelationalTableModel;
// Last db update 0.0.5
// Previous db update 0.0.4
const float DBVersionf = 0.005;
// Last db update 0.0.6
// Previous db update 0.0.5
const float DBVersionf = 0.006;
class DataBase
{
@ -86,6 +86,7 @@ private:
bool updateTo003(); // Updates the DB to 0.0.3
bool updateTo004();
bool updateTo005();
bool updateTo006();
bool createTheBandQuickReference();
bool createTheModeQuickReference();
@ -93,10 +94,13 @@ private:
bool updateLog(); // Updates the log table
bool createTableLog(); //Creates log=0 or selectedlog=1
bool createTableLogs();
bool createTablePropModes();
bool recreateContestData();
bool createTableContest();
bool populateContestData();
bool populatePropagationModes();
bool howManyQSOsInLog(const int i);
void showError(const QString _errorC);

View File

@ -503,12 +503,17 @@ QString DataProxy_SQLite::getCallFromId(const int _qsoId)
QStringList DataProxy_SQLite::getClubLogRealTimeFromId(const int _qsoId)
{
//qDebug() << "DataProxy_SQLite::getClubLogRealTimeFromId: " << QString::number(_qsoId) << endl;
/* Return a QStringList with these data:
qDebug() << "DataProxy_SQLite::getClubLogRealTimeFromId: " << QString::number(_qsoId) << endl;
/* Return a QStringList with 16 fields with these data:
QSO_DATE, TIME_ON, QSLRDATE, QSLSDATE, CALL, OPERATOR, MODE, BAND, BAND_RX, FREQ, QSL_RCVD,
LOTW_QSL_RCVD, QSL_SENT, DXCC, PROP_MODE, CREDIT_GRANTED
*/
QSqlQuery query;
int nameCol = -1;
QStringList dataC = QStringList();
@ -520,16 +525,16 @@ LOTW_QSL_RCVD, QSL_SENT, DXCC, PROP_MODE, CREDIT_GRANTED
QString stringQuery = QString("SELECT qso_date, time_on, qslrdate, qslsdate, call, operator, M.name, B.name, R.name, freq, qsl_rcvd, lotw_qsl_rcvd, qsl_sent, dxcc, prop_mode, credit_granted FROM log INNER JOIN band as B ON bandid = B.id INNER JOIN band as R ON band_rx = R.id INNER JOIN mode as M ON modeid = M.id WHERE log.id='%1'").arg(_qsoId);
bool sqlOk = query.exec(stringQuery);
//qDebug() << "DataProxy_SQLite::getClubLogRealTimeFromId: LastQuery: " << query.lastQuery() << endl;
//qDebug() << "DataProxy_SQLite::getClubLogRealTimeFromId: LastError-data: " << query.lastError().databaseText() << endl;
//qDebug() << "DataProxy_SQLite::getClubLogRealTimeFromId: LastError-driver: " << query.lastError().driverText() << endl;
//qDebug() << "DataProxy_SQLite::getClubLogRealTimeFromId: LastError-n: " << QString::number(query.lastError().number() ) << endl;
qDebug() << "DataProxy_SQLite::getClubLogRealTimeFromId: LastQuery: " << query.lastQuery() << endl;
qDebug() << "DataProxy_SQLite::getClubLogRealTimeFromId: LastError-data: " << query.lastError().databaseText() << endl;
qDebug() << "DataProxy_SQLite::getClubLogRealTimeFromId: LastError-driver: " << query.lastError().driverText() << endl;
qDebug() << "DataProxy_SQLite::getClubLogRealTimeFromId: LastError-n: " << QString::number(query.lastError().number() ) << endl;
QSqlRecord rec = query.record();
if (sqlOk)
{
//qDebug() << "DataProxy_SQLite::getClubLogRealTimeFromId sqlOK" << endl;
qDebug() << "DataProxy_SQLite::getClubLogRealTimeFromId sqlOK" << endl;
if (query.next())
//if (1)
{

View File

@ -11,9 +11,6 @@ eLogClubLog::eLogClubLog() : QObject(0)
email = QString();
pass = QString();
api = "9467beee93377e82a276b0a777d388b5c933d044";
// manager = new QNetworkAccessManager();
//QObject::connect(&manager, SIGNAL(finished(QNetworkReply*)),this, SLOT(downloadFinished(QNetworkReply*)));
}
eLogClubLog::~eLogClubLog()
@ -35,7 +32,7 @@ eLogClubLog::~eLogClubLog()
const QByteArray sdata = data->readAll();
qDebug() << sdata;
qDebug() << "eLogClubLog::downloadFinished: and CTY file created!" << endl;
emit actionReturnDownload(result);
}
else if (result == QNetworkReply::HostNotFoundError)
@ -87,17 +84,16 @@ void eLogClubLog::slotErrorManagement(QNetworkReply::NetworkError networkError)
int eLogClubLog::sendQSO(const QStringList _qso)
{
qDebug() << "eLogClubLog::sendQSO: " << call <<"/"<< email << "/" << pass << "/" << api << endl;
qDebug() << "eLogClubLog::sendQSO:: length = " << QString::number(_qso.length()) << endl;
if (_qso.length()!=16)
{
return -1;
}
QString qso = getClubLogAdif(_qso);
qDebug() << "eLogClubLog::sendQSO: " << qso << endl;
return sendData(qso);
//target = "https://secure.clublog.org/realtime.php";
//QUrl url = QUrl::fromEncoded(this->target.toLocal8Bit());
//QNetworkRequest request(url);
//request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
// reply = manager.get(request);
/*******************/
/*
QUrl serviceUrl = QUrl("https://secure.clublog.org/realtime.php");
QByteArray postData;
@ -120,13 +116,46 @@ int eLogClubLog::sendQSO(const QStringList _qso)
connect(networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(downloadFinished(QNetworkReply*)));
networkManager->post(request, postData);
*/
//qDebug() << "eLogClubLog::sendQSO (result): " << QString::number(result) << endl;
// return result;
}
int eLogClubLog::sendData(const QString _q)
{
qDebug() << "eLogClubLog::sendData: " << _q<< endl;
QUrl serviceUrl = QUrl("https://secure.clublog.org/realtime.php");
QByteArray postData;
//QByteArray postData;
QUrl params;
params.addQueryItem("email",email);
params.addQueryItem("password",pass);
params.addQueryItem("callsign",call);
params.addQueryItem("api",api);
params.addQueryItem("adif",_q);
postData = params.encodedQuery();
// Call the webservice
QNetworkAccessManager *networkManager = new QNetworkAccessManager(this);
QNetworkRequest request(serviceUrl);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
connect(networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(downloadFinished(QNetworkReply*)));
networkManager->post(request, postData);
return -1;
}
QString eLogClubLog::getClubLogAdif(const QStringList _q)
{
qDebug() << "eLogClubLog::getCLubLogAdif" << endl;
qDebug() << "eLogClubLog::getClubLogAdif: " << QString::number(_q.length()) << endl;
// _qso must include 16 ordered fields than can be empty or contain data. This function builds the ADIF QSO
/* http://clublog.freshdesk.com/support/solutions/articles/53202-which-adif-fields-does-club-log-use-
ClubLog only accepts the following ADIF fields:
@ -147,6 +176,10 @@ ClubLog only accepts the following ADIF fields:
PROP_MODE
CREDIT_GRANTED
*/
if (_q.length()!=16)
{
return QString();
}
QString qso, aux1;
qso.clear();
@ -158,26 +191,44 @@ ClubLog only accepts the following ADIF fields:
qso = "<QSO_DATE:" + QString::number(aux1.length()) + ">" + aux1 + " ";
}
qDebug() << "eLogClubLog::getClubLogAdif: 1" << endl;
//qso = "<QSO_DATE:" + QString::number((_q.at(0)).length()) + ">" + _q.at(0) + " ";
qso = qso + "<TIME_ON:" + QString::number((_q.at(1)).length()) + ">" + _q.at(1) + " ";
qDebug() << "eLogClubLog::getClubLogAdif: 10" << endl;
qso = qso + "<QSLRDATE:" + QString::number((_q.at(2)).length()) + ">" + _q.at(2) + " ";
qDebug() << "eLogClubLog::getClubLogAdif: 20" << endl;
qso = qso + "<QSLSDATE:" + QString::number((_q.at(3)).length()) + ">" + _q.at(3) + " ";
qDebug() << "eLogClubLog::getClubLogAdif: 30" << endl;
qso = qso + "<CALL:" + QString::number((_q.at(4)).length()) + ">" + _q.at(4) + " ";
qDebug() << "eLogClubLog::getClubLogAdif: 40" << endl;
qso = qso + "<OPERATOR:" + QString::number((_q.at(5)).length()) + ">" + _q.at(5) + " ";
qDebug() << "eLogClubLog::getClubLogAdif: 50" << endl;
qso = qso + "<MODE:" + QString::number((_q.at(6)).length()) + ">" + _q.at(6) + " ";
qDebug() << "eLogClubLog::getClubLogAdif: 60" << endl;
qso = qso + "<BAND:" + QString::number((_q.at(7)).length()) + ">" + _q.at(7) + " ";
qDebug() << "eLogClubLog::getClubLogAdif: 70" << endl;
qso = qso + "<BAND_RX:" + QString::number((_q.at(8)).length()) + ">" + _q.at(8) + " ";
qDebug() << "eLogClubLog::getClubLogAdif: 80" << endl;
qso = qso + "<FREQ:" + QString::number((_q.at(9)).length()) + ">" + _q.at(9) + " ";
qDebug() << "eLogClubLog::getClubLogAdif: 90" << endl;
qso = qso + "<QSL_RCVD:" + QString::number((_q.at(10)).length()) + ">" + _q.at(10) + " ";
qDebug() << "eLogClubLog::getClubLogAdif: 100" << endl;
qso = qso + "<LOTW_QSL_RCVD:" + QString::number((_q.at(11)).length()) + ">" + _q.at(11) + " ";
qDebug() << "eLogClubLog::getClubLogAdif: 110" << endl;
qso = qso + "<QSL_SENT:" + QString::number((_q.at(12)).length()) + ">" + _q.at(12) + " ";
qDebug() << "eLogClubLog::getClubLogAdif: 120" << endl;
qso = qso + "<DXCC:" + QString::number((_q.at(13)).length()) + ">" + _q.at(13) + " ";
qDebug() << "eLogClubLog::getClubLogAdif: 130'" << endl;
qso = qso + "<PROP_MODE:" + QString::number((_q.at(14)).length()) + ">" + _q.at(14) + " ";
qDebug() << "eLogClubLog::getClubLogAdif: 140" << endl;
qso = qso + "<CREDIT_GRANTED:" + QString::number((_q.at(15)).length()) + ">" + _q.at(15) + " ";
qDebug() << "eLogClubLog::getClubLogAdif: 150" << endl;
qso = qso + "<EOR>";
//qDebug() << "eLogClubLog::getCLubLogAdif - QSO: " << qso << endl;
qDebug() << "eLogClubLog::getClubLogAdif: 100" << endl;
return qso;
}
@ -190,3 +241,23 @@ void eLogClubLog::setCredentials(const QString _call, const QString _email, cons
}
int eLogClubLog::deleteQSO(const QStringList _qso)
{
qDebug() << "eLogClubLog::deleteQSO: length = " << QString::number(_qso.length()) << endl;
if (_qso.length()!=16)
{
return -1;
}
//http://clublog.freshdesk.com/support/solutions/articles/54908-using-adif-to-update-or-delete-qsos
//<CALL:5>VP9NO<QSO_DATE:8>20070903<TIME_ON:6>213300<BAND:3>30M<MODE:2>CW<QSLCALL:5>GH6UW<EOR>
QString replaceCall = "<QSLCALL:" + QString::number(call.length()) + ">" + call + " " + "<EOR>";
QString qso = getClubLogAdif(_qso);
qso.replace("<EOR>", replaceCall);
return sendData(qso);
}

View File

@ -15,11 +15,14 @@ public:
void setCredentials(const QString _call, const QString _email, const QString _pass);
int sendQSO(const QStringList _qso);
int deleteQSO(const QStringList _qso);
//int download();
private:
QString getClubLogAdif(const QStringList _q);
int sendData(const QString _q); // Sends the data (http post) to ClubLog
QString call, email, pass, api;
QNetworkAccessManager *manager;

View File

@ -24,6 +24,7 @@
* *
*****************************************************************************/
#include <QtGui>
#include <QtSql>
#include <QObject>
@ -4390,7 +4391,8 @@ void MainWindow::slotQSOToEditFromSearch()
void MainWindow::slotQsoDeleteFromLog()
{
//qDebug() << "MainWindow::slotQsoDeleteFromLog: " << (delQSOFromLogAct->data()).toString() << endl;
qDebug() << "MainWindow::slotQsoDeleteFromLog: " << (delQSOFromLogAct->data()).toString() << endl;
QMessageBox msgBox;
msgBox.setIcon(QMessageBox::Information);
@ -4400,9 +4402,19 @@ void MainWindow::slotQsoDeleteFromLog()
msgBox.setDefaultButton(QMessageBox::No);
int ret = msgBox.exec();
int QSOid = ((logModel->index((delQSOFromLogAct->data()).toInt(), 0)).data(0)).toInt();
qDebug() << "MainWindow::slotQsoDeleteFromLog (id): " << QString::number(QSOid) << endl;
switch (ret) {
case QMessageBox::Yes:
logModel->removeRow((delQSOFromLogAct->data()).toInt());
qDebug() << "MainWindow::slotQsoDeleteFromLog (id): -1" << endl;
elogClublog->deleteQSO(dataProxy->getClubLogRealTimeFromId(QSOid));
qDebug() << "MainWindow::slotQsoDeleteFromLog (id): -2"<< endl;
logModel->removeRow((delQSOFromLogAct->data()).toInt());
qDebug() << "MainWindow::slotQsoDeleteFromLog (id):-3 " << endl;
slotSearchBoxTextChanged();
awards->recalculateAwards();
showAwards();
@ -4421,8 +4433,10 @@ void MainWindow::slotQsoDeleteFromSearch()
//qDebug() << "MainWindow::slotQsoDeleteFromSearch: " << (delQSOFromSearchAct->data()).toString() << endl;
//qDebug() << "MainWindow::slotQsoDeleteFromSearch: " << QString::number((logModel->index((delQSOFromSearchAct->data(6)).toInt(), 0)).data(0).toInt()) << endl;
int QSOid = (delQSOFromSearchAct->data()).toInt();
int x = -1;
QString _qrz = dataProxy->getCallFromId((delQSOFromSearchAct->data()).toInt());
QString _qrz = dataProxy->getCallFromId(QSOid);
if (_qrz.length()>=3)
{
@ -4439,8 +4453,11 @@ void MainWindow::slotQsoDeleteFromSearch()
switch (ret)
{
case QMessageBox::Yes:
if(dataProxy->deleteQSO((delQSOFromSearchAct->data()).toInt()))
x = elogClublog->deleteQSO(dataProxy->getClubLogRealTimeFromId(QSOid));
if(dataProxy->deleteQSO(QSOid))
{
logModel->select();
if(qslingNeeded)
{