From 9384102e8c24b2d89640a8a878887dc9cc57e0cf Mon Sep 17 00:00:00 2001
From: OH1KH
Date: Sat, 7 May 2022 09:28:21 +0300
Subject: [PATCH 1/2] Fixes to mode/submode handling
This fix does not affect "classic" modes CW,AM,FM and SSB that already has had conversion from USB/LSB to SSB.
How ever there are hundreds of submodes in adif standard.
IMHO the idea of mode and submode is not very clever. I would like to see all submodes
to be modes, and then then there would be modegroups instead.
This way mode would be mandatory information and modegroup just makes genres of them if that is needed for awards or other kinds of grouping.
But we have to live with this. This fix makes conversion from mode+submode to "CqrMode"
that mainly is submode in ADIF standard. How ever there are some exceptions.
A part of submodes are "for import only" by ADIF standard. They should be accepted in
import, but never exported. It seems that at least eQSL does not follow that standard
sending mode:RTTY submode:ASCI in doenwload if user has uploaded it that way to eQSL.
Another execptions come from Cqrlog itself. Mentioned submodes LSB and USB are logged
in Cqrlog as SSB (that is the mode, not submode).
Then rigctld may set mode to PACKET, USBPACKET... etc. with Icom rigs in data mode.
This, if logged that way, is not ADIF standard mode and must be converted to PKT that
is ADIF standard mode.
To do these conversions we need function/procedure "ModeToCqr()" and "ModeFromCqr()"
Those functions use conversion tables from files "submode_mode.txt" (the main mode/submode table), "import_mode.txt" (table of import only submodes) and "exception_mode.txt" (special conversion for Cqrlog in/out)
If files do not exist they are created at Cqrlog start to ~/.config/cqrlog folder with breaf "README_modefiles" explanation file.
After that files are not touched and user can make changes by himself without programming and compile if something changes in ADIF standard.
Files are loaded to string lists at Cqrlog start.
"ModeToCqr()" and "ModeFromCqr()" usage is added to all routines that uses ADIF import or export.
Excluding online logging. I do not use them, can not test, and did not find explanation of their API and mode/submode usage there.
There is still work to do with exports as I have seen that there are many export routines
doing same kind of jobs that could be combined to one "common export" or "create adif record" procedure. That maybe later...
---------------
Help files updated (Quick start/modes)
---------------
Improved external database server's backups script. Makes now one common mysqldump from all
cqr* databases and separate dumps from each one with date/time stamp on filename.
---------------
Squashed commit of the following:
commit dc1ca22633eefa9365961a551e6b9d1585f23cc8
Author: OH1KH
Date: Fri May 6 17:35:47 2022 +0300
Fixed some comments
commit 4ec5ddf25c37de627a5d8fc876add35aee5f6de9
Author: OH1KH
Date: Thu May 5 20:03:17 2022 +0300
Changed modefile directory. Updated help files
commit 7a0c5de47f5e3de58f4ab9f364892bdc92f1aa62
Author: OH1KH
Date: Thu May 5 13:10:03 2022 +0300
Assigned and tested eQSL and LoTW uploads. For other uploads: checked them, but cannot be sure with online logs (I can not test them)
commit dfb35ef2df5bec37913d3150f9dc5afb2386b477
Author: OH1KH
Date: Thu May 5 11:18:45 2022 +0300
Tested eQSl and LoTW downloads
commit 79a2072d21cc82db4028362b4da58a02f637d5ea
Author: OH1KH
Date: Wed May 4 19:06:11 2022 +0300
Fixed debug printing. Tested: adif export and import
commit 5f86f8899c6c9b3d8fbd849115d8ef3147166e73
Author: OH1KH
Date: Wed May 4 11:47:53 2022 +0300
Tested: fldigi remote ipc and xmlrpc, fldigi (old version) xmlrpc, adif remote
commit 88774fcd12556fb59043805f211be07f7d9dd7c7
Author: OH1KH
Date: Wed May 4 10:31:27 2022 +0300
Fixed external database's backups script
commit 3f4198f0ce4dfb1d227cd9b06798294ec1a7d457
Author: OH1KH
Date: Tue May 3 11:48:35 2022 +0300
fixed adif import and export. TODO: test all adif import/export, lotw/eqsl import/export, remotes: fldigi ipc/xml, adif
commit 891674a2346e0f402d301711e32a7dcdba697aef
Author: OH1KH
Date: Sun May 1 17:35:33 2022 +0300
new conversion now in: fldigixml,adifremote, fldigiipc,lotw and eqsl import. Partilly added also to adif import but this is not finished yet
commit 050b35f3e69ea7254c71590874c50d46f7a9f3f6
Author: OH1KH
Date: Sat Apr 30 10:01:56 2022 +0300
Ficed naming, created a debug procedure and put in use with fldigi(others still need appending)
commit a03c1758851d19a5f7f5fccbf09b5638da583f6f
Author: OH1KH
Date: Fri Apr 29 13:30:31 2022 +0300
Mode conversion idea works now.
creates convert files if they do not exist in ctyfiles folder.
Fileas are loaded from Cqrlog start, so user can edit files
if needed new mode conversions without doing compile.
fxfldigi.pas still has testing lines, must remove
todo
take conversions in use (adif ex/import, eQSL, Lotw, adif remote, fldigi remote)
---
help/h1.html | 43 ++++++-
src/dLogUpload.pas | 4 +
src/dUtils.lfm | 14 +--
src/dUtils.pas | 270 +++++++++++++++++++++++++++++++++++++++-
src/fAdifImport.pas | 99 +++++++--------
src/fCabrilloExport.pas | 2 +
src/fDbSqlSel.pas | 30 ++++-
src/fEDIExport.pas | 2 +
src/fExportProgress.pas | 124 ++----------------
src/fImportProgress.pas | 186 ++++++++++++++-------------
src/fLoTWExport.pas | 48 +++----
src/fMain.pas | 3 +-
src/fNewQSO.pas | 47 +++----
src/fSOTAExport.pas | 3 +
src/fXfldigi.pas | 9 +-
src/feQSLUpload.pas | 45 +++----
src/uADIFhash.pas | 1 +
src/uVersion.pas | 2 +-
18 files changed, 562 insertions(+), 370 deletions(-)
diff --git a/help/h1.html b/help/h1.html
index 7c4b567..40c00d6 100644
--- a/help/h1.html
+++ b/help/h1.html
@@ -320,8 +320,47 @@ Some TRX like ICOM don't have support for this in HamLib. To get mode se
all values to 0 (zero).
User definable digital modes can be set up in a separate box. Use comma
as a separator, ie. MYMODE1,MYMODE2 etc.
-If user adds digital modes (submode names) exactly as written in this table ADIF.org: Mode_Enumeration ADIF export will place correct mode and submode tags to exported file.
- Submode list is copied at 2021-08-25 and may need updating of source code some day in future.
+user should add digital modes (submode names) exactly as written in this table ADIF.org: Mode_Enumeration
+If mode is missing from NewQSO/mode selection list and not added to User defined digital modes it may prevent ADIF import causing "wrong mode" error.
+
+Note:
+Cqrlog uses internally modefied mode name. We call it here CqrMode. CqrMode is created from ADIF mode and submode with conversion table. CqrMode is mainly ADIF submode if it exist, with some exceptions.
+
Cqrlog will create four files in ~/.config/cqrlog folder for this use if they do not exist. One is a brief README_modefiles explaining three other files purposes.
+
If files exist they are not overwritten keeping possible user changes there. How ever user must do backups by himself if files are edited from original format.
+These files apply to all logs created. They are not log based.
+
+- submode_mode.txt
+
This file holds submode=mode pairs used to convert incoming mode+submode pair to CqrMode that mainly is the submode.
+
All pairs must be in uppercase format. User can add or delete mode pairs with text editor if definition at
+
ADIF.org: Mode_Enumeration changes.
+
"Self invented" mode names should not be used! Just one mode pair is accepted in one line.
+
The first line is never read (lower case). It just shows the order of submode and mode.
+
This file is used also when qso record is ADIF exported. Then CqrMode is converted back to mode+sumbode tags.
+
+
+- import_mode.txt
+
This file holds a list of deprecated ADIF submodes that are accepted only for input. They are used in CqrModes but they will never be ADIF exported out from Cqrlog.
+
All lines must be in uppercase format. User can add or delete lines with text editor if definition at
+
ADIF.org: Mode_Enumeration changes.
+
"Self invented" mode names should not be used! Just one mode is accepted in one line.
+
The first line is never read (lower case). It just shows the meaning of then list.
+
This file is used also when qso record is ADIF exported. It prevents submode in list to export and only mode is exported.
+
+
+
+- exception_mode.txt
+
This file holds submode=mode pairs used to convert incoming mode+submode pair to CqrMode when CqrMode can not use ADIF submode directly.
+
For example by ADIF definition mode SSB has submodes USB and LSB. How ever Cqrlog does not use those as CqrMode, but uses only SSB.
+ Then CqrMode is converted as SSB. How ever after exception the mode can not have it's submode back when exporting ADIF from Cqrlog.
+
This file can also have conversion from rigctld given mode to ADIF mode. For example with IC7300 rigctld shows mode PACKETUSB if rig is set to usb and data mode:
+
then this file can convert PACKETUSB to PKT that is ADIF standard format.
+
All pairs must be in uppercase format. User can add or delete mode pairs with text editor when needed.
+
How ever in case of outgoing modes (outgoing mode is at right side of mode pair) ADIF.org: Mode_Enumeration should be used.
+
"Self invented" mode names should not be used! Just one mode pair is accepted in one line.
+
The first line is never read (lower case). It just shows the order of submode and mode.
+
+
+
QTH Profiles
diff --git a/src/dLogUpload.pas b/src/dLogUpload.pas
index 660385d..06a72f9 100644
--- a/src/dLogUpload.pas
+++ b/src/dLogUpload.pas
@@ -514,6 +514,10 @@ begin
time_on := Q2.FieldByName('time_on').AsString;
time_on := copy(time_on,1,2) + copy(time_on,4,2);
+ //2022-05-05 OH1KH I do not know (I can not test) are mode+submode pairs needed with log uploads
+ // or is the CqrMode ok here ???????
+ //If mode+submode needed then use dmUtils.ModeFromCqr to get mode and submode at this point
+ // (look sample from fLoTWExport.pas line 453-460)
adif := GetAdifValue('QSO_DATE',qsodate)+GetAdifValue('TIME_ON',time_on)+
GetAdifValue('CALL',Q2.FieldByName('callsign').AsString)+
GetAdifValue('BAND',Q2.FieldByName('band').AsString)+
diff --git a/src/dUtils.lfm b/src/dUtils.lfm
index beb3064..2b4cc45 100644
--- a/src/dUtils.lfm
+++ b/src/dUtils.lfm
@@ -1,26 +1,26 @@
object dmUtils: TdmUtils
OnCreate = DataModuleCreate
+ OnDestroy = DataModuleDestroy
OldCreateOrder = False
Height = 300
HorizontalOffset = 365
VerticalOffset = 366
Width = 400
- PPI = 96
object HelpDatabase: THTMLHelpDatabase
BaseURL = 'file:///usr/share/cqrlog/help'
AutoRegister = True
KeywordPrefix = 'help/'
- left = 176
- top = 40
+ Left = 176
+ Top = 40
end
object HelpViewer: THTMLBrowserHelpViewer
BrowserParams = '%s'
AutoRegister = True
- left = 272
- top = 40
+ Left = 272
+ Top = 40
end
object Datasource1: TDataSource
- left = 56
- top = 48
+ Left = 56
+ Top = 48
end
end
diff --git a/src/dUtils.pas b/src/dUtils.pas
index de78870..dc3560e 100644
--- a/src/dUtils.pas
+++ b/src/dUtils.pas
@@ -88,6 +88,12 @@ const
'NAME_INTL', 'NOTES_INTL', 'QSLMSG_INTL', 'QTH_INTL',
'RIG_INTL', 'SIG_INTL', 'SIG_INFO_INTL');
+ c_MODEFILE_DIR = ''; // 'ctyfiles/';
+ C_SUBMODE_FILE = 'submode_mode.txt';
+ C_IMPORTMODE_FILE = 'import_mode.txt';
+ C_EXCEPMODE_FILE = 'exception_mode.txt';
+ C_READMEMODE_FILE = 'README_modefiles';
+
type
{ TdmUtils }
@@ -97,16 +103,21 @@ type
HelpViewer: THTMLBrowserHelpViewer;
HelpDatabase: THTMLHelpDatabase;
procedure DataModuleCreate(Sender: TObject);
+ procedure DataModuleDestroy(Sender: TObject);
private
fTimeOffset: currency;
fGrayLineOffset: currency;
fQRZSession: string;
fHamQTHSession: string;
fSysUTC: boolean;
-
+ SubmodeMode: TStringList;
+ ImportMode : TStringlist;
+ ExceptMode : TStringlist;
procedure LoadRigList(RigCtlBinaryPath : String;RigList : TStringList);
procedure LoadRigListCombo(CurrentRigId : String; RigList : TStringList; RigComboBox : TComboBox);
+ procedure ModeConvListsCreate(SetUp:boolean);
+ procedure MakeMissingModeFile(num:integer);
function nr(ch: char): integer;
function GetTagValue(Data, tg: string): string;
@@ -116,6 +127,7 @@ type
var nick, qth, address, zip, grid, state, county, qsl, iota, waz, itu, ErrMsg: string): boolean;
function GetHamQTHInfo(call: string;
var nick, qth, address, zip, grid, state, county, qsl, iota, waz, itu, dok, ErrMsg: string): boolean;
+
public
s136: string;
s630: string;
@@ -152,6 +164,7 @@ type
//list of bands, band labels
BandFreq : array [0..cMaxBandsCount - 1]of BandVsFreq;
+
property TimeOffset: currency read fTimeOffset write fTimeOffset;
property GrayLineOffset: currency read fGraylineOffset write fGrayLineOffset;
property SysUTC: boolean read fSysUTC write fSysUTC;
@@ -204,11 +217,12 @@ type
procedure LoadRigsToComboBox(CurrentRigId : String; RigCtlBinaryPath : String; RigComboBox : TComboBox);
procedure GetShorterCoordinates(latitude,longitude : Currency; var lat, long : String);
procedure LoadListOfFiles(Path, Mask : String; ListOfFiles : TStringList);
- procedure BandFromDbase;
+ procedure BandFromDbase;
procedure UpdateHelpBrowser;
+ procedure ModeFromCqr(CqrMode:String;var OutMode,OutSubmode:String;dbg:Boolean);
function BandFromArray(tmp:Currency):string;
- function MyDefaultBrowser:String;
+ function MyDefaultBrowser:String;
function StrToDateFormat(sDate : String) : TDateTime;
function DateToSQLIteDate(date : TDateTime) : String;
function GetBandFromFreq(MHz : string): String;
@@ -297,6 +311,8 @@ type
function LoadVisibleColumnsConfiguration : TColumnVisibleArray;
function StdFormatLocator(loc:string):String;
function IsHeDx(call:String; CqDir:String = ''):boolean;
+ function ModeToCqr(InMode,InSubmode:String;dbg:boolean=False):String;
+
end;
@@ -598,7 +614,14 @@ begin
USstates[49] := 'WV, West Virginia';
USstates[50] := 'WY, Wyoming';
+ ModeConvListsCreate(True);
end;
+
+procedure TdmUtils.DataModuleDestroy(Sender: TObject);
+begin
+ ModeConvListsCreate(False);
+end;
+
procedure TdmUtils.InsertContests(cmbContestName: TComboBox);
var
ListOfContests : TStringList;
@@ -4774,5 +4797,246 @@ begin
Writeln('My continent is:', mycont, ' His continent is:', cont,' is DX/CQ for me:',Result);
end;
end;
+
+procedure TdmUtils.ModeFromCqr(CqrMode:String;var OutMode,OutSubmode:String;dbg:Boolean);
+//encodes Cqrlog's mode to mode and submode pair
+//returns empty string to submode if not exist
+var
+ e: integer;
+
+Begin
+ if dbg then
+ Writeln('ModeFromCqr: ',CqrMode);
+ Cqrmode:=uppercase(CqrMode); //this is for sure
+ //cqrmode -> ex_mode
+ e:= ExceptMode.IndexOfName(CqrMode);
+ if e > -1 then
+ Begin
+ OutMode := uppercase(ExceptMode.Values[CqrMode]);
+ OutSubmode:='';
+ if dbg then
+ begin
+ Writeln('ex_mode=cqrlogmode line: ',e+1);
+ Writeln('Cqrlog will export adif as mode: ',OutMode,' submode: ',OutSubmode);
+ end;
+ exit;
+ end;
+ // cqrmode -> mode+submode
+ e:= SubmodeMode.IndexOfName(CqrMode);
+ if e > -1 then
+ Begin
+ OutMode := uppercase(SubmodeMode.Values[CqrMode]);
+ OutSubmode := CqrMode;
+ if dbg then
+ Writeln('submode=mode line: ',e+1);
+
+ //is submode import only
+ e:=ImportMode.IndexOf(CqrMode);
+ if e > -1 then
+ begin
+ if dbg then
+ Writeln('submode for_import_only line: ',e+1);
+ OutSubmode :='';
+ end;
+ end
+ else
+ //no submodes
+ Begin
+ OutMode := CqrMode;
+ OutSubmode:='';
+ end;
+ if dbg then
+ Writeln('Cqrlog will export adif as mode: ',OutMode,' submode: ',OutSubmode);
+end;
+function TdmUtils.ModeToCqr(InMode,InSubmode:String;dbg:boolean=False):String;
+//decodes mode and submode pair to mode used by Cqrlog internally
+var
+ e: integer;
+
+Begin
+ if dbg then
+ Writeln('ModeToCqr mode: ',InMode,' submode: ',InSubmode);
+ InMode:=uppercase(InMode); //this is for sure
+ InSubmode:=uppercase(InSubmode);
+
+ Result:=InMode; //defaults to InMode
+ if InSubmode='' then
+ Begin
+ if dbg then
+ writeln('Cqrlog internal mode will be: ',Result);
+ exit;
+ end;
+
+ e:= SubmodeMode.IndexOfName(InSubmode);
+ if (e > -1 ) then //it exist
+ Begin
+ if dbg then
+ Writeln('submode=mode line: ',e+1);
+ Result:=InSubmode;
+ end;
+
+ e:= ExceptMode.IndexOfName(Result);
+ if e > -1 then //it exist
+ begin
+ if dbg then
+ Writeln('ex_mode=cqrlogmode line: ',e+1);
+ Result:= ExceptMode.ValueFromIndex[e];
+ end;
+
+ Result:=uppercase(Result); //this is for sure
+ if dbg then
+ writeln('Cqrlog internal mode will be: ',Result);
+end;
+procedure TdmUtils.ModeConvListsCreate(SetUp:boolean);
+
+Begin
+ if not SetUp then
+ Begin
+ if assigned(SubmodeMode) then FreeAndNil(SubmodeMode);
+ if assigned(ImportMode) then FreeAndNil(ImportMode);
+ if assigned(ExceptMode) then FreeAndNil(ExceptMode);
+ exit;
+ end;
+
+ SubmodeMode:= TStringList.Create;
+ ImportMode := TStringlist.Create;
+ ExceptMode := TStringlist.Create;
+
+ //if we do not find one of these files we create it
+ if FileSearch(C_SUBMODE_FILE,dmData.HomeDir+C_MODEFILE_DIR,[])='' then
+ MakeMissingModeFile(1);
+ if FileSearch(C_IMPORTMODE_FILE,dmData.HomeDir+C_MODEFILE_DIR,[])='' then
+ MakeMissingModeFile(2);
+ if FileSearch(C_EXCEPMODE_FILE,dmData.HomeDir+C_MODEFILE_DIR,[])='' then
+ MakeMissingModeFile(3);
+ if FileSearch(C_READMEMODE_FILE,dmData.HomeDir+C_MODEFILE_DIR,[])='' then
+ MakeMissingModeFile(4);
+ try
+ SubmodeMode.LoadFromFile(dmData.HomeDir+C_MODEFILE_DIR+C_SUBMODE_FILE);
+ ImportMode .LoadFromFile(dmData.HomeDir+C_MODEFILE_DIR+C_IMPORTMODE_FILE);
+ ExceptMode.LoadFromFile(dmData.HomeDir+C_MODEFILE_DIR+C_EXCEPMODE_FILE);
+ except
+ on E : Exception do writeln('Could not load mode conversion files!');
+ end;
+
+ if dmData.DebugLevel>=1 then
+ Begin
+ Writeln('Loaded mode conversion files:');
+ Writeln(' ',SubmodeMode.Strings[0]);
+ Writeln(' ',ImportMode.Strings[0]);
+ Writeln(' ',ExceptMode.Strings[0]);
+ end;
+
+
+end;
+
+
+procedure TdmUtils.MakeMissingModeFile(num:integer);
+//the idea not to use const for conversion is that when they are put in files
+//later additions and deletions can be done by user without compile
+Const
+ S_file: array [1..168] of string = (
+ 'submode=mode','8PSK125=PSK','8PSK125F=PSK','8PSK125FL=PSK','8PSK250=PSK','8PSK250F=PSK','8PSK250FL=PSK','8PSK500=PSK','8PSK500F=PSK','8PSK1000=PSK',
+ '8PSK1000F=PSK','8PSK1200F=PSK','AMTORFEC=TOR','ASCI=RTTY','CHIP64=CHIP','CHIP128=CHIP','DOM-M=DOMINO','DOM4=DOMINO','DOM5=DOMINO','DOM8=DOMINO',
+ 'DOM11=DOMINO','DOM16=DOMINO','DOM22=DOMINO','DOM44=DOMINO','DOM88=DOMINO','DOMINOEX=DOMINO','DOMINOF=DOMINO','FMHELL=HELL','FSK31=PSK','FSKHELL=HELL',
+ 'FSQCALL=MFSK','FST4=MFSK','FST4W=MFSK','FT4=MFSK','GTOR=TOR','HELL80=HELL','HELLX5=HELL','HELLX9=HELL','HFSK=HELL','ISCAT-A=ISCAT',
+ 'ISCAT-B=ISCAT','JS8=MFSK','JT4A=JT4','JT4B=JT4','JT4C=JT4','JT4D=JT4','JT4E=JT4','JT4F=JT4','JT4G=JT4','JT9-1=JT9',
+ 'JT9-2=JT9','JT9-5=JT9','JT9-10=JT9','JT9-30=JT9','JT9A=JT9','JT9B=JT9','JT9C=JT9','JT9D=JT9','JT9E=JT9','JT9E=FAST',
+ 'JT9F=JT9','JT9F=FAST','JT9G=JT9','JT9G=FAST','JT9H=JT9','JT9H=FAST','JT65A=JT65','JT65B=JT65','JT65B2=JT65','JT65C=JT65',
+ 'JT65C2=JT65','JTMS=MFSK','LSB=SSB','MFSK4=MFSK','MFSK8=MFSK','MFSK11=MFSK','MFSK16=MFSK','MFSK22=MFSK','MFSK31=MFSK','MFSK32=MFSK',
+ 'MFSK64=MFSK','MFSK64L=MFSK','MFSK128=MFSK','MFSK128L=MFSK','NAVTEX=TOR','OLIVIA 4/125=OLIVIA','OLIVIA 4/250=OLIVIA','OLIVIA 8/250=OLIVIA','OLIVIA 8/500=OLIVIA','OLIVIA 16/500=OLIVIA',
+ 'OLIVIA 16/1000=OLIVIA','OLIVIA 32/1000=OLIVIA','OPERA-BEACON=OPERA','OPERA-QSO=OPERA','PAC2=PAC','PAC3=PAC','PAC4=PAC','PAX2=PAX','PCW=CW','PSK10=PSK',
+ 'PSK31=PSK','PSK63=PSK','PSK63F=PSK','PSK63RC10=PSK','PSK63RC20=PSK','PSK63RC32=PSK','PSK63RC4=PSK','PSK63RC5=PSK','PSK125=PSK','PSK125RC10=PSK','PSK125RC12=PSK',
+ 'PSK125RC16=PSK','PSK125RC4=PSK','PSK125RC5=PSK','PSK250=PSK','PSK250RC2=PSK','PSK250RC3=PSK','PSK250RC5=PSK','PSK250RC6=PSK','PSK250RC7=PSK','PSK500=PSK',
+ 'PSK500RC2=PSK','PSK500RC3=PSK','PSK500RC4=PSK','PSK800RC2=PSK','PSK1000=PSK','PSK1000RC2=PSK','PSKAM10=PSK','PSKAM31=PSK','PSKAM50=PSK','PSKFEC31=PSK',
+ 'PSKHELL=HELL','QPSK31=PSK','Q65=MFSK','QPSK63=PSK','QPSK125=PSK','QPSK250=PSK','QPSK500=PSK','QRA64A=QRA64','QRA64B=QRA64','QRA64C=QRA64',
+ 'QRA64D=QRA64','QRA64E=QRA64','ROS-EME=ROS','ROS-HF=ROS','ROS-MF=ROS','SIM31=PSK','SITORB=TOR','SLOWHELL=HELL','THOR-M=THOR','THOR4=THOR',
+ 'THOR5=THOR','THOR8=THOR','THOR11=THOR','THOR16=THOR','THOR22=THOR','THOR25X4=THOR','THOR50X1=THOR','THOR50X2=THOR','THOR100=THOR','THRBX=THRB',
+ 'THRBX1=THRB','THRBX2=THRB','THRBX4=THRB','THROB1=THRB','THROB2=THRB','THROB4=THRB','USB=SSB'
+ );
+ I_file: array [1 .. 41] of string = (
+ 'for_import_only','AMTORFEC','ASCI','CHIP64','CHIP128','DOMINOF','FMHELL','FSK31','GTOR','HELL80',
+ 'HFSK','JT4A','JT4B','JT4C','JT4D','JT4E','JT4F','JT4G','JT65A','JT65B',
+ 'JT65C','MFSK8','MFSK16','PAC2','PAC3','PAX2','PCW','PSK10','PSK31','PSK63',
+ 'PSK63F','PSK125','PSKAM10','PSKAM31','PSKAM50','PSKFEC31','PSKHELL','QPSK31','QPSK63','QPSK125',
+ 'THRBX'
+ );
+
+ {Exceptions file:
+ Cqrlog uses SSB for both USB and LSB
+ Cqrlog uses RTTY, some programs may export ASCI even when it is import only!
+ 'PACKET':
+ these modes come from ICOM rig (IC7300) when DATA is selected with USB,LSB,FM or AM
+ and checkbox "auto" for mode is selected in NewQSO we put them all to PKT category here
+ as it is in ADIF standard
+ }
+ E_file: array [1 .. 9] of string = (
+ 'ex_mode=cqrlogmode',
+ 'USB=SSB',
+ 'LSB=SSB',
+ 'ASCI=RTTY',
+ 'PACKET=PKT',
+ 'PKTUSB=PKT',
+ 'PKTLSB=PKT',
+ 'PKTFM=PKT',
+ 'PKTAM=PKT'
+ );
+ R_file: array [1 .. 22] of string = (
+ 'Files to modify ADIF mode+submode to fit with Cqrlog.',
+ 'Cqrlog internally uses submodes as mode. (only one database column -> mode)',
+ '',
+ 'These files are manually created and can be changed if needed:',
+ 'Contents are read to TStringLists at program start.',
+ '',
+ 'submode_mode.txt',
+ ' Submode=Mode',
+ ' Used en/decoding mode-submode pairs for Cqrlog.',
+ '',
+ 'import_mode.txt',
+ ' Submode list for import only',
+ ' Used to define deprecated submodes that are used ony for adif input.',
+ ' These submodes do not export.',
+ '',
+ 'exception_mode.txt',
+ ' mode=cqrlogmode',
+ ' Exceptions between "true" (sub)modes and internal cqrlog mode',
+ ' Converts also in export "non adif" modes from rigctld like PACKET -> PKT',
+ '',
+ 'Two first files created by https://adif.org/312/ADIF_312_annotated.htm#Mode_Enumeration',
+ 'informations 2022-04-29,'
+ );
+ var f:TextFile;
+
+
+//--------------------------------------------------------
+ procedure CreaFile(Fname:string;items:array of string);
+ var
+ i: integer;
+ itemsmax:integer;
+
+ begin
+ itemsmax:=length(items);
+ AssignFile(f,Fname);
+ try
+ rewrite(f);
+ try
+ for i:= 0 to itemsmax-1 do
+ Writeln(f, items[i]);
+ finally
+ CloseFile(f);
+ end;
+ except
+ on E: EInOutError do
+ ShowMessage('File handling error occurred. Details: ' + E.ClassName + '/' + E.Message);
+ end;
+ end;
+//--------------------------------------------------------
+Begin
+ if num=1 then CreaFile(dmData.HomeDir+C_MODEFILE_DIR+C_SUBMODE_FILE,S_file);
+ if num=2 then CreaFile(dmData.HomeDir+C_MODEFILE_DIR+C_IMPORTMODE_FILE,I_file);
+ if num=3 then CreaFile(dmData.HomeDir+C_MODEFILE_DIR+C_EXCEPMODE_FILE,E_file);
+ if num=4 then CreaFile(dmData.HomeDir+C_MODEFILE_DIR+C_READMEMODE_FILE,R_file);
+end;
+
end.
diff --git a/src/fAdifImport.pas b/src/fAdifImport.pas
index 8d01b41..0021cc2 100644
--- a/src/fAdifImport.pas
+++ b/src/fAdifImport.pas
@@ -46,6 +46,7 @@ type TnewQSOEntry=record //represents a new qso entry in the log
LOTW_QSL_RCVD:string[l_LOTW_QSL_RCVD];
LOTW_QSL_SENT:string[l_LOTW_QSL_SENT];
MODE:string[l_MODE];
+ SUBMODE:string[l_SUBMODE]; //we need this while processing cqrmode
MY_GRIDSQUARE:string[l_MY_GRIDSQUARE];
NAME:string[l_NAME];
NOTES:string[l_NOTES];
@@ -140,7 +141,6 @@ type
procedure mnueditClick(Sender: TObject);
procedure mnuImportClick(Sender: TObject);
private
- LockSubMode : boolean; //if we replace mode with submode we set lock in case that submode and mode are in opposite order in qso record.
LocalDbg : Boolean;
AbortImport : boolean;
ERR_FILE : String;
@@ -296,58 +296,44 @@ function TfrmAdifImport.fillTypeVariableWithTagData(h:longint;var data:string;va
h_LOTW_QSL_RCVD :d.LOTW_QSL_RCVD:=TrimDataLen(adifTag,data,l_LOTW_QSL_RCVD);
h_LOTW_QSL_SENT :d.LOTW_QSL_SENT:=TrimDataLen(adifTag,data,l_LOTW_QSL_SENT);
- // DL7OAP: because MODE-field in cqrlog database does not match completely
- // with MODE field of ADIF specification, we have to transfer the
- // ADIF MODES/SUBMODES (JS8, FT4, FST4,PKT) to MODE-field in cqrlog database
+ h_MODE :d.MODE := UpperCase(TrimDataLen(adifTag,data,l_MODE));
+ h_SUBMODE :d.SUBMODE := UpperCase(TrimDataLen(adifTag,data,l_SUBMODE));
- //OH1KH: we can put all submodes to mode when importing
-
- h_MODE : begin
- if not LockSubMode then //do not override mode if already set by submode
- if data = 'PKT' then d.MODE:='PACKET'
- else d.MODE:=UpperCase(TrimDataLen(adifTag,data,l_MODE));
- end;
- h_SUBMODE : begin
- // Cqrlog does not use USB and LSB (submodes)
- // but it is fixed in function saveNewEntryFromADIFinDatabase
- d.MODE:=UpperCase(TrimDataLen(adifTag,data,l_MODE));
- LockSubMode:=true;
- end;
- h_MY_GRIDSQUARE :d.MY_GRIDSQUARE:=dmUtils.StdFormatLocator(data);
- h_NAME :d.NAME:=TrimDataLen(adifTag,data,l_NAME);
- h_NOTES :d.NOTES:=TrimDataLen(adifTag,data,l_NOTES);
- h_PFX :d.PFX:=UpperCase(TrimDataLen(adifTag,data,l_PFX));
- h_QSLMSG :d.QSLMSG:=TrimDataLen(adifTag,data,l_QSLMSG);
- h_QSLRDATE :d.QSLRDATE:=TrimDataLen(adifTag,data,l_QSLRDATE);
- h_QSLSDATE :d.QSLSDATE:=TrimDataLen(adifTag,data,l_QSLSDATE);
- h_QSL_RCVD :d.QSL_RCVD:=TrimDataLen(adifTag,data,l_QSL_RCVD);
- h_QSL_SENT :d.QSL_SENT:=TrimDataLen(adifTag,data,l_QSL_SENT);
- h_QSL_VIA :d.QSL_VIA:=TrimDataLen(adifTag,data,l_QSL_VIA);
- h_QSO_DATE :d.QSO_DATE:=TrimDataLen(adifTag,data,l_QSO_DATE);
- h_QTH :d.QTH:=TrimDataLen(adifTag,data,l_QTH);
- h_RST_RCVD :d.RST_RCVD:=TrimDataLen(adifTag,data,l_RST_RCVD);
- h_RST_SENT :d.RST_SENT:=TrimDataLen(adifTag,data,l_RST_SENT);
- h_SRX :d.SRX:=TrimDataLen(adifTag,data,l_SRX);
- h_SRX_STRING :d.SRX_STRING:=TrimDataLen(adifTag,data,l_SRX_STRING);
- h_STX :d.STX:=TrimDataLen(adifTag,data,l_STX);
- h_STX_STRING :d.STX_STRING:=TrimDataLen(adifTag,data,l_STX_STRING);
- h_CONTEST_ID :d.CONTEST_ID:=TrimDataLen(adifTag,data,l_CONTEST_ID);
- h_DARC_DOK :d.DARC_DOK:=TrimDataLen(adifTag,data,l_DARC_DOK);
- h_TIME_OFF :d.TIME_OFF:=copy(data,1,4);//can be HHMMSS but cqrlog uses HHMM both
- h_TIME_ON :d.TIME_ON:=copy(data,1,4); //are valid adif forms so no Trim/Err here
- h_TX_PWR :d.TX_PWR:=TrimDataLen(adifTag,data,l_TX_PWR);
- h_APP_CQRLOG_DXCC :d.APP_CQRLOG_DXCC:=TrimDataLen(adifTag,data,l_APP_CQRLOG_DXCC);
- h_APP_CQRLOG_QSLS :d.APP_CQRLOG_QSLS:=TrimDataLen(adifTag,data,l_APP_CQRLOG_QSLS);
- h_APP_CQRLOG_PROFILE :d.APP_CQRLOG_PROFILE:=TrimDataLen(adifTag,data,l_APP_CQRLOG_PROFILE);
- h_APP_CQRLOG_QSLR :d.APP_CQRLOG_QSLR:=TrimDataLen(adifTag,data,l_APP_CQRLOG_QSLR);
- h_APP_CQRLOG_COUNTY :d.APP_CQRLOG_COUNTY:=TrimDataLen(adifTag,data,l_APP_CQRLOG_COUNTY);
- h_CQZ :d.CQZ:=TrimDataLen(adifTag,data,l_CQZ);
- h_STATE :d.STATE:=UpperCase(TrimDataLen(adifTag,data,l_STATE));
- h_AWARD :d.AWARD:=TrimDataLen(adifTag,data,l_AWARD);
- h_PROP_MODE :d.PROP_MODE:=TrimDataLen(adifTag,data,l_PROP_MODE);
- h_SAT_NAME :d.SAT_NAME:=TrimDataLen(adifTag,data,l_SAT_NAME);
- h_FREQ_RX :d.FREQ_RX:=TrimDataLen(adifTag,data,l_FREQ_RX);
- h_OP :d.OP:=TrimDataLen(adifTag,data,l_OP);
+ h_MY_GRIDSQUARE :d.MY_GRIDSQUARE:=dmUtils.StdFormatLocator(data);
+ h_NAME :d.NAME:=TrimDataLen(adifTag,data,l_NAME);
+ h_NOTES :d.NOTES:=TrimDataLen(adifTag,data,l_NOTES);
+ h_PFX :d.PFX:=UpperCase(TrimDataLen(adifTag,data,l_PFX));
+ h_QSLMSG :d.QSLMSG:=TrimDataLen(adifTag,data,l_QSLMSG);
+ h_QSLRDATE :d.QSLRDATE:=TrimDataLen(adifTag,data,l_QSLRDATE);
+ h_QSLSDATE :d.QSLSDATE:=TrimDataLen(adifTag,data,l_QSLSDATE);
+ h_QSL_RCVD :d.QSL_RCVD:=TrimDataLen(adifTag,data,l_QSL_RCVD);
+ h_QSL_SENT :d.QSL_SENT:=TrimDataLen(adifTag,data,l_QSL_SENT);
+ h_QSL_VIA :d.QSL_VIA:=TrimDataLen(adifTag,data,l_QSL_VIA);
+ h_QSO_DATE :d.QSO_DATE:=TrimDataLen(adifTag,data,l_QSO_DATE);
+ h_QTH :d.QTH:=TrimDataLen(adifTag,data,l_QTH);
+ h_RST_RCVD :d.RST_RCVD:=TrimDataLen(adifTag,data,l_RST_RCVD);
+ h_RST_SENT :d.RST_SENT:=TrimDataLen(adifTag,data,l_RST_SENT);
+ h_SRX :d.SRX:=TrimDataLen(adifTag,data,l_SRX);
+ h_SRX_STRING :d.SRX_STRING:=TrimDataLen(adifTag,data,l_SRX_STRING);
+ h_STX :d.STX:=TrimDataLen(adifTag,data,l_STX);
+ h_STX_STRING :d.STX_STRING:=TrimDataLen(adifTag,data,l_STX_STRING);
+ h_CONTEST_ID :d.CONTEST_ID:=TrimDataLen(adifTag,data,l_CONTEST_ID);
+ h_DARC_DOK :d.DARC_DOK:=TrimDataLen(adifTag,data,l_DARC_DOK);
+ h_TIME_OFF :d.TIME_OFF:=copy(data,1,4);//can be HHMMSS but cqrlog uses HHMM both
+ h_TIME_ON :d.TIME_ON:=copy(data,1,4); //are valid adif forms so no Trim/Err here
+ h_TX_PWR :d.TX_PWR:=TrimDataLen(adifTag,data,l_TX_PWR);
+ h_APP_CQRLOG_DXCC :d.APP_CQRLOG_DXCC:=TrimDataLen(adifTag,data,l_APP_CQRLOG_DXCC);
+ h_APP_CQRLOG_QSLS :d.APP_CQRLOG_QSLS:=TrimDataLen(adifTag,data,l_APP_CQRLOG_QSLS);
+ h_APP_CQRLOG_PROFILE :d.APP_CQRLOG_PROFILE:=TrimDataLen(adifTag,data,l_APP_CQRLOG_PROFILE);
+ h_APP_CQRLOG_QSLR :d.APP_CQRLOG_QSLR:=TrimDataLen(adifTag,data,l_APP_CQRLOG_QSLR);
+ h_APP_CQRLOG_COUNTY :d.APP_CQRLOG_COUNTY:=TrimDataLen(adifTag,data,l_APP_CQRLOG_COUNTY);
+ h_CQZ :d.CQZ:=TrimDataLen(adifTag,data,l_CQZ);
+ h_STATE :d.STATE:=UpperCase(TrimDataLen(adifTag,data,l_STATE));
+ h_AWARD :d.AWARD:=TrimDataLen(adifTag,data,l_AWARD);
+ h_PROP_MODE :d.PROP_MODE:=TrimDataLen(adifTag,data,l_PROP_MODE);
+ h_SAT_NAME :d.SAT_NAME:=TrimDataLen(adifTag,data,l_SAT_NAME);
+ h_FREQ_RX :d.FREQ_RX:=TrimDataLen(adifTag,data,l_FREQ_RX);
+ h_OP :d.OP:=TrimDataLen(adifTag,data,l_OP);
else begin
{ writeln('Unnamed...>',pom,'<');fillTypeVariableWithTagData:=false;exit;}
@@ -396,9 +382,11 @@ begin
if (not dmUtils.IsLocOK(d.MY_GRIDSQUARE)) or chkOverrideLocator.Checked then
d.MY_GRIDSQUARE := FMyLoc;
d.CALL := UpperCase(d.CALL);
- if (d.MODE = 'USB') or (d.MODE ='LSB') then
- d.MODE := 'SSB';
- if (d.FREQ = '') or (d.FREQ = '0') then
+
+ //convert mode and submode to cqrmode here
+ d.MODE:=dmUtils.ModeToCqr(d.MODE,d.SUBMODE,LocalDbg);
+
+ if (d.FREQ = '') or (d.FREQ = '0') then
d.FREQ := dmUtils.FreqFromBand(d.BAND,d.MODE);
d.QSO_DATE := dmUtils.ADIFDateToDate(d.QSO_DATE);
@@ -837,7 +825,6 @@ begin
WriteWrongADIF(tmp,'Imported with shrink(s):'+#10+CutErrText);
CutErrText:='';
tmp:='';
- LockSubMode :=false;
end;
fillTypeVariableWithTagData(h,data,D,adifTag);
end;
diff --git a/src/fCabrilloExport.pas b/src/fCabrilloExport.pas
index ee68e9d..61152cf 100644
--- a/src/fCabrilloExport.pas
+++ b/src/fCabrilloExport.pas
@@ -208,6 +208,8 @@ begin
end;
function TfrmCabrilloExport.CabrilloMode(mode: string): String;
+//2022-05-05 OH1KH It seems that Cabrilllo mode can be CqrMode (mainly CW,SSB,AM,FM,RTTY)(I.E. no mode+submode pairs needed)
+//otherwise use dmUtils.ModeFromCqr to get mode and submode at this function
begin
Result := '';
case mode of
diff --git a/src/fDbSqlSel.pas b/src/fDbSqlSel.pas
index 3609d62..a98292c 100644
--- a/src/fDbSqlSel.pas
+++ b/src/fDbSqlSel.pas
@@ -167,14 +167,34 @@ begin
rewrite(f);
Writeln(f, '#!/bin/bash');
Writeln(f);
- Writeln(f, 'echo -e "\nCreating backup of all CQRLOG logs in database to /tmp/allcqrlogs.sql\n"');
+ Writeln(f, 'stamp=$(date +_%Y%m%d-%H%M)');
+ Writeln(f, 'echo -e "\nStarted$stamp"');
+ Writeln(f, 'echo -e "Creating common backup of all CQRLOG logs in database to /tmp/allcqrlogs$stamp.sql"');
Writeln(f, '$(mysql -u' + user + ' -p' + pass + ' -B -N -h' + ip + ' -P' + port +
- ' -e " show databases like ' + #$27 + 'cqr%' + #$27 + '" |\');
+ ' -e " show databases like ' + #$27 + 'cqr%' + #$27 + '" |\');
Writeln(f, 'xargs echo -n mysqldump -q -h' + ip + ' -P' + port + ' -u' +
- user + ' -p' + pass + ' --databases) > /tmp/allcqrlogs.sql');
- Writeln(f, 'echo -e "Done!\nCopy backup file to your safe place.\nIt will be erased from /tmp at next Linux start\n\nTo restore all CQRLOG logs use command:\n"');
+ user + ' -p' + pass + ' --databases) > /tmp/allcqrlogs$stamp.sql');
+
+ Writeln(f, 'echo -e "Creating separate backups of each CQRLOG logXXX in database to /tmp/cqrlogXXX$stamp.sql(s)\n"');
+ Writeln(f, 'mysql -u' + user + ' -p' + pass + ' -B -N -h' + ip + ' -P' + port +
+ ' -e " show databases like ' + #$27 + 'cqr%' + #$27 + '" |\');
+ Writeln(f, 'xargs -d\ | while read line; do if [[ $line != "" ]];then\');
+ Writeln(f, ' echo "mysqldump -q -h' + ip + ' -P' + port + ' -u' +
+ user + ' -p' + pass + ' $line > /tmp/$line$stamp.sql";fi;done > /tmp/sepsql.sh');
+ Writeln(f, 'chmod a+x /tmp/sepsql.sh');
+ Writeln(f, '/tmp/sepsql.sh');
+ Writeln(f, 'rm /tmp/sepsql.sh');
+
+
+ Writeln(f, 'echo -e "\nDone!\nCopy backup files to your safe place.\n'+
+ 'They will be erased from /tmp at next Linux start\n\n"');
+ Writeln(f, 'echo "To restore all CQRLOG logs use command:"');
+ Writeln(f, 'echo -e "mysql -h' + ip + ' -P' + port + ' -u' + user + ' -p' + pass +
+ ' < /tmp/allcqrlogs$stamp.sql\n\n"');
+ Writeln(f, 'echo "To restore single a log use command:"');
Writeln(f, 'echo "mysql -h' + ip + ' -P' + port + ' -u' + user + ' -p' + pass +
- ' < /tmp/allcqrlogs.sql"');
+ ' cqrlog001 < /tmp/cqrlog001$stamp.sql"');
+ Writeln(f, 'echo -e "\nBe sure that both log numbers used in line are equal"');
closeFile(f);
dmUtils.ExecuteCommand('chmod a+rwx ' + UsrHome + 'backup_all_cqr.sh');
end;
diff --git a/src/fEDIExport.pas b/src/fEDIExport.pas
index 1fd0b7e..2d5ebbb 100644
--- a/src/fEDIExport.pas
+++ b/src/fEDIExport.pas
@@ -102,6 +102,8 @@ begin
end;
function TfrmEDIExport.EdiMode(mode: string): String;
+//2022-05-05 OH1KH It seems that EDI mode can be CqrMode (I.E. no mode+submode pairs needed)
+//otherwise use dmUtils.ModeFromCqr to get mode and submode at this point
begin
Result := '0';
case mode of
diff --git a/src/fExportProgress.pas b/src/fExportProgress.pas
index 4af4fcd..4ecc129 100644
--- a/src/fExportProgress.pas
+++ b/src/fExportProgress.pas
@@ -188,7 +188,10 @@ var
srx, stx_string, srx_string, contestname, Darc_Dok : String);
var
- station_callsign : String;
+ station_callsign : String;
+ OutMode,
+ OutSubmode :String;
+
begin
station_callsign := cqrini.ReadString('Station', 'Call', '');
leng := 0;
@@ -219,120 +222,11 @@ var
if ExCall then
SaveTag(dmUtils.StringToADIF(''+Mode;SaveTag(tmp,leng);end;
- 'PCW' : begin tmp := 'CW'+Mode;SaveTag(tmp,leng);end;
- 'DOM-M','DOM4','DOM5',
- 'DOM8','DOM11','DOM16',
- 'DOM22','DOM44','DOM88',
- 'DOMINOEX','DOMINOF' : begin tmp := 'DOMINO'+Mode;SaveTag(tmp,leng);end;
- 'FELDHELL', //this is non standard that fldigi uses
- 'FMHELL','FSKHELL',
- 'HELL80','HELLX5',
- 'HELLX9','HFSK',
- 'PSKHELL','SLOWHELL' : begin tmp := 'HELL'+Mode;SaveTag(tmp,leng);end;
- 'ISCAT-A','ISCAT-B' : begin tmp := 'ISCAT'+Mode;SaveTag(tmp,leng);end;
- 'JT4A','JT4B','JT4C',
- 'JT4D','JT4E','JT4F',
- 'JT4G' : begin tmp := 'JT4'+Mode;SaveTag(tmp,leng);end;
- 'JT9-1','JT9-2','JT9-5',
- 'JT9-10','JT9-30',
- 'JT9A','JT9B','JT9C',
- 'JT9D','JT9E','JT9E FAST',
- 'JT9F','JT9F FAST','JT9G',
- 'JT9G FAST','JT9H',
- 'JT9H FAST' : begin tmp := 'JT9'+Mode;SaveTag(tmp,leng);end;
- 'FSQCALL','FST4','FST4W',
- 'FT4','JS8','JTMS','MFSK4',
- 'MFSK8','MFSK11','MFSK16',
- 'MFSK22','MFSK31','MFSK32',
- 'MFSK64','MFSK64L',
- 'MFSK128' : begin tmp := 'MFSK'+Mode;SaveTag(tmp,leng);end;
- //OLIVIA is exception #1
- 'OPERA-BEACON',
- 'OPERA-QSO' : begin tmp := 'OPERA'+Mode;SaveTag(tmp,leng);end;
- 'PAC2','PAC3','PAC4' : begin tmp := 'PAC'+Mode;SaveTag(tmp,leng);end;
- 'PAX2' : begin tmp := 'PAX'+Mode;SaveTag(tmp,leng);end;
- '8PSK125','8PSK125F',
- '8PSK125FL','8PSK250',
- '8PSK250F','8PSK250FL',
- '8PSK500','8PSK500F',
- '8PSK1000','8PSK1000F',
- '8PSK1200F','FSK31','PSK10',
- 'PSK31','PSK63','PSK63F',
- 'PSK63RC4','PSK63RC5',
- 'PSK63RC10','PSK63RC20',
- 'PSK63RC32','PSK125',
- 'PSK125C12','PSK125R',
- 'PSK125RC10','PSK125RC12',
- 'PSK125RC16','PSK125RC4',
- 'PSK125RC5','PSK250',
- 'PSK250C6','PSK250R',
- 'PSK250RC2','PSK250RC3',
- 'PSK250RC5','PSK250RC6',
- 'PSK250RC7','PSK500',
- 'PSK500C2','PSK500C4',
- 'PSK500R','PSK500RC2',
- 'PSK500RC3','PSK500RC4',
- 'PSK800C2','PSK800RC2',
- 'PSK1000','PSK1000C2',
- 'PSK1000R','PSK1000RC2',
- 'PSKAM10','PSKAM31',
- 'PSKAM50','PSKFEC31',
- 'QPSK31','QPSK63',
- 'QPSK125','QPSK250',
- 'QPSK500','SIM31' : begin tmp := 'PSK'+Mode;SaveTag(tmp,leng);end;
- 'QRA64A','QRA64B','QRA64C',
- 'QRA64D','QRA64E' : begin tmp := 'QRA64'+Mode;SaveTag(tmp,leng);end;
- 'ROS-EME','ROS-HF',
- 'ROS-MF' : begin tmp := 'ROS'+Mode;SaveTag(tmp,leng);end;
- 'ASCI','ASCII' : begin tmp := 'RTTY'+Mode;SaveTag(tmp,leng);end;
- 'LSB','USB' : begin tmp := 'SSB'+Mode;SaveTag(tmp,leng);end;
- 'THOR-M','THOR4','THOR5',
- 'THOR8','THOR11','THOR16',
- 'THOR22','THOR25X4',
- 'THOR50X1','THOR50X2',
- 'THOR100' : begin tmp := 'THOR'+Mode;SaveTag(tmp,leng);end;
- 'THRBX','THRBX1','THRBX2',
- 'THRBX4','THROB1','THROB2',
- 'THROB4' : begin tmp := 'THRB'+Mode;SaveTag(tmp,leng);end;
- 'AMTORFEC','GTOR','NAVTEX',
- 'SITORB' : begin tmp := 'TOR'+Mode;SaveTag(tmp,leng);end;
-
- else begin
- //exceptions follow
- if pos('OLIVIA',mode)=1 then
- //fldigi marks them with "-" that is against standard " "
- //also there are more BW definitions than standard: will pass them all
- begin
- mode := StringReplace(mode,'-',' ',[rfReplaceAll]);
- tmp := 'OLIVIA'+Mode;SaveTag(tmp,leng);
- end
- else
- //exceptions end
- Begin
- tmp := '=1);
+ SaveTag(dmUtils.StringToADIF(''' then
+ SaveTag(dmUtils.StringToADIF('',uppercase(Buf))=1;
- //execption is SSB. Cqrlog does not use USB and LSB (submodes)
- if (mode='USB') or (mode='LSB') then
- mode:='SSB';
+ //store original modes
+ modeorig:=uppercase(mode);
+ submodeorig:=uppercase(submode);
+ //after this line mode will be changed to Cqrmode. submodeorig & modeorig has orignal ones stored for possible error reports
+ mode :=dmUtils.ModeToCqr(mode,submode,LocalDbg);
end;
-procedure TfrmImportProgress.WriteErrorRecord(f:char;call,band,mode,qsodate,time_on,qslr,qslrdate,
+procedure TfrmImportProgress.WriteErrorRecord(f:char;call,band,modeorig,submodeorig,qsodate,time_on,qslr,qslrdate,
cqz,ituz,iota,grid,state,county,qsorecord:string;var s:Tstringlist);
var
l,
@@ -649,7 +649,8 @@ Begin
+'QSO NOT FOUND in log'+LineEnding
+'Call: '+call+LineEnding
+'Band: '+band+LineEnding
- +'Mode: '+mode+LineEnding
+ +'Mode: '+modeorig+LineEnding
+ +'Submode: '+submodeorig+lineEnding
+'QSO_date: '+qsodate+LineEnding
+'Time_on: '+time_on+LineEnding;
if f='L' then
@@ -685,21 +686,22 @@ var
f : TextFile;
PosEOH : Word;
PosEOR : Word;
- qsorecord: String;
- call : String;
- band : String;
- mode : String;
- //submode not needed with lotw
- submode : String;
- qsodate : String;
- time_on : String;
- qslr : String;
- qslrdate : String;
- cqz : String;
- ituz : String;
- iota : String;
- grid : String;
- state : String;
+ qsorecord,
+ call,
+ band,
+ mode,
+ modeorig,
+ submode,
+ submodeorig,
+ qsodate,
+ time_on,
+ qslr,
+ qslrdate,
+ cqz,
+ ituz,
+ iota,
+ grid,
+ state,
county : String;
qso_in_log : Boolean = False;
@@ -753,7 +755,9 @@ begin
call := '';
band := '';
mode := '';
+ modeorig := '';
submode := '';
+ submodeorig := '';
qsodate := '';
time_on := '';
qslr := '';
@@ -768,9 +772,9 @@ begin
while not ((PosEOR > 0) or eof(f)) do //read all records
begin
qso_in_log := False;
- CommonImport(PosEOR,f,call,band,mode,submode,qsodate,time_on,qslr,
+ CommonImport(PosEOR,f,call,band,modeorig,mode,submodeorig,submode,qsodate,time_on,qslr,
qslrdate,cqz,ituz,iota,grid,state,county,qsorecord);
-
+ //for now on the mode is converted Cqrmode
if PosEOR > 0 then
begin
if LocalDbg then
@@ -779,7 +783,9 @@ begin
Writeln('Record Number: ',IntToStr(qsln));
Writeln('Call: ',call);
Writeln('Band: ',band);
- Writeln('Mode: ',mode);
+ Writeln('Mode: ',modeorig);
+ Writeln('Submode: ',submodeorig);
+ Writeln('Cqrmode: ',mode);
Writeln('QSO_date: ',qsodate);
Writeln('Time_on: ',time_on);
Writeln('QSLR: ',qslr);
@@ -796,15 +802,19 @@ begin
qsodate := dmUtils.ADIFDateToDate(qsodate);
qslrdate := dmUtils.ADIFDateToDate(qslrdate);
- mode := UpperCase(mode);
- if mode='JT65' then
- mode := 'JT65A';
-
dmData.Q.Close;
+ //we compare Cqrmode in log to mode and submode received and Cqrmode created.
+ //If any of these is ok, qso is ok by mode.
+ //this makes backward compatible to old cqrlog loggings.
+ //Actually qso is ok even without mode check if other items fit!
dmData.Q.SQL.Text := 'select time_on,lotw_qslr,waz,itu,iota,loc,state,county,id_cqrlog_main from cqrlog_main ' +
'where (qsodate ='+QuotedStr(qsodate)+') '+
'and (band = ' + QuotedStr(band) + ')'+
-// 'and (mode = ' + QuotedStr(mode) + ') and (band = ' + QuotedStr(band) + ')'+
+ 'and ('+
+ '(mode = ' + QuotedStr(mode) +') or '+
+ '(mode = ' + QuotedStr(modeorig)+') or '+
+ '(mode = ' + QuotedStr(submodeorig)+') '+
+ ')' +
'and (callsign = ' + QuotedStr(call) + ')';
if LocalDbg then Writeln(dmData.Q.SQL.Text);
//if dmData.trQ.Active then dmData.trQ.Rollback;
@@ -872,7 +882,7 @@ begin
end;
if not qso_in_log then
begin
- WriteErrorRecord('L',call,band,mode,qsodate,time_on,qslr,qslrdate,cqz,ituz,iota,grid,state,county,qsorecord,l);
+ WriteErrorRecord('L',call,band,modeorig,submodeorig,qsodate,time_on,qslr,qslrdate,cqz,ituz,iota,grid,state,county,qsorecord,l);
inc(ErrorCount)
end
end
@@ -1019,45 +1029,47 @@ end;
procedure TfrmImportProgress.ImporteQSLAdif;
var
- num : Word = 1;
- size : Word;
- sSize : String;
- a : String;
- orig : String;
f : TextFile;
- PosEOH : Word;
+ num : Word = 1;
+ size,
+ PosEOH,
PosEOR : Word;
- qsorecord: String;
- call : String;
- band : String;
- mode : String;
- submode : String;
- qsodate : String;
- time_on : String;
- qslr : String;
- qslrdate : String;
- cqz : String;
- ituz : String;
- iota : String;
- grid : String;
- state : String;
- county : String;
- Buf : String;
+ sSize,
+ a,
+ orig,
+ qsorecord,
+ call,
+ band,
+ mode,
+ modeorig,
+ submode,
+ submodeorig,
+ qsodate,
+ time_on,
+ qslr,
+ qslrdate,
+ cqz,
+ ituz,
+ iota,
+ grid,
+ state,
+ county,
+ Buf : String;
- PosCall : Word;
- PosBand : Word;
- PosMode : Word;
- PosSubmode : Word;
- PosQsoDate : Word;
- PosTime_on : Word;
+ PosCall,
+ PosBand,
+ PosMode,
+ PosSubmode,
+ PosQsoDate,
+ PosTime_on,
PosQslr : Word;
qso_in_log : Boolean = False;
ErrorCount : Word = 0;
l : TStringList;
- t_eQSL : TDateTime;
- t_eQSL_min : TDateTime;
- t_eQSL_max : TDateTime;
+ t_eQSL,
+ t_eQSL_min,
+ t_eQSL_max,
t_log : TDateTime;
begin
@@ -1099,7 +1111,10 @@ begin
begin
call := '';
band := '';
+ modeorig := '';
mode := '';
+ submodeorig
+ := '';
submode := '';
qsodate := '';
time_on := '';
@@ -1119,9 +1134,9 @@ begin
while not ((PosEOR > 0) or eof(f)) do
begin
qso_in_log := False;
- CommonImport(PosEOR,f,call,band,mode,submode,qsodate,time_on,qslr,
+ CommonImport(PosEOR,f,call,band,modeorig,mode,submodeorig,submode,qsodate,time_on,qslr,
qslrdate,cqz,ituz,iota,grid,state,county,qsorecord);
-
+ //for now on the mode is converted Cqrmode
if PosEOR > 0 then
begin
if LocalDbg then
@@ -1129,8 +1144,9 @@ begin
Writeln('------------------------------------------------');
Writeln('Call: ',call);
Writeln('Band: ',band);
- Writeln('Mode: ',mode);
- Writeln('Submode: ',submode);
+ Writeln('Mode: ',modeorig);
+ Writeln('Submode: ',submodeorig);
+ Writeln('CqrMode: ',mode);
Writeln('QSO_date: ',qsodate);
Writeln('Time_on: ',time_on);
Writeln('QSLR: ',qslr);
@@ -1140,22 +1156,20 @@ begin
dmData.Q.Close;
- if (mode='JT65') then //since implementing submodes below, this can most probably be removed
- begin
- dmData.Q.SQL.Text := 'select id_cqrlog_main,eqsl_qsl_rcvd,time_on from cqrlog_main ' +
+ //we compare Cqrmode in log to mode and submode received and Cqrmode created.
+ //If any of these is ok, qso is ok by mode.
+ //this makes backward compatible to old cqrlog loggings.
+ //Actually qso is ok even without mode check if other items fit!
+ dmData.Q.SQL.Text := 'select id_cqrlog_main,eqsl_qsl_rcvd,time_on from cqrlog_main ' +
'where (qsodate ='+QuotedStr(qsodate)+') '+
- 'and ((mode = ' + QuotedStr('JT65') + ') or (mode='+QuotedStr('JT65A')+') '+
- 'or (mode='+QuotedStr('JT65B')+') or (mode='+QuotedStr('JT65C')+')) '+
+ 'and ('+
+ '(mode = ' + QuotedStr(mode) +') or '+
+ '(mode = ' + QuotedStr(modeorig)+') or '+
+ '(mode = ' + QuotedStr(submodeorig)+') '+
+ ')' +
'and (band = ' + QuotedStr(band) + ') '+
- 'and (callsign = ' + QuotedStr(call) + ')'
- end
- else begin
- dmData.Q.SQL.Text := 'select id_cqrlog_main,eqsl_qsl_rcvd,time_on from cqrlog_main ' +
- 'where (qsodate ='+QuotedStr(qsodate)+') '+
- 'and ((mode = ' + QuotedStr(mode) + ') or (mode = ' + QuotedStr(submode) + ')) '+
- 'and (band = ' + QuotedStr(band) + ') '+
- 'and (callsign = ' + QuotedStr(call) + ')'
- end;
+ 'and (callsign = ' + QuotedStr(call) + ')';
+
if LocalDbg then Writeln(dmData.Q.SQL.Text);
//if dmData.trQ.Active then dmData.trQ.Rollback;
//dmData.trQ.StartTransaction;
@@ -1206,7 +1220,7 @@ begin
end;
if not qso_in_log then
begin
- WriteErrorRecord('E',call,band,mode,qsodate,time_on,qslr,qslrdate,cqz,ituz,iota,grid,state,county,qsorecord,l);
+ WriteErrorRecord('E',call,band,modeorig,submodeorig,qsodate,time_on,qslr,qslrdate,cqz,ituz,iota,grid,state,county,qsorecord,l);
inc(ErrorCount)
end
end
diff --git a/src/fLoTWExport.pas b/src/fLoTWExport.pas
index f82cac7..8218137 100644
--- a/src/fLoTWExport.pas
+++ b/src/fLoTWExport.pas
@@ -365,10 +365,12 @@ end;
function TfrmLoTWExport.ExportToAdif : Word;
var
- f : TextFile;
- tmp : String = '';
- nr : Integer = 1;
- date : String;
+ f : TextFile;
+ tmp : String = '';
+ nr : Integer = 1;
+ date,
+ ModeOut,
+ SubmodeOut: String;
begin
if FileExists(FileName) then
DeleteFile(FileName);
@@ -447,35 +449,15 @@ begin
tmp := dmUtils.StringToADIF('= 1);
+ tmp := dmUtils.StringToADIF(''' then
+ Begin
+ tmp := dmUtils.StringToADIF('= 1 then
+ WriteLn(dmData.Q.SQL.Text);
dmData.trQ.StartTransaction;
dmData.Q.ExecSQL;
dmData.trQ.Commit
diff --git a/src/fNewQSO.pas b/src/fNewQSO.pas
index 001fc06..e988f92 100644
--- a/src/fNewQSO.pas
+++ b/src/fNewQSO.pas
@@ -1928,6 +1928,7 @@ var
Mo :TStringList;
mhz,
mode,
+ submode,
Mask,
data : String;
begin
@@ -2026,12 +2027,12 @@ begin
//first set mode by mode, then if submode exist replace mode with it.
//Here no problem with SSB/USB/LSB combination
- cmbMode.Text := logged.ValueFromIndex[logged.IndexOfName('mode')];
+ mode := logged.ValueFromIndex[logged.IndexOfName('mode')];
if logged.IndexOfName('submode')> -1 then
- Begin
- mode := logged.ValueFromIndex[logged.IndexOfName('submode')];
- if mode<>'' then cmbMode.Text := mode;
- end;
+ submode := logged.ValueFromIndex[logged.IndexOfName('submode')]
+ else
+ submode:='';
+ cmbMode.Text:=dmUtils.ModeToCqr(mode,submode,dmData.DebugLevel>=1);
//set frquency
mhz := logged.ValueFromIndex[logged.IndexOfName('mhz')];
@@ -2045,10 +2046,7 @@ begin
edtMyRST.Text := logged.ValueFromIndex[logged.IndexOfName('rx')];
//then override with possible defaults for frequency, mode and RST from Cqrlog settings
- //Buggy Lazarus GUI creates under this one extra "end;" because of "try/finally/end" above.
- //Remove it!
-
- case cqrini.ReadInteger('fldigi','freq',0) of
+ case cqrini.ReadInteger('fldigi','freq',0) of
0 : if frmTRXControl.GetModeFreqNewQSO(mode,mhz) then cmbFreq.Text := mhz;
2 : cmbFreq.Text := cqrini.ReadString('fldigi','deffreq','3.600')
end;
@@ -2075,15 +2073,14 @@ end;
procedure TfrmNewQSO.tmrADIFTimer(Sender: TObject);
var
Buf, buf2,
- prik,data :string;
- chkDuplicates,
- submodeExist :boolean;
+ prik,data :string;
+ chkDuplicates :boolean;
i :longint;
a,b,l :integer;
fixed :Boolean;
+ mode,submode :string;
begin
-
fixed:=false;
tmrADIF.Enabled:=false;
chkDuplicates:=false;
@@ -2151,10 +2148,11 @@ begin
if pos(' 0 then
Begin
if dmData.DebugLevel>=1 then writeln('Handle qso record: ',Buf);
+ mode:='';
+ submode:='';
//this is fake as call info(qslmgr) needs date. We use current date if call tag comes before qso_date tag
//qso_date will then replace this
edtDate.Text := FormatDateTime('YYYY-MM-DD',now());
- submodeExist:=false;
repeat
begin
if frmAdifImport.getNextAdifTag(Buf,prik,data) then
@@ -2176,14 +2174,8 @@ begin
if pos(data,edtGrid.Text)=0 then //if qso loc does not fit to QRZ loc , or qrz loc is empty
edtGrid.Text := data; //replace qrz loc, otherwise keep it
end;
- 'MODE' : if not submodeExist
- then cmbMode.Text := uppercase(data);
- //now this overrides MODE, if exists
- 'SUBMODE' : Begin
- //we need lock in case submode found before mode tag
- submodeExist:=true;
- cmbMode.Text := uppercase(data);
- end;
+ 'MODE' : mode := uppercase(data);
+ 'SUBMODE' : submode := uppercase(data);
'FREQ' : cmbFreq.Text := data;
'FREQ_RX' : edtRXFreq.Text := data;
'RST_SENT' : edtHisRST.Text := data;
@@ -2221,9 +2213,10 @@ begin
end; //case
end; //repeat
until pos('',uppercase(Buf))=1;
- //execption is SSB. Cqrlog does not use USB and LSB (submodes)
- if (cmbMode.Text ='USB') or (cmbMode.Text='LSB') then
- cmbMode.Text:='SSB';
+
+ //set the final Cqrlmode
+ cmbMode.Text:=dmUtils.ModeToCqr(mode,submode,dmData.DebugLevel>=1 );
+
SaveRemote;
//these do not reset in qso save, so they must be cleared here in case there was
@@ -7551,8 +7544,8 @@ begin
cbOffline.Enabled := True;
btnSave.Enabled := True;
edtCall.SetFocus;
-
-
+ //clear TMPQSO mode on close. Otherwise it shows up on next remote mode (procedure ClearAll makes it)
+ cqrini.WriteString('TMPQSO','Mode','');
end;
procedure TfrmNewQSO.SaveRemote;
Begin
diff --git a/src/fSOTAExport.pas b/src/fSOTAExport.pas
index 4f5b361..d12ee4d 100644
--- a/src/fSOTAExport.pas
+++ b/src/fSOTAExport.pas
@@ -199,7 +199,10 @@ begin
dmUtils.DateInSOTAFormat(dmData.Q.FieldByName('qsodate').AsDateTime)+',',
StringReplace(dmData.Q.FieldByName('time_on').AsString,':','',[rfReplaceAll, rfIgnoreCase])+',',
FormatFloat('0.00;;',dmData.Q.FieldByName('freq').AsFloat),'MHz,',
+ //2022-05-05 OH1KH It seems that SOTA mode can be CqrMode (mainly CW,SSB,FM,AM)(I.E. no mode+submode pairs needed)
+ //otherwise use dmUtils.ModeFromCqr to get mode and submode at this point
dmData.Q.FieldByName('mode').AsString,',',
+
dmData.Q.FieldByName('callsign').AsString,',', //his callsign
HisSota+',', //his summit
note //comments
diff --git a/src/fXfldigi.pas b/src/fXfldigi.pas
index 5f7aebe..e9fe653 100644
--- a/src/fXfldigi.pas
+++ b/src/fXfldigi.pas
@@ -237,6 +237,7 @@ var
Drop :integer;
tmp :extended;
+
begin
frmNewQSO.tmrFldigi.Enabled := false;
SockOK := true;
@@ -281,10 +282,12 @@ begin
mode:='';submode:='';
if SockOK then SockOK := PollFldigi('modem.get_mode',mode);
if SockOK then SockOK := PollFldigi('modem.get_submode',submode);
- if mode='' then //old version of fldigi, make different query
+ if mode='' then //old version of fldigi get_mode not supported, make different query
+ Begin
if SockOK then SockOK := PollFldigi('modem.get_name',mode);
- //cqrlog saves submode as mode
- if submode<>'' then mode := submode;
+ end
+ else
+ mode:=dmUtils.ModeToCqr(mode,submode,dmData.DebugLevel>=1 );
end;
2 : begin
mode := cqrini.ReadString('fldigi','defmode','RTTY');
diff --git a/src/feQSLUpload.pas b/src/feQSLUpload.pas
index 724ea4d..ab3d4d2 100644
--- a/src/feQSLUpload.pas
+++ b/src/feQSLUpload.pas
@@ -69,9 +69,12 @@ end;
function TfrmeQSLUpload.ExportData(const FileName : String) : Boolean;
var
- nr : integer = 0;
- tmp : String = '';
- f : TextFile;
+ nr : integer = 0;
+ tmp : String = '';
+ ModeOut,
+ SubmodeOut : String;
+ f : TextFile;
+
begin
QSOCount := 0;
Result := True;
@@ -132,34 +135,14 @@ begin
tmp := dmUtils.StringToADIF('= 1);
+ tmp := dmUtils.StringToADIF(''' then
+ Begin
+ tmp := dmUtils.StringToADIF('
Date: Tue, 10 May 2022 13:41:20 +0300
Subject: [PATCH 2/2] Fix for adif headers
Added one linefeed before first line of adif header.
This makes linux command 'file' to detect adi files as text
instead of music file.
---
src/fAdifImport.pas | 1 +
src/fExportProgress.pas | 1 +
src/fLoTWExport.pas | 1 +
src/feQSLUpload.pas | 1 +
4 files changed, 4 insertions(+)
diff --git a/src/fAdifImport.pas b/src/fAdifImport.pas
index 8d01b41..badbc9a 100644
--- a/src/fAdifImport.pas
+++ b/src/fAdifImport.pas
@@ -1047,6 +1047,7 @@ begin
else begin
AssignFile(f,dmData.UsrHomeDir + ERR_FILE);
Rewrite(f);
+ Writeln(f);
Writeln(f,'ADIF export from CQRLOG for Linux version ' + dmData.VersionString);
Writeln(f,'Copyright (C) ',YearOf(now),' by Petr, OK2CQR and Martin, OK1RR');
Writeln(f,'Internet: http://www.cqrlog.com');
diff --git a/src/fExportProgress.pas b/src/fExportProgress.pas
index 4af4fcd..da91a40 100644
--- a/src/fExportProgress.pas
+++ b/src/fExportProgress.pas
@@ -547,6 +547,7 @@ begin //TfrmExportProgress
AssignFile(f, FileName);
Rewrite(f);
+ Writeln(f);
Writeln(f, 'ADIF export from CQRLOG for Linux version '+dmData.VersionString);
Writeln(f, 'Copyright (C) ',YearOf(now),' by Petr, OK2CQR and Martin, OK1RR');
Writeln(f);
diff --git a/src/fLoTWExport.pas b/src/fLoTWExport.pas
index f82cac7..6dee9aa 100644
--- a/src/fLoTWExport.pas
+++ b/src/fLoTWExport.pas
@@ -385,6 +385,7 @@ begin
end;
date := FormatDateTime('yyyy-mm-dd',now);
+ Writeln(f);
Writeln(f, '3.1.0');
Writeln(f, '',FormatDateTime('YYYYMMDD hhmmss',dmUtils.GetDateTime(0)));
Writeln(f, 'ADIF export from CQRLOG for Linux version '+dmData.VersionString);
diff --git a/src/feQSLUpload.pas b/src/feQSLUpload.pas
index 724ea4d..684dfe6 100644
--- a/src/feQSLUpload.pas
+++ b/src/feQSLUpload.pas
@@ -104,6 +104,7 @@ begin
AssignFile(f,FileName);
try try
Rewrite(f);
+ Writeln(f);
Writeln(f, 'ADIF export from CQRLOG for Linux version '+dmData.VersionString);
Writeln(f, 'Copyright (C) ',YearOf(now),' by Petr, OK2CQR and Martin, OK1RR');
Writeln(f);