223 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			223 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "adif.h"
 | |
| 
 | |
| #include <QFile>
 | |
| #include <QTextStream>
 | |
| #include <QDateTime>
 | |
| #include <QDebug>
 | |
| 
 | |
| /*
 | |
| <CALL:4>W1XT<BAND:3>20m<FREQ:6>14.076<GRIDSQUARE:4>DM33<MODE:4>JT65<RST_RCVD:3>-21<RST_SENT:3>-14<QSO_DATE:8>20110422<TIME_ON:6>041712<TIME_OFF:6>042435<TX_PWR:1>4<COMMENT:34>1st JT65A QSO.   Him: mag loop 20W<STATION_CALLSIGN:6>VK3ACF<MY_GRIDSQUARE:6>qf22lb<eor>
 | |
| <CALL:6>IK1SOW<BAND:3>20m<FREQ:6>14.076<GRIDSQUARE:4>JN35<MODE:4>JT65<RST_RCVD:3>-19<RST_SENT:3>-11<QSO_DATE:8>20110422<TIME_ON:6>052501<TIME_OFF:6>053359<TX_PWR:1>3<STATION_CALLSIGN:6>VK3ACF<MY_GRIDSQUARE:6>qf22lb<eor>
 | |
| <CALL:6:S>W4ABC> ...
 | |
| */
 | |
| 
 | |
| void ADIF::init(QString const& filename)
 | |
| {
 | |
|     _filename = filename;
 | |
|     _data.clear();
 | |
| }
 | |
| 
 | |
| 
 | |
| QString ADIF::extractField(QString const& record, QString const& fieldName) const
 | |
| {
 | |
|     int fieldNameIndex = record.indexOf ('<' + fieldName + ':', 0, Qt::CaseInsensitive);
 | |
|     if (fieldNameIndex >=0)
 | |
|     {
 | |
|         int closingBracketIndex = record.indexOf('>',fieldNameIndex);
 | |
|         int fieldLengthIndex = record.indexOf(':',fieldNameIndex);  // find the size delimiter
 | |
|         int dataTypeIndex = -1;
 | |
|         if (fieldLengthIndex >= 0)
 | |
|         {
 | |
|           dataTypeIndex = record.indexOf(':',fieldLengthIndex+1);  // check for a second : indicating there is a data type
 | |
|           if (dataTypeIndex > closingBracketIndex)
 | |
|             dataTypeIndex = -1; // second : was found but it was beyond the closing >
 | |
|         }
 | |
| 
 | |
|         if ((closingBracketIndex > fieldNameIndex) && (fieldLengthIndex > fieldNameIndex) && (fieldLengthIndex< closingBracketIndex))
 | |
|         {
 | |
|             int fieldLengthCharCount = closingBracketIndex - fieldLengthIndex -1;
 | |
|             if (dataTypeIndex >= 0)
 | |
|               fieldLengthCharCount -= 2; // data type indicator is always a colon followed by a single character
 | |
|             QString fieldLengthString = record.mid(fieldLengthIndex+1,fieldLengthCharCount);
 | |
|             int fieldLength = fieldLengthString.toInt();
 | |
|             if (fieldLength > 0)
 | |
|             {
 | |
|               QString field = record.mid(closingBracketIndex+1,fieldLength);
 | |
|               return field;
 | |
|             }
 | |
|        }
 | |
|     }
 | |
|     return "";
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| void ADIF::load()
 | |
| {
 | |
|     _data.clear();
 | |
|     QFile inputFile(_filename);
 | |
|     if (inputFile.open(QIODevice::ReadOnly))
 | |
|     {
 | |
|       QTextStream in(&inputFile);
 | |
|       QString buffer;
 | |
|       bool pre_read {false};
 | |
|       int end_position {-1};
 | |
| 
 | |
|       // skip optional header record
 | |
|       do
 | |
|         {
 | |
|           buffer += in.readLine () + '\n';
 | |
|           if (buffer.startsWith (QChar {'<'})) // denotes no header
 | |
|             {
 | |
|               pre_read = true;
 | |
|             }
 | |
|           else
 | |
|             {
 | |
|               end_position = buffer.indexOf ("<EOH>", 0, Qt::CaseInsensitive);
 | |
|             }
 | |
|         }
 | |
|       while (!in.atEnd () && !pre_read && end_position < 0);
 | |
|       if (!pre_read)            // found header
 | |
|         {
 | |
|           buffer.remove (0, end_position + 5);
 | |
|         }
 | |
|       while (buffer.size () || !in.atEnd ())
 | |
|         {
 | |
|           do
 | |
|             {
 | |
|               end_position = buffer.indexOf ("<EOR>", 0, Qt::CaseInsensitive);
 | |
|               if (!in.atEnd () && end_position < 0)
 | |
|                 {
 | |
|                   buffer += in.readLine () + '\n';
 | |
|                 }
 | |
|             }
 | |
|           while (!in.atEnd () && end_position < 0);
 | |
|           int record_length {end_position >= 0 ? end_position + 5 : -1};
 | |
|           auto record = buffer.left (record_length).trimmed ();
 | |
|           auto next_record = buffer.indexOf (QChar {'<'}, record_length);
 | |
|           buffer.remove (0, next_record >=0 ? next_record : buffer.size ());
 | |
|           record = record.mid (record.indexOf (QChar {'<'}));
 | |
|           add (extractField (record, "CALL")
 | |
|                , extractField (record, "BAND")
 | |
|                , extractField (record, "MODE")
 | |
|                , extractField (record, "SUBMODE")
 | |
|                , extractField (record, "QSO_DATE"));
 | |
|         }
 | |
|         inputFile.close ();
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| void ADIF::add(QString const& call, QString const& band, QString const& mode, QString const& submode, QString const& date)
 | |
| {
 | |
|     QSO q;
 | |
|     q.call = call;
 | |
|     q.band = band;
 | |
|     q.mode = mode;
 | |
|     q.submode = submode;
 | |
|     q.date = date;
 | |
|     if (q.call.size ())
 | |
|       {
 | |
|         _data.insert(q.call,q);
 | |
|         // qDebug() << "Added as worked:" << call << band << mode << date;
 | |
|       }
 | |
| }
 | |
| 
 | |
| // return true if in the log same band
 | |
| bool ADIF::match(QString const& call, QString const& band) const
 | |
| {
 | |
|     QList<QSO> qsos = _data.values(call);
 | |
|     if (qsos.size()>0)
 | |
|     {
 | |
|         QSO q;
 | |
|         foreach(q,qsos)
 | |
|         {
 | |
|             if (     (band.compare(q.band,Qt::CaseInsensitive) == 0)
 | |
|                   || (band=="")
 | |
|                   || (q.band==""))
 | |
|             {
 | |
|                 return true;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     return false;
 | |
| }    
 | |
| 
 | |
| QList<QString> ADIF::getCallList() const
 | |
| {
 | |
|     QList<QString> p;
 | |
|     QMultiHash<QString,QSO>::const_iterator i = _data.constBegin();
 | |
|      while (i != _data.constEnd())
 | |
|      {
 | |
|          p << i.key();
 | |
|          ++i;
 | |
|      }
 | |
|     return p;
 | |
| }
 | |
| 
 | |
| 
 | |
|     
 | |
| int ADIF::getCount() const
 | |
| {
 | |
|     return _data.size();
 | |
| }   
 | |
|     
 | |
| QByteArray ADIF::QSOToADIF(QString const& hisCall, QString const& hisGrid, QString const& mode, QString const& submode
 | |
|                            , QString const& rptSent, QString const& rptRcvd, QDateTime const& dateTimeOn
 | |
|                            , QDateTime const& dateTimeOff, QString const& band, QString const& comments
 | |
|                            , QString const& name, QString const& strDialFreq, QString const& m_myCall
 | |
|                            , QString const& m_myGrid, QString const& m_txPower, QString const& operator_call)
 | |
| {
 | |
|   QString t;
 | |
|   t = "<call:" + QString::number(hisCall.length()) + ">" + hisCall;
 | |
|   t += " <gridsquare:" + QString::number(hisGrid.length()) + ">" + hisGrid;
 | |
|   t += " <mode:" + QString::number(mode.length()) + ">" + mode;
 | |
|   if(!submode.isEmpty()){
 | |
|     t += " <submode:" + QString::number(submode.length()) + ">" + submode;
 | |
|   }
 | |
|   t += " <rst_sent:" + QString::number(rptSent.length()) + ">" + rptSent;
 | |
|   t += " <rst_rcvd:" + QString::number(rptRcvd.length()) + ">" + rptRcvd;
 | |
|   t += " <qso_date:8>" + dateTimeOn.date().toString("yyyyMMdd");
 | |
|   t += " <time_on:6>" + dateTimeOn.time().toString("hhmmss");
 | |
|   t += " <qso_date_off:8>" + dateTimeOff.date().toString("yyyyMMdd");
 | |
|   t += " <time_off:6>" + dateTimeOff.time().toString("hhmmss");
 | |
|   t += " <band:" + QString::number(band.length()) + ">" + band;
 | |
|   t += " <freq:" + QString::number(strDialFreq.length()) + ">" + strDialFreq;
 | |
|   t += " <station_callsign:" + QString::number(m_myCall.length()) + ">" +
 | |
|       m_myCall;
 | |
|   t += " <my_gridsquare:" + QString::number(m_myGrid.length()) + ">" +
 | |
|       m_myGrid;
 | |
|   if (m_txPower != "")
 | |
|     t += " <tx_pwr:" + QString::number(m_txPower.length()) +
 | |
|         ">" + m_txPower;
 | |
|   if (comments != "")
 | |
|     t += " <comment:" + QString::number(comments.length()) +
 | |
|         ">" + comments;
 | |
|   if (name != "")
 | |
|     t += " <name:" + QString::number(name.length()) +
 | |
|         ">" + name;
 | |
|   if (operator_call!="")
 | |
|       t+=" <operator:" + QString::number(operator_call.length()) +
 | |
|               ">" + operator_call;
 | |
|   return t.toLatin1 ();
 | |
| }
 | |
| 
 | |
| 
 | |
| // open ADIF file and append the QSO details. Return true on success
 | |
| bool ADIF::addQSOToFile(QByteArray const& ADIF_record)
 | |
| {
 | |
|     QFile f2(_filename);
 | |
|     if (!f2.open(QIODevice::Text | QIODevice::Append))
 | |
|         return false;
 | |
|     else
 | |
|     {
 | |
|         QTextStream out(&f2);
 | |
|         if (f2.size()==0)
 | |
|             out << "JS8Call ADIF Export<eoh>" << endl;  // new file
 | |
| 
 | |
|         out << ADIF_record << " <eor>" << endl;
 | |
|         f2.close();
 | |
|     }
 | |
|     return true;
 | |
| }
 | 
