1 /***************************************************************************
2 utilities.cpp - description
3 -------------------
4 begin : jun 2015
5 copyright : (C) 2015 by Jaime Robles
6 email : jaime@robles.es
7 ***************************************************************************/
8
9 /*****************************************************************************
10 * This file is part of KLog. *
11 * *
12 * KLog is free software: you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation, either version 3 of the License, or *
15 * (at your option) any later version. *
16 * *
17 * KLog is distributed in the hope that it will be useful, *
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
20 * GNU General Public License for more details. *
21 * *
22 * You should have received a copy of the GNU General Public License *
23 * along with KLog. If not, see <https://www.gnu.org/licenses/>. *
24 * *
25 *****************************************************************************/
26 #include "global.h"
27 #include "utilities.h"
28
29 bool g_callsignCheck;
Utilities()30 Utilities::Utilities()
31 {
32 //qDebug() << "Utilities::Utilities" ;
33 init();
34
35 //palRed.setColor(QPalette::Text, Qt::red);
36 //palBlack.setColor(QPalette::Text, Qt::black);
37 //qDebug() << "Utilities::Utilities - END" ;
38 }
39
~Utilities()40 Utilities::~Utilities()
41 {
42 }
43
init()44 void Utilities::init()
45 {
46 softwareVersion = "0.0";
47 darkMode = false;
48 callValidation = true;
49 }
50
setVersion(const QString & _v)51 void Utilities::setVersion(const QString &_v)
52 {
53 //qDebug() << "Utilities::setVersion: " << _v ;
54 softwareVersion = _v;
55 }
56
getVersion()57 QString Utilities::getVersion()
58 {
59 return softwareVersion;
60 }
61
getVersionDouble()62 double Utilities::getVersionDouble()
63 {
64 //qDebug() << "Utilities::getVersionDouble: " << softwareVersion ;
65 if (softwareVersion.count('.')>1)
66 {
67 QString first = softwareVersion.section('.', 0, 0);
68 int pos = softwareVersion.indexOf('.');
69
70 QString decimals = softwareVersion.section('.', pos, -1);
71 decimals.remove('.');
72 first = first + "." + decimals;
73 //qDebug() << "Utilities::getVersionDouble - returning: " << first ;
74 return first.toDouble();
75 }
76 //qDebug() << "Utilities::getVersionDouble: no points detected" ;
77 return softwareVersion.toDouble();
78 }
79
getProgresStepForDialog(int totalSteps)80 int Utilities::getProgresStepForDialog(int totalSteps)
81 {
82 //qDebug() << "Utilities::getProgresStepForDialog";
83 if (totalSteps <=100)
84 return 1;
85 else if (totalSteps <=1000)
86 return 5;
87 else if (totalSteps <=4000)
88 return 10;
89 else if (totalSteps <=5000)
90 return 15;
91 else if (totalSteps <=7000)
92 return 20;
93 else if (totalSteps <=9999)
94 return 25;
95 else if (totalSteps <=20000)
96 return 100;
97 else
98 return 250;
99 }
100
trueOrFalse(const QString & _s)101 bool Utilities::trueOrFalse(const QString &_s)
102 {// reads a String and return true if s.upper()== TRUE :-)
103 //qDebug() << "Utilities::trueOrFalse: " << _s ;
104
105 if ( (_s.toUpper()) == "TRUE")
106 {
107 return true;
108 }
109 else
110 {
111 return false;
112 }
113 //return false;
114 }
115
boolToCharToSQLite(const bool _b)116 QChar Utilities::boolToCharToSQLite(const bool _b)
117 {
118 if (_b)
119 {
120 return 'Y';
121 }
122 else
123 {
124 return 'N';
125 }
126 }
127
boolToQString(const bool _b)128 QString Utilities::boolToQString(const bool _b)
129 {
130 if (_b)
131 {
132 return "True";
133 }
134 else
135 {
136 return "False";
137 }
138 }
139
checkAndFixASCIIinADIF(const QString & _data)140 QString Utilities::checkAndFixASCIIinADIF(const QString &_data)
141 {
142 //qDebug() << "SetupDialog::checkAndFixASCIIinADIF " << _data ;
143 // This function is not really working with ASCII but with Unicode
144 //TODO: this function is also in the FileManager class. Maybe I should call that one and keep just one copy
145 ushort unicodeVal;
146 QString st = _data;
147 QString newString;
148 newString.clear();
149 for(int i=0; i < st.length(); i++)
150 {
151 // Get unicode VALUE into unicodeVal
152 unicodeVal = (st.at(i)).unicode();
153 if ((20 <= unicodeVal ) && (unicodeVal <= 126))
154 {
155 newString.append(st.at(i));
156 }
157 //qDebug() << "SetupDialog::checkAndFixunicodeinADIF: " << st.at(i) <<" = " << QString::number(unicodeVal) ;
158 }
159 // Show into another lineEdit
160 return newString;
161 }
162
printQString(const QStringList & _qs)163 void Utilities::printQString(const QStringList &_qs)
164 {
165 //qDebug() << "Utilities::printQString: COMMENT THIS CALL BEFORE RELEASING" ;
166 if (_qs.length()<1)
167 {
168 //qDebug() << "Utilities::printQString: EMPTY QStringList received!!" ;
169 return;
170 }
171 for (int i=0; i<_qs.length()-1;i++)
172 {
173 //qDebug() << _qs.at(i) << "/" ;
174 }
175 //qDebug() << _qs.at(_qs.length()-1) ;
176 }
177
getGlobalAgent(const QString & _klogversion)178 QString Utilities::getGlobalAgent(const QString &_klogversion)
179 {
180 return QString("KLog-%1").arg(_klogversion);
181 }
182
getAgent(const QString & _klogversion)183 QString Utilities::getAgent(const QString &_klogversion)
184 {
185 QString version;
186 QString ops;
187 version = _klogversion;
188
189 #if defined(Q_OS_WIN32)
190 ops = "KLog-Win32-";
191 #elif defined(Q_OS_WIN64)
192 ops = "KLog-Win64-";
193 #elif defined(Q_OS_LINUX)
194 ops = "KLog-Linux-";
195 #elif defined(Q_OS_WIN)
196 ops = "KLog-Win-"+ version;
197 #elif defined(Q_OS_MACOS)
198 ops = "KLog-macOS-";
199 #elif defined(Q_OS_OSX)
200 ops = "KLog-OSX-";
201 #elif defined(Q_OS_MAC)
202 ops = "KLog-MAC-";
203 #elif defined(Q_OS_DARWIN)
204 ops = "KLog-DARWIN-";
205 #elif defined(Q_OS_AIX)
206 ops = "KLog-aix-";
207 #elif defined(Q_OS_ANDROID)
208 ops = "KLog-android-";
209 //#elif defined(Q_OS_BSD4)
210 // ops = "KLog-bsd4-";
211 #elif defined(Q_OS_BSDI)
212 ops = "KLog-bsdi-";
213 #elif defined(Q_OS_CYGWIN)
214 ops = "KLog-cygwin-";
215 #elif defined(Q_OS_DARWIN)
216 ops = "KLog-darwin-";
217 #elif defined(Q_OS_DGUX)
218 ops = "KLog-dgux-";
219 #elif defined(Q_OS_DYNIX)
220 ops = "KLog-dynix-";
221 #elif defined(Q_OS_FREEBSD)
222 ops = "KLog-freebsd-";
223 #elif defined(Q_OS_HPUX)
224 ops = "KLog-hpux-";
225 #elif defined(Q_OS_IOS)
226 ops = "KLog-ios-";
227 #elif defined(Q_OS_IRIX)
228 ops = "KLog-irix-";
229 #elif defined(Q_OS_LYNX)
230 ops = "KLog-lynx-";
231 #elif defined(Q_OS_NETBSD)
232 ops = "KLog-netbsd-";
233 #elif defined(Q_OS_OPENBSD)
234 ops = "KLog-openbsd-";
235 #elif defined(Q_OS_OSF)
236 ops = "KLog-osf-";
237 #elif defined(Q_OS_QNX)
238 ops = "KLog-qnx-";
239 #elif defined(Q_OS_SCO)
240 ops = "KLog-sco-";
241 #elif defined(Q_OS_SOLARIS)
242 ops = "KLog-solaris-";
243 #elif defined(Q_OS_TVOS)
244 ops = "KLog-tvos-";
245 #elif defined(Q_OS_UNIX)
246 ops = "KLog-unix-";
247 #elif defined(Q_OS_UNIXWARE)
248 ops = "KLog-unixware-";
249 #elif defined(Q_OS_WHATCHOS)
250 ops = "KLog-whatchos-";
251 #elif defined(Q_OS_WINRT)
252 ops = "KLog-winrt-";
253 #else
254 ops = "KLog-Other-";
255 #endif
256
257 return ops+version;
258
259 //return "KLog-Unknown-" + version;
260 }
261
getHomeDir()262 QString Utilities::getHomeDir()
263 {
264 //TODO: To be removed when the defaultDir is saved in the config file
265 #if defined(Q_OS_WIN)
266 //qDebug() << "WINDOWS DETECTED!: " << QDir::homePath() + "/klog" ;
267 return QDir::homePath()+"/klog"; // We create the \klog for the logs and data
268
269 #else
270 //qDebug() << "NO WINDOWS DETECTED!" ;
271 return QDir::homePath()+"/.klog"; // We create the ~/.klog for the logs and data
272 #endif
273 }
274
getDefaultRST(const QString & _m)275 QString Utilities::getDefaultRST(const QString &_m)
276 {
277 //qDebug() << "Utilities::getDefaultRST: " << _m ;
278
279 if ((_m == "SSB") || (_m== "LSB") || (_m=="USB") )
280 {
281 //qDebug() << "MainWindow::setRSTToMode: Detected SSB/LSB/USB" ;
282 return "59";
283 }
284 else if ((_m == "CW") || (_m == "RTTY"))
285 {
286 return "599";
287 }
288 else if (_m == "PSK31")
289 {
290 return "599";
291 }
292 else if ( (_m.contains("FT", Qt::CaseInsensitive)) || (_m.contains("JT", Qt::CaseInsensitive)) || (_m.contains("QRA64", Qt::CaseInsensitive)) || (_m.contains("JS", Qt::CaseInsensitive)))
293 {
294 return "0";
295 }
296 else
297 { // By default SSB RST is configured but anything could be added
298 return "59";
299 }
300 }
301
getDefaultLogFields()302 QStringList Utilities::getDefaultLogFields()
303 {
304 QStringList fields;
305 fields.clear();
306 fields << "qso_date" << "call" << "rst_sent" << "rst_rcvd" << "bandid" << "modeid" << "comment";
307 return fields;
308 }
309
getKLogDefaultDatabaseFile()310 QString Utilities::getKLogDefaultDatabaseFile()
311 {
312 //TODO: To be removed when the defaultDir is saved in the config file
313 return getHomeDir() ;
314 }
315
getKLogDBFile()316 QString Utilities::getKLogDBFile()
317 {
318 //qDebug() << "Utilities::getKLogDBFile: start " ;
319
320 dbPath = getKLogDefaultDatabaseFile();
321 QFile file(getCfgFile());
322
323 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) /* Flawfinder: ignore */
324 {
325 //return dbPath;
326 //return getKLogDatabaseFile(dbPath);
327 }
328 else
329 {
330 while (!file.atEnd()) {
331 QByteArray line = file.readLine();
332 processConfigLine(line);
333 }
334
335 if (dbPath.length()<1)
336 {
337 dbPath = getKLogDefaultDatabaseFile();
338 }
339 }
340 //qDebug() << "Utilities::getKLogDBFile: path to use: " << dbPath ;
341 return dbPath + "/logbook.dat";
342 }
343
getKLogDBBackupFile()344 QString Utilities::getKLogDBBackupFile()
345 {
346 //qDebug() << "Utilities::getKLogDBFile: start " ;
347
348 dbPath = getKLogDefaultDatabaseFile();
349 QFile file(getCfgFile());
350
351 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) /* Flawfinder: ignore */
352 {
353 //return dbPath;
354 //return getKLogDatabaseFile(dbPath);
355 }
356 else
357 {
358 while (!file.atEnd()) {
359 QByteArray line = file.readLine();
360 processConfigLine(line);
361 }
362 if (dbPath.length()<1)
363 {
364 dbPath = getKLogDefaultDatabaseFile();
365 }
366 }
367 //qDebug() << "Utilities::getKLogDBFile: path to use: " << dbPath ;
368 return dbPath + "/" + QDateTime::currentDateTime().toString("yyyyMMdd-hhmmss") + "-backup-logbook.dat" ;
369 }
370
processConfigLine(const QString & _line)371 bool Utilities::processConfigLine(const QString &_line)
372 {
373 //qDebug() << "Utilities::processConfigLine: " << _line ;
374
375 QString line = _line.simplified();
376 //line.simplified();
377 //QString aux;
378 QStringList values = line.split("=", QT_SKIP);
379
380 if (line.startsWith('#')){
381 //qDebug() << "Utilities::processConfigLine: notes Line!" ;
382 return true;
383 }
384 if (!( (line.contains('=')) && (line.contains(';')))){
385 //qDebug() << "Utilities::processConfigLine: Wrong Line!" ;
386 return false;
387 }
388 QString field = (values.at(0)).toUpper();
389 QString value = values.at(1);
390
391 int endValue = value.indexOf(';');
392 if (endValue>-1){
393 value = value.left(value.length() - (value.length() - endValue));
394 }
395
396 if (field == "DBPATH")
397 {
398 //qDebug() << "Utilities::processConfigLine: dbPATH found: " << value ;
399 dbPath = value;
400 }
401 return true;
402 }
403
404 /*
405 QString Utilities::getKLogDatabaseFile(const QString &_file)
406 {
407 //qDebug() << "Utilities::getKLogDatabaseFile:" << _file ;
408 if ( QFile::exists(_file + "/logbook.dat") )
409 {
410 //qDebug() << "Utilities::getKLogDatabaseFile:returning: " << _file + "/logbook.dat" ;
411 return _file + "/logbook.dat";
412 }
413 //qDebug() << "Utilities::getKLogDatabaseFile: Does not exist so default: " << getKLogDefaultDatabaseFile() ;
414 return getKLogDefaultDatabaseFile();
415 }
416 */
417
getCfgFile()418 QString Utilities::getCfgFile()
419 {
420 //TODO: To be removed when the defaultDir is saved in the config file
421 #if defined(Q_OS_WIN)
422 //qDebug() << "WINDOWS DETECTED!: " << getHomeDir() + "/klogrc.cfg" ;
423 return getHomeDir() + "/klogrc.cfg";
424
425 #else
426 //qDebug() << "NO WINDOWS DETECTED!: " << getHomeDir() + "/klogrc.cfg" ;
427 return getHomeDir() + "/klogrc";
428
429 #endif
430 }
431
getDebugLogFile()432 QString Utilities::getDebugLogFile()
433 {
434 #if defined(Q_OS_WIN)
435 //qDebug() << "WINDOWS DETECTED!: " << getHomeDir() + "/klogrc.cfg" ;
436 return getHomeDir() + "/klogdebug.log";
437
438 #else
439 //qDebug() << "NO WINDOWS DETECTED!: " << getHomeDir() + "/klogrc.cfg" ;
440 return getHomeDir() + "/klogdebug.log";
441
442 #endif
443 }
444
getSaveSpotsLogFile()445 QString Utilities::getSaveSpotsLogFile()
446 {
447 QString filename = "/" + (QDateTime::currentDateTime()).toString("yyyyMMdd") + "-klogdxcluster.txt";
448 return getHomeDir() + filename;
449 }
450
getBackupADIFile()451 QString Utilities::getBackupADIFile()
452 {
453 return getHomeDir() + "/" + (QDateTime::currentDateTime()).toString("yyyyMMdd-hhmm") + "-klogbackup.adi";
454 }
455
getClubLogFile()456 QString Utilities::getClubLogFile()
457 {
458 return getHomeDir() + "/klog-clublog-upload.adi";
459 }
460
getEQSLFile()461 QString Utilities::getEQSLFile()
462 {
463 return getHomeDir() + "/klog-eqsl-upload.adi";
464 }
465
getLoTWAdifFile()466 QString Utilities::getLoTWAdifFile()
467 {
468 return getHomeDir() + "/klog-lotw-upload.adi";
469 }
470
getTQSLsFileName()471 QString Utilities::getTQSLsFileName()
472 {
473 //qDebug() << "Utilities::getTQSLsFileName: " ;
474
475 #if defined(Q_OS_WIN)
476 //qDebug() << "WINDOWS DETECTED!: " ;
477 return "tqsl.exe";
478 #elif defined(Q_OS_MACOS)
479 //qDebug() << "macOS DETECTED!: " ;
480 return "tqsl.app";
481 #else
482 //qDebug() << "NO WINDOWS/macOS DETECTED!: " ;
483 return "tqsl";
484 #endif
485 }
486
getTQSLsPath()487 QString Utilities::getTQSLsPath()
488 {
489 //qDebug() << "Utilities::getDefaultProgramsPath " ;
490
491 #if defined(Q_OS_WIN64)
492 //qDebug() << "WINDOWS DETECTED!: " ;
493 return "C:/Program Files/TrustedQSL/";
494 #elif defined(Q_OS_WIN32)
495 return "C:/Program Files (x86)/TrustedQSL/";
496 #elif defined(Q_OS_MACOS)
497 //qDebug() << "macOS DETECTED!: " ;
498 return "/Applications/TrustedQSL/";
499 #else
500 //qDebug() << "NO WINDOWS/macOS DETECTED!: " ;
501 return "/usr/bin/";
502 #endif
503 }
504
getCTYFile()505 QString Utilities::getCTYFile()
506 {
507 return getHomeDir() + "/cty.csv";
508 }
509
getNormalizedDXCCValue(const int _dxcc)510 int Utilities::getNormalizedDXCCValue(const int _dxcc)
511 {
512 if (_dxcc >1000)
513 {
514 return ((QString::number(_dxcc)).rightRef(3)).toInt();
515 }
516 else
517 {
518 return _dxcc;
519 }
520 }
521
getDefaultDate()522 QDate Utilities::getDefaultDate()
523 {
524 //return QDate::fromString("18000101", "yyyyMMdd");
525 return QDate::currentDate();
526 }
527
isValidDate(const QDate _d)528 bool Utilities::isValidDate(const QDate _d)
529 {
530 //qDebug() << "Utilities::isValidDate: " << _d.toString("yyyyMMdd") ;
531 if (_d.isValid())
532 {
533 if ( _d > QDate::fromString("18000101", "yyyyMMdd") )
534 {
535 //qDebug() << "Utilities::isValidDate: OK" ;
536 return true;
537 }
538 }
539 //qDebug() << "Utilities::isValidDate: Error" ;
540 return false;
541 }
542
isValidDateTime(const QString & _d)543 bool Utilities::isValidDateTime(const QString &_d)
544 {
545 //qDebug() << "Utilities::isValidDateTime: " << _d ;
546 QDateTime _dateTime = QDateTime::fromString(_d, "yyyyMMddhhmmss");
547 if ( _dateTime.isValid() )
548 {
549 //qDebug() << "Utilities::isValidDateTime: 1" ;
550 return isValidDate(_dateTime.date());
551 }
552 //qDebug() << "Utilities::isValidDateTime: Error" ;
553 return false;
554 }
555
isValidSubCall(const QString & _c)556 bool Utilities::isValidSubCall(const QString &_c)
557 {
558 //qDebug() << "Utilities::isValidSubCall: " << _c ;
559 // This functions only checks simple calls like EA4K, not composed like EA4K/F of F/EA4K/QRP
560 //Rules: http://life.itu.int/radioclub/rr/art19.pdf
561 if (_c.contains ('/'))
562 {
563 return false;
564 }
565 if (_c.length()<3)
566 {
567 //qDebug() << "Utilities::isValidSubCall: FALSE-1: " << _c ;
568 return false;
569 }
570 if (!(_c.at(_c.length ()-1).isLetter ()))
571 {
572 //qDebug() << "Utilities::isValidSubCall: FALSE-1.1: " << _c ;
573 return false;
574 }
575 for (int i = 0; i<_c.length ();i++)
576 {
577 if (!_c.at(i).isLetterOrNumber ())
578 {
579 // Non valid chars
580 return false;
581 }
582 }
583
584 int prefixLength = isAPrefix (_c);
585 if (prefixLength<1)
586 {
587 //qDebug() << "Utilities::isValidSubCall: FALSE-1.2: " << _c ;
588 return false;
589 }
590
591 int i = prefixLength;
592 //qDebug() << "Utilities::isValidSubCall: prefixLength" << QString::number(prefixLength) ;
593 //qDebug() << "Utilities::isValidSubCall: call" << _c ;
594 while(i<_c.length ()-1)
595 {
596 if (!((_c.at(i).isLetter()) ))
597 {
598 //qDebug() << "Utilities::isValidSubCall: FALSE-1.3: " << _c ;
599 return false;
600 }
601 i++;
602 }
603 //qDebug() << "Utilities::isValidSubCall: true" ;
604 return true;
605 }
606
isAPrefix(const QString & _c)607 int Utilities::isAPrefix (const QString &_c)
608 {
609 // Returns -1 if it is not a prefix or valid call.
610 // Returns an int with the lenght of the prefix:
611 // The length would be including the number, if possible EA4 or;
612 // including just the country prefix: EA if the number is not included.
613
614 //qDebug() << "Utilities::isAPrefix: " << _c ;
615 // Prefixes are at least 1 chars (like in K1K)
616 int length = _c.length ();
617
618 if (length < 1)
619 {
620 //qDebug() << "Utilities::isAPrefix: TOO short prefix - false - END \n";
621 return -1;
622 }
623
624 QString call = _c;
625 //qDebug() << "Utilities::isAPrefix: -10: " << call.at(0) ;
626 QChar firstChar = call.at(0);
627 QList<QChar> validFirstLettersOnly = {'B', 'F', 'G', 'I', 'K', 'M', 'N', 'R', 'W'};
628
629 if (length == 1)
630 {
631 if (validFirstLettersOnly.contains (firstChar))
632 {
633 //qDebug() << "Utilities::isAPrefix: VALID 1 letter" ;
634 return 1;
635 }
636 else
637 {
638 //qDebug() << "Utilities::isAPrefix: NOT VALID 1 letter" ;
639 return -1;
640 }
641 }
642
643 QChar secondChar = call.at(1);
644 //qDebug() << "Utilities::isAPrefix: SecondChar: " << secondChar ;
645 int pref = -1;
646 if (call.count(QRegularExpression("\\d")) >0) // Does it has any digit?
647 {
648 //qDebug() << "Utilities::isAPrefix: It has digits: " << call ;
649 bool done = false;
650 int i = -1;
651 while ((i < length-1) && !done)
652 {
653 //qDebug() << "Utilities::isAPrefix: in the while: " << QString::number(i) ;
654 i++;
655 if (call.at(i).isLetter ())
656 {
657 //qDebug() << "Utilities::isAPrefix: in the while: is a Letter: " << call.at(i) ;
658 if (pref>0)
659 {
660 pref = i;
661 done = true;
662 }
663 }
664 else
665 {
666 //qDebug() << "Utilities::isAPrefix: in the while: is NOT a Letter: " << call.at(i) ;
667 if (i > 0)
668 {
669 pref = i;
670 }
671 }
672 } // end of while
673 }
674
675 //qDebug() << "Utilities::isAPrefix: After the while: " << QString::number(pref) ;
676
677 QString prefix;
678 if (pref>0)
679 {
680 //qDebug() << "Utilities::isAPrefix: pref>0 =>: " << call.left (pref) ;
681 prefix = call.left (pref);
682 }
683 else
684 {
685 prefix = call;
686 //qDebug() << "Utilities::isAPrefix: pref<=0 =>: " << call ;
687 }
688
689 length = prefix.length();
690
691 QChar thirdChar = QChar();
692 if (length>2)
693 {
694 thirdChar = prefix.at(2);
695 }
696
697 //qDebug() << "Utilities::isAPrefix: -50 " ;
698 // The first two characters shall be two letters or a letter followed
699 // by a digit or a digit followed by a letter. The first two characters or in certain cases
700 // the first character of a call sign constitute the nationality identification
701
702 if (firstChar.isDigit() && secondChar.isDigit())
703 {
704 //qDebug() << "Utilities::isAPrefix: FALSE-6: " << prefix ;
705 return -1;
706 }
707
708 //qDebug() << "Utilities::isAPrefix: -60 " ;
709 if (firstChar.isLetter() && secondChar.isLetter() && thirdChar.isLetter())
710 {
711 //qDebug() << "Utilities::isAPrefix: FALSE-6: " << prefix ;
712 return -1;
713 }
714
715 //qDebug() << "Utilities::isAPrefix: -70 " ;
716
717 QList<QChar> validFirstLetters = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'P', 'R', 'S', 'T' ,'U', 'V', 'W', 'Z'};
718
719 if (secondChar.isDigit ())
720 {
721 if (!validFirstLetters.contains (firstChar))
722 {
723 //qDebug() << "Utilities::isAPrefix: NOT VALID 1 letter not valid" ;
724 return -1;
725 }
726 }
727 /*
728 // The following if is to manage not format but specific IARU callsign assignments
729 // defined here: http://life.itu.int/radioclub/rr/ap42.pdf
730 // For the time being, KLog will not check that
731 if ( (firstChar.isLetter ()) && (secondChar.isDigit ()) && (validFirstLetters.contains(firstChar)))
732 {
733 //qDebug() << "Utilities::isAPrefix validFirstLetters contains the first one!" ;
734 if (firstChar == 'C')
735 {
736 if ((secondChar == '1') || (secondChar == '7'))
737 {
738 //qDebug() << "Utilities::isAPrefix: FALSE-7.1: " << prefix ;
739 return false;
740 }
741 }
742 if (firstChar == 'D')
743 {
744 //((secondChar == '1') || (secondChar == '8'))
745 if (false)
746 {
747 //qDebug() << "Utilities::isAPrefix: FALSE-7.2: " << prefix ;
748 return false;
749 }
750 }
751 if (firstChar == 'E')
752 {
753 if (!(secondChar == '2') && !(secondChar == '3') && !(secondChar == '4') && !(secondChar == '7')
754 {
755 //qDebug() << "Utilities::isAPrefix: FALSE-7.3: " << prefix ;
756 return false;
757 }
758 }
759 if (firstChar == 'H')
760 {
761 if ((secondChar == '1') )
762 {
763 //qDebug() << "Utilities::isAPrefix: FALSE-7.4: " << prefix ;
764 return false;
765 }
766 }
767 if (firstChar == 'J')
768 {
769 if ((secondChar == '1') || (secondChar == '9'))
770 {
771 //qDebug() << "Utilities::isAPrefix: FALSE-7.5: " << prefix ;
772 return false;
773 }
774 }
775 if (firstChar == 'P')
776 {
777 if (secondChar == '1')
778 {
779 //qDebug() << "Utilities::isAPrefix: FALSE-7.6: " << prefix ;
780 return false;
781 }
782 }
783 if (firstChar == 'S')
784 {
785 if ((secondChar == '1') || (secondChar == '6'))
786 {
787 //qDebug() << "Utilities::isAPrefix: FALSE-7.7: " << prefix ;
788 return false;
789 }
790 }
791 if (firstChar == 'T')
792 {
793 if (secondChar == '0')
794 {
795 //qDebug() << "Utilities::isAPrefix: FALSE-7.8: " << prefix ;
796 return false;
797 }
798 }
799 if (firstChar == 'V')
800 {
801 if ((secondChar == '1') || (secondChar == '9'))
802 {
803 //qDebug() << "Utilities::isAPrefix: FALSE-7.9: " << prefix ;
804 return false;
805 }
806 }
807 if (firstChar == 'Z')
808 {
809 if (!((secondChar == '2') || (secondChar == '3')))
810 {
811 //qDebug() << "Utilities::isAPrefix: FALSE-7.10: " << prefix ;
812 return false;
813 }
814 }
815 //qDebug() << "Utilities::isAPrefix: 1-Letter + number prefix valid: " << prefix ;
816 }
817 */
818 //qDebug() << "Utilities::isAPrefix: After the if's" ;
819 // It seems to be a valid prefix, let's count how many chars belong to the prefix, first letter after the digit
820 // should be the suffix starting point
821
822 //qDebug() << "Utilities::isAPrefix: Prefix length: " << QString::number(pref) << "/" << prefix ;
823 if (pref>0)
824 {
825 return pref;
826 }
827 else
828 {
829 return prefix.length ();
830 }
831 }
832
setCallValidation(const bool _b)833 void Utilities::setCallValidation(const bool _b)
834 {
835 callValidation = _b;
836 }
837
isValidCall(const QString & _c)838 bool Utilities::isValidCall(const QString &_c)
839 {
840 //qDebug() << "Utilities::isValidCall: " << _c ;
841 // Prefixes are at least 2 chars
842 if (!g_callsignCheck)
843 {
844 //qDebug() << "Utilities::isValidCall - 009" ;
845 return true;
846 }
847 //qDebug() << "Utilities::isValidCall - 010" ;
848 QString call = _c;
849 if (_c.length()<3)
850 {
851 //qDebug() << "Utilities::isValidCall: FALSE-1: " << _c ;
852 return false;
853 }
854 //qDebug() << "Utilities::isValidCall - 015" ;
855 call.replace('\\', '/');
856
857 if (call.count('/')>2)
858 {
859 //qDebug() << "Utilities::isValidCall: FALSE-3: " << call;
860 return false;
861 }
862 //qDebug() << "Utilities::isValidCall - 020" ;
863 if (call.count('/') == 2)
864 { //Things like F/EA4K/P will become F/EA4K
865 //qDebug() << "Utilities::isValidCall: Two /; Ignoring the last part: " << call ;
866 QStringList parts;
867 parts.clear();
868 parts << call.split('/');
869 call = parts.at(0) + "/" + parts.at(1);
870 }
871 //qDebug() << "Utilities::isValidCall - 025" ;
872 //qDebug() << "Utilities::isValidCall: Call: " << call ;
873
874 if (call.count('/') == 1)
875 { // Complex calls (like F/EA4K or EA4K/F OR /p OR /qrp
876 // We are just checking the call format not if it belongs to a country or whatever.
877 // It may return true for wrong calls like "ABC/EA4K"
878 // TODO: Add a check just for prefixes to fix the previous
879 //qDebug() << "Utilities::isValidCall: Call with one /: " << call ;
880 QStringList parts;
881 parts.clear();
882 parts << call.split ('/');
883
884 //return ( ((isAPrefix (parts.at (0)))>0) || ((isAPrefix (parts.at (1)))>0) || (isValidSubCall (parts.at(0)) ) || (isValidSubCall (parts.at(1)) ));
885
886
887 if (parts.at(0).length ()<parts.at(1).length ())
888 {
889 return ( ((isAPrefix (parts.at (0)))>0) && (isValidSubCall (parts.at(1)) ) );
890 }
891 else
892 { //Both lenght are just the same or the second is showter, we need to check both parts and return true if one is valid
893 // It may happen that we have a EA4K/QRP or EA4K/F or EA4K/TTT
894 return isValidSubCall (parts.at(0));
895 }
896 }
897 return isValidSubCall (call);
898 }
899
getPrefixFromCall(const QString & _c)900 QString Utilities::getPrefixFromCall(const QString &_c)
901 {
902 //qDebug() << "Utilities::getPrefixFromCall: " << _c ;
903 QString call = _c;
904 call.replace('\\', '/');
905
906 if (call.count('/') == 2)
907 { //Things like F/EA4K/P will become F/EA4K
908 QStringList parts;
909 parts.clear();
910 parts << call.split('/');
911 call = parts.at(0) + "/" + parts.at(1);
912 }
913
914 //QString prefix = QString();
915 int pref = -1;
916 if (call.count('/') == 1)
917 { // Complex calls (like F/EA4K or EA4K/F OR /p OR /qrp
918 QStringList parts;
919 parts.clear();
920 parts << call.split ('/');
921 if (parts.at(0).length ()<parts.at(1).length ())
922 { // First one is shorter
923 //qDebug() << "Utilities::getPrefixFromCall: First one is shorter: " ;
924 int pref = isAPrefix (parts.at(0));
925 if (pref>0)
926 {
927 //qDebug() << "Utilities::getPrefixFromCall: R1=" << call.left (pref) ;
928 return parts.at(0);
929 }
930 else
931 {
932 //qDebug() << "Utilities::getPrefixFromCall: EMPTY-2" ;
933 return QString();
934 }
935 }
936 else if(parts.at(0).length ()>parts.at(1).length ())
937 { // Second one is shorter
938 //qDebug() << "Utilities::getPrefixFromCall: Second one is shorter: " ;
939 pref = isAPrefix (parts.at(1));
940 if (pref>0)
941 {
942 //qDebug() << "Utilities::getPrefixFromCall: R2=" << parts.at(1) ;
943
944 return parts.at(1);
945 }
946 else
947 {
948 pref = isAPrefix (parts.at(0));
949 if (pref>0)
950 {
951 //qDebug() << "Utilities::getPrefixFromCall: R3=" << parts.at(0).left (pref) ;
952 return parts.at(0).left (pref);
953 }
954 else
955 {
956 //qDebug() << "Utilities::getPrefixFromCall: EMPTY-3" ;
957 return QString();
958 }
959 }
960 }
961 else
962 { //Both lenght are just the same, we need to check both parts and return true if one is valid
963 //qDebug() << "Utilities::getPrefixFromCall: Same length, we shoudl consider the first one if valid, if not the second one " ;
964 }
965 }
966
967 pref = isAPrefix (call);
968 if (pref>0)
969 {
970 //qDebug() << "Utilities::getPrefixFromCall: R4=" << call.left (pref) ;
971 return call.left (pref);
972 }
973 //qDebug() << "Utilities::getPrefixFromCall: EMPTY-4" ;
974 return QString();
975 }
976
977 /*
978 QPair<QString, QString> Utilities::getCallParts(const QString &_c)
979 { // DXCC prefix, if different from original, full call
980
981 QString call = _c;
982 QPair<QString, QString> pair;
983 pair.first = QString();
984 pair.second = QString();
985
986 if (_c.length()<3)
987 {
988 //qDebug() << "Utilities::isValidCall: FALSE-1: " << _c ;
989 return pair;
990 }
991
992 call.replace('\\', '/');
993
994 if (call.count('/')>2)
995 {
996 //qDebug() << "Utilities::isValidCall: FALSE-3: " << call ;
997 return pair;
998 }
999 if (call.count('/') == 2)
1000 { //Things like F/EA4K/P will become F/EA4K
1001 QStringList parts;
1002 parts.clear();
1003 parts << call.split('/');
1004 call = parts.at(0)+parts.at(1);
1005 }
1006 QString prefix = QString();
1007
1008 if (call.count('/') == 1)
1009 { // Complex calls (like F/EA4K or EA4K/F OR /p OR /qrp
1010 QStringList parts;
1011 parts.clear();
1012 parts << call.split('/');
1013 //qDebug() << "Utilities::isValidCall: first: " << parts.at(0) ;
1014 //qDebug() << "Utilities::isValidCall: second: " << parts.at(1) ;
1015
1016 QStringList validSuffixes = {"P", "M", "MM", "QRP", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"};
1017 if (validSuffixes.contains (parts.at(1)))
1018 {
1019 //qDebug() << "Utilities::isValidCall: returning a result just with: " << parts.at(1) ;
1020 pair.second = parts.at(1);
1021 return pair;
1022 }
1023
1024 if (parts.at(0).length ()<=parts.at(1).length ())
1025 {
1026 if (isAPrefix (parts.at(0))>0)
1027 //if (isAPrefix (parts.at(0)))
1028 {
1029 //qDebug() << "Utilities::isValidCall: first is shorter " ;
1030 pair.first = parts.at(0);
1031 pair.second = parts.at(1);
1032 }
1033 else
1034 {
1035 //qDebug() << "Utilities::isValidCall: first is shorter but not a prefix" ;
1036 return pair;
1037 }
1038 }
1039 else
1040 {
1041 //qDebug() << "Utilities::isValidCall: second is shorter " ;
1042 if (isAPrefix (parts.at(1))>0)
1043 {
1044
1045 pair.first = parts.at(1);
1046 pair.second = parts.at(0);
1047 }
1048 else
1049 {
1050 //qDebug() << "Utilities::isValidCall: second is shorter but not a prefix" ;
1051 return pair;
1052 }
1053 }
1054 }
1055 return pair;
1056 }
1057 */
1058
isSameFreq(const double fr1,const double fr2)1059 bool Utilities::isSameFreq(const double fr1, const double fr2)
1060 {
1061 //qDebug() << Q_FUNC_INFO << ": " << QString::number(fr1) << "/" << QString::number(fr2) << " = " << QString::number(fabs(fr1 - fr2)) ;
1062
1063 if (fabs(fr1 - fr2) < 0.001)
1064 {
1065 //qDebug() << Q_FUNC_INFO << " - true" ;
1066 return true;
1067 }
1068 else
1069 {
1070 //qDebug() << Q_FUNC_INFO << " - false" ;
1071 return false;
1072 }
1073 //return fabs(fr1 - fr2) < 0.001;
1074 }
1075
isValidBandId(const int _b)1076 bool Utilities::isValidBandId(const int _b)
1077 {
1078 if (_b>0)
1079 {
1080 return true;
1081 }
1082 else
1083 {
1084 return false;
1085 }
1086 //return false;
1087 }
1088
isValidModeId(const int _m)1089 bool Utilities::isValidModeId(const int _m)
1090 {
1091 if (_m>0)
1092 {
1093 return true;
1094 }
1095 else
1096 {
1097 return false;
1098 }
1099 //return false;
1100 }
1101
isValidFreq(const QString & _b)1102 bool Utilities::isValidFreq(const QString &_b)
1103 {
1104 if (_b.toDouble()>0)
1105 {
1106 return true;
1107 }
1108 else
1109 {
1110 return false;
1111 }
1112 //return false;
1113 }
1114
isValidGrid(const QString & _b)1115 bool Utilities::isValidGrid(const QString &_b)
1116 {
1117 Locator locator;
1118 return locator.isValidLocator(_b);
1119 }
1120
isValidVUCCGrids(const QString & _b)1121 bool Utilities::isValidVUCCGrids(const QString &_b)
1122 {
1123 //qDebug() << Q_FUNC_INFO << ": " << _b;
1124 QStringList tmp;
1125
1126 //QString a = _b;
1127 tmp.clear ();
1128 tmp << _b.split (',', QT_SKIP);
1129
1130 if ((tmp.length ()!=2) && (tmp.length ()!=4))
1131 {
1132 //qDebug() << Q_FUNC_INFO << ": NON VALID LENGTH";
1133 return false;
1134 }
1135
1136 //qDebug() << Q_FUNC_INFO << ": tmp: " << tmp;
1137 QString aux;
1138 foreach (aux, tmp) {
1139 aux = aux.trimmed ();
1140
1141 if ((!isValidGrid (aux)) || (aux.length ()!=4))
1142 {
1143 //qDebug() << Q_FUNC_INFO << ": NON VALID";
1144 return false;
1145 }
1146 else
1147 {
1148 //qDebug() << Q_FUNC_INFO << ": VALID: " << aux;
1149 }
1150 }
1151 //qDebug() << Q_FUNC_INFO << ": VALID-END";
1152 return true;
1153 }
1154
isValidRST(const QString & _b)1155 bool Utilities::isValidRST(const QString &_b)
1156 {
1157 if (_b.length()>0)
1158 {
1159 return true;
1160 }
1161 return false;
1162 }
1163
isValidPower(const QString & _b)1164 bool Utilities::isValidPower(const QString &_b)
1165 {
1166 if (_b.toDouble()>0)
1167 {
1168 return true;
1169 }
1170 return false;
1171 }
1172
isValidComment(const QString & _b)1173 bool Utilities::isValidComment(const QString &_b)
1174 {
1175 if (_b.length()>0)
1176 {
1177 return true;
1178 }
1179 return false;
1180 }
1181
isValidName(const QString & _b)1182 bool Utilities::isValidName(const QString &_b)
1183 {
1184 if (_b.length()>0)
1185 {
1186 return true;
1187 }
1188 return false;
1189 }
1190
isDBFileExisting()1191 bool Utilities::isDBFileExisting()
1192 {
1193 //qDebug() << "Utilities::isDBFileExisting: " << getKLogDBFile() ;
1194 if (QFile::exists(getKLogDBFile()))
1195 {
1196 //qDebug() << "Utilities::isDBFileExisting - true" ;
1197 return true;
1198 }
1199 else
1200 {
1201 //qDebug() << "Utilities::isDBFileExisting - false" ;
1202 return false;
1203 }
1204 //return false;
1205 }
1206
isDBFileExisting(const QString & _file)1207 bool Utilities::isDBFileExisting(const QString &_file)
1208 {
1209 //qDebug() << "Utilities::isDBFileExisting2: " << _file ;
1210
1211 if (QFile::exists(_file))
1212 {
1213 //qDebug() << "Utilities::isDBFileExisting2 - true" ;
1214 return true;
1215 }
1216 else
1217 {
1218 //qDebug() << "Utilities::isDBFileExisting2 - false" ;
1219 return false;
1220 }
1221 //return false;
1222 }
1223
isValidADIFField(const QString & _b)1224 bool Utilities::isValidADIFField(const QString &_b)
1225 {
1226 //qDebug() << "Utilities::isValidADIFField: " << _b ;
1227 /*
1228 This functions checks if the ADIF field has the proper format.
1229 <Field:length:Data type>Data
1230 */
1231
1232 if (!((_b.startsWith('<')) && (_b.count('>')) == 1 ))
1233 {
1234 //qDebug() << "Utilities::isValidADIFField: BAD FORMAT: No < or > delimiters: " << _b ;
1235 return false;
1236 }
1237 if (_b.simplified() == "<EOR>")
1238 {
1239 return true;
1240 }
1241
1242 QStringList validDataTypes = {"B", "N", "D", "T", "S", "I", "M", "G", "E", "L"};
1243 QStringList qs;
1244 qs.clear();
1245 qs.append(_b.split('>'));
1246
1247 if (qs.size()!= 2)
1248 {
1249 //qDebug() << "Utilities::isValidADIFField-0 (not two): " << QString::number(qs.size()) ;
1250 return false;
1251 }
1252
1253 QString field = (qs.at(0)).right((qs.at(0)).length() - 1);
1254 QString data = (qs.at(1)).simplified();
1255 //data = data.simplified();
1256 QString dataType = QString();
1257
1258 //qDebug() << "Utilities::isValidADIFField-Field: " << field ;
1259 //qDebug() << "Utilities::isValidADIFField_Data: " << data ;
1260
1261 int length = data.length();
1262 int separatorPosition = 0;
1263 int i = (field).count(":"); //Check how many ":" do we have, to see if we have a data type or not
1264
1265 if (i == 2) // We have data type
1266 { // DATE:8:D / 20141020
1267 separatorPosition = (field.section(':', 1, 1)).toInt();
1268 dataType = field.section(':', 2, 2);
1269 if (!validDataTypes.contains(dataType.toUpper()))
1270 {
1271 //qDebug() << "Utilities::isValidADIFField - FORMAT ERROR: Wrong data type: " << dataType ;
1272 return false;
1273 }
1274 }
1275 else if (i == 1)
1276 { // DATE:8 / 20141020
1277 separatorPosition = (field.section(':', 1, 1)).toInt();
1278 }
1279 else
1280 {
1281 //qDebug() << "Utilities::isValidADIFField - FORMAT ERROR, more than 2 \":\" - " << field ;
1282 return false;
1283 }
1284
1285 if ( length != separatorPosition)
1286 {
1287 //qDebug() << "Utilities::isValidADIFField: Data Length problem: " << (field) << "/" << data << " - " << QString::number(length) << "/" << QString::number(separatorPosition) ;
1288 return false;
1289 }
1290
1291 if (separatorPosition <= 0)
1292 {
1293 //qDebug() << "Utilities::isValidADIFField: Length problem <= 0" ;
1294 return false;
1295 }
1296
1297 //qDebug() << "FileManager::checkADIFValidFormat: Return true" ;
1298 return true;
1299 }
1300
isValidQSL_Rcvd(const QString & c)1301 bool Utilities::isValidQSL_Rcvd(const QString &c)
1302 {
1303 if ((c == "Y") || (c == "N") || (c == "R") || (c == "I") || (c == "V"))
1304 {
1305 return true;
1306 }
1307 else {
1308 return false;
1309 }
1310 }
1311
isValidQSL_Sent(const QString & c)1312 bool Utilities::isValidQSL_Sent(const QString &c)
1313 {
1314 if ((c == "Y") || (c == "N") || (c == "R") || (c == "Q") || (c == "I"))
1315 {
1316 return true;
1317 }
1318 else
1319 {
1320 return false;
1321 }
1322 }
1323
isValidUpload_Status(const QString & c)1324 bool Utilities::isValidUpload_Status(const QString &c)
1325 {
1326 if ((c == "Y") || (c == "N") || (c == "M"))
1327 {
1328 return true;
1329 }
1330 else {
1331 return false;
1332 }
1333 }
1334
getValidADIFFieldAndData(const QString & _b)1335 QStringList Utilities::getValidADIFFieldAndData(const QString &_b)
1336 {
1337 //qDebug() << "Utilities::getValidADIFFieldAndData: " << _b ;
1338 /*
1339 This functions checks if the ADIF field has the proper format.
1340 <Field:length:Data type>Data
1341 */
1342 QStringList result;
1343 result.clear();
1344
1345 if (!(_b.startsWith('<')))
1346 {
1347 //qDebug() << "Utilities::getValidADIFFieldAndData: BAD FORMAT: No < or > delimiters: " << _b ;
1348 return QStringList();
1349 }
1350 if (_b.simplified() == "<EOR>")
1351 {
1352 //qDebug() << "Utilities::getValidADIFFieldAndData: EOR" ;
1353 result << "EOR" << "EOR";
1354 return result;
1355 }
1356 QString aux = _b;
1357 QStringList qs;
1358 qs.clear();
1359
1360 if ((aux.contains("APP_LOTW_")) && aux.contains("//"))
1361 { // Trying to fix a LoTW ADIF bug
1362 qs.append(aux.split("//"));
1363 aux = qs.at(0);
1364 }
1365
1366 //qDebug() << "Utilities::getValidADIFFieldAndData: -20" ;
1367 QStringList validDataTypes = {"B", "N", "D", "T", "S", "I", "M", "G", "E", "L"};
1368
1369 qs.clear();
1370 qs.append(aux.split('>'));
1371
1372 if (qs.size()!= 2)
1373 {
1374 //qDebug() << "Utilities::getValidADIFFieldAndData-0 (not two): " << QString::number(qs.size()) ;
1375 return result;
1376 }
1377 //qDebug() << "Utilities::getValidADIFFieldAndData: -30" ;
1378 //QString field = (qs.at(0)).right((qs.at(0)).length() - 1);
1379 QString field = (qs.at(0)).right((qs.at(0)).length() - 1);
1380 QString data = (qs.at(1)).simplified();
1381 //data = data.simplified();
1382 QString dataType = QString();
1383
1384 //qDebug() << "Utilities::getValidADIFFieldAndData-Field: " << field ;
1385 //qDebug() << "Utilities::getValidADIFFieldAndData_Data: " << data ;
1386
1387 int length = data.length();
1388 int separatorPosition = 0;
1389 int i = (field).count(":"); //Check how many ":" do we have, to see if we have a data type or not
1390
1391 if (i == 2) // We have data type
1392 { // DATE:8:D / 20141020
1393 separatorPosition = (field.section(':', 1, 1)).toInt();
1394 dataType = field.section(':', 2, 2);
1395 //qDebug() << "Utilities::getValidADIFFieldAndData - DataType: -" << dataType << "-" ;
1396 if (!validDataTypes.contains(dataType.toUpper()))
1397 {
1398 //qDebug() << "Utilities::getValidADIFFieldAndData - FORMAT ERROR: Wrong data type: " << dataType ;
1399 return result;
1400 }
1401 }
1402 else if (i == 1)
1403 { // DATE:8 / 20141020
1404 separatorPosition = (field.section(':', 1, 1)).toInt();
1405 }
1406 else
1407 {
1408 //qDebug() << "Utilities::getValidADIFFieldAndData - FORMAT ERROR, more than 2 \":\" - " << field ;
1409 return result;
1410 }
1411 //qDebug() << "Utilities::getValidADIFFieldAndData: -60" ;
1412 if ( length != separatorPosition)
1413 {
1414 //qDebug() << "Utilities::getValidADIFFieldAndData: Data Length problem: " << (field) << "/" << data << " - " << QString::number(length) << "/" << QString::number(separatorPosition) ;
1415 return result;
1416 }
1417
1418 if (separatorPosition <= 0)
1419 {
1420 //qDebug() << "Utilities::getValidADIFFieldAndData: Length problem <= 0" ;
1421 return result;
1422 }
1423 //qDebug() << "Utilities::getValidADIFFieldAndData: -90: f: " << field ;
1424 //qDebug() << "Utilities::getValidADIFFieldAndData: -90: d: " << data<< endl;
1425 //field = field.section(':', 0, 0);
1426 result.clear();
1427 result << field.section(':', 0, 0) << data;
1428 //qDebug() << "Utilities::checkADIFValidFormat: Return true: " << result.at(0) << "/" << result.at(1) ;
1429 return result;
1430 }
1431
getAValidCall(const QString & _wrongCall)1432 QString Utilities::getAValidCall (const QString &_wrongCall)
1433 {
1434 //qDebug() << "Utilities::getAValidCall: " << _wrongCall ;
1435 QString _confirmedCall;
1436 _confirmedCall.clear();
1437
1438 bool ok;
1439 if (_wrongCall.length() > 0)
1440 {
1441 //qDebug() << "Utilities::getAValidCall (Don't have VALID CALL): " << _wrongCall ;
1442 _confirmedCall = QString(QObject::tr("A wrong callsign has been found: %1. Please enter a new callsign or confirm that the current one is a good callsign.")).arg(_wrongCall);
1443 }
1444 else
1445 {
1446 //qDebug() << "Utilities::getAValidCall (Don't have ANY CALL): " << _wrongCall ;
1447 _confirmedCall = QString(QObject::tr("An empty callsign has been detected. If it is possible, please enter the right call."));
1448 }
1449
1450 QString text = QInputDialog::getText(nullptr, QObject::tr("KLog - Not valid callsign found"),
1451 _confirmedCall, QLineEdit::Normal, _wrongCall, &ok);
1452 if (!(ok && isValidCall(text)))
1453 {
1454 _confirmedCall = text;
1455 }
1456 else
1457 {
1458 _confirmedCall = QString();
1459 }
1460 //qDebug() << "Utilities::getAValidCall: " << _confirmedCall ;
1461 return _confirmedCall;
1462 }
1463
getDateTimeSQLiteStringFromDateTime(const QDateTime & _d)1464 QString Utilities::getDateTimeSQLiteStringFromDateTime(const QDateTime &_d)
1465 {
1466 return QString(_d.toString("yyyy-MM-dd hh:mm:ss"));
1467 }
1468
getDateSQLiteStringFromDate(const QDate & _d)1469 QString Utilities::getDateSQLiteStringFromDate(const QDate &_d)
1470 {
1471 return QString(_d.toString("yyyy-MM-dd"));
1472 }
1473
isValidDateFromString(const QString & _s)1474 bool Utilities::isValidDateFromString(const QString &_s)
1475 {
1476 return getDateFromSQliteString(_s).isValid();
1477 }
1478
isValidTimeFromString(const QString & _s)1479 bool Utilities::isValidTimeFromString(const QString &_s)
1480 {
1481 return getDateTimeFromSQLiteString(_s).time().isValid();
1482 }
1483
isValidDateTimeFromString(const QString & _s)1484 bool Utilities::isValidDateTimeFromString(const QString &_s)
1485 {
1486 return getDateTimeFromSQLiteString(_s).isValid();
1487 }
1488
isValidDXCC(const int _d)1489 bool Utilities::isValidDXCC(const int _d)
1490 {//TODO: Look for a better way to check, taking into account how KLog is identifiying the DXCC
1491 if (((_d > 0) && (_d < 523)) || (_d == 1206) || (_d == 1279) || (_d == 1248) || (_d == 2248) || (_d == 1259) || (_d == 1390))
1492 {
1493 return true;
1494 }
1495 else
1496 {
1497 return false;
1498 }
1499 }
1500
getDateTimeFromSQLiteString(const QString & _s)1501 QDateTime Utilities::getDateTimeFromSQLiteString(const QString &_s)
1502 {
1503 return QDateTime::fromString(_s, "yyyy-MM-dd hh:mm:ss");
1504 }
1505
getTimeFromSQLiteString(const QString & _s)1506 QTime Utilities::getTimeFromSQLiteString(const QString &_s)
1507 {
1508 if (_s.length()==5)
1509 {
1510 return QTime::fromString(_s, "hh:mm");
1511 }
1512 else
1513 {
1514 return QTime::fromString(_s, "hh:mm:ss");
1515 }
1516 }
1517
getDateFromSQliteString(const QString & _s)1518 QDate Utilities::getDateFromSQliteString(const QString &_s)
1519 {
1520 //It may receive "just" a date or a "date time".
1521
1522 if (getDateTimeFromSQLiteString(_s).isValid()) // if we have received a full date time
1523 {
1524 return (getDateTimeFromSQLiteString(_s)).date();
1525 }
1526 else // If we have received "just a date" or an error
1527 {
1528 return QDate::fromString(_s, "yyyy-MM-dd");
1529 }
1530 }
1531
getDateFromADIFDateString(const QString & _s)1532 QDate Utilities::getDateFromADIFDateString(const QString &_s)
1533 {// Expects an ADIF DATE format string: "YYYYMMDD"
1534 //qDebug() << "Utilities::getDateFromADIFDateString: " << _s ;
1535 return QDate::fromString(_s, "yyyyMMdd");
1536 }
1537
getTimeFromADIFTimeString(const QString & _s)1538 QTime Utilities::getTimeFromADIFTimeString(const QString &_s)
1539 {// Expects and ADIF TIME format String "HHMMSS" or "HHMM"
1540 //qDebug() << "Utilities::getTimeFromADIFTimeString: " << _s ;
1541 if (_s.length()==4)
1542 {
1543 return QTime::fromString(_s, "hhmm");
1544 }
1545 else
1546 {
1547 return QTime::fromString(_s, "hhmmss");
1548 }
1549 }
1550
getDateFromLoTWQSLDateString(const QString & _s)1551 QDate Utilities::getDateFromLoTWQSLDateString(const QString &_s)
1552 {
1553 //qDebug() << "Utilities::getDateFromLoTWQSLDateString: " << _s ;
1554 QStringList datet;
1555 datet.clear();
1556 if (_s.endsWith ('Z'))
1557 {
1558 datet << _s.split("T");
1559 }
1560 else
1561 {
1562 datet << _s.split(" ");
1563 }
1564 //qDebug() << "Utilities::getDateFromLoTWQSLDateString: " << datet.at(0) ;
1565 return QDate::fromString(datet.at(0), "yyyy-MM-dd");
1566 }
1567
1568
getADIFDateFromQDateTime(const QDateTime & _d)1569 QString Utilities::getADIFDateFromQDateTime(const QDateTime &_d)
1570 {
1571 if (!_d.isValid())
1572 {
1573 return QString();
1574 }
1575 else
1576 {
1577 return _d.date().toString("yyyyMMdd");
1578 }
1579 }
1580
getADIFDateFromQDate(const QDate & _d)1581 QString Utilities::getADIFDateFromQDate(const QDate &_d)
1582 {
1583 if (!_d.isValid())
1584 {
1585 return QString();
1586 }
1587 else
1588 {
1589 return _d.toString("yyyyMMdd");
1590 }
1591 }
1592
getADIFTimeFromQDateTime(const QDateTime & _d)1593 QString Utilities::getADIFTimeFromQDateTime(const QDateTime &_d)
1594 {
1595 if (!_d.isValid())
1596 {
1597 return QString();
1598 }
1599 else
1600 {
1601 return _d.time().toString("hhmmss");
1602 }
1603 }
1604
1605
getCabrilloDateFromQDate(const QDate & _d)1606 QString Utilities::getCabrilloDateFromQDate(const QDate &_d)
1607 {// Will produce the Cabrillo DATE format: "YYYY-MM-DD"
1608 if (!_d.isValid())
1609 {
1610 return QString("0000-00-00");
1611 }
1612 else
1613 {
1614 return _d.toString("yyyy-MM-dd");
1615 }
1616 }
1617
getCabrilloTimeFromQDateTime(const QDateTime & _d)1618 QString Utilities::getCabrilloTimeFromQDateTime(const QDateTime &_d)
1619 {// Will produce the Cabrillo TIME format: "HHMM"
1620 if (!_d.isValid())
1621 {
1622 return QString("0000");
1623 }
1624 else
1625 {
1626 return _d.time().toString("hhmm");
1627 }
1628 }
1629
getOnlineServiceName(OnLineProvider _service)1630 QString Utilities::getOnlineServiceName(OnLineProvider _service)
1631 {//enum OnLineProvider {ClubLog, LoTW, eQSL, QRZ}; //, HamQTH, HRDLog
1632 switch (_service)
1633 {
1634 case LoTW:
1635 {
1636 return "LoTW";
1637 }
1638 case ClubLog:
1639 {
1640 return "ClubLog";
1641 }
1642 case QRZ:
1643 {
1644 return "QRZ.com";
1645 }
1646 case eQSL:
1647 {
1648 return "eQSL.cc";
1649 }
1650 }
1651 return QString();
1652 }
1653
getClearSQLi(QString _s)1654 QString Utilities::getClearSQLi(QString _s)
1655 {
1656 return _s.remove ('\'');
1657 }
1658
1659 /*
1660 QPalette Utilities::getPalete(bool _ok)
1661 {
1662 //qDebug() << "Utilities::getPalete" ;
1663 if (_ok)
1664 {
1665 //qDebug() << "Utilities::getPalete - true" ;
1666 return palRed;
1667 //return QPalette::setColor(QPalette::Text, Qt::red);
1668 }
1669 else
1670 {
1671 //qDebug() << "Utilities::getPalete - false" ;
1672 return palBlack;
1673 }
1674 }
1675 */
1676
setDarkMode(const QString & _dm)1677 void Utilities::setDarkMode(const QString &_dm)
1678 {
1679 darkMode = trueOrFalse(_dm);
1680 }
1681
isDarkMode()1682 bool Utilities::isDarkMode()
1683 {
1684 if (darkMode)
1685 {
1686 return true;
1687 }
1688 else
1689 {
1690 return false;
1691 }
1692 }
1693
getLogColumnName(const QString & _column)1694 QString Utilities::getLogColumnName(const QString &_column)
1695 {
1696 //qDebug() << Q_FUNC_INFO << ": " << _column;
1697 if (_column == "qso_date")
1698 return QObject::tr("Date");
1699 else if (_column == "call")
1700 return QObject::tr("Call");
1701 else if (_column == "rst_sent")
1702 return QObject::tr("RSTtx");
1703 else if (_column == "rst_rcvd")
1704 return QObject::tr("RSTrx");
1705 else if (_column == "bandid")
1706 return QObject::tr("Band");
1707 else if (_column == "comment")
1708 return QObject::tr("Comment");
1709 else if (_column == "modeid")
1710 return QObject::tr("Mode");
1711 else if (_column == "cqz")
1712 return QObject::tr("CQz");
1713 else if (_column == "ituz")
1714 return QObject::tr("ITUz");
1715 else if (_column == "dxcc")
1716 return QObject::tr("DXCC");
1717 else if (_column == "address")
1718 return QObject::tr("Address");
1719 else if (_column == "age")
1720 return QObject::tr("Age");
1721 else if (_column == "cnty")
1722 return QObject::tr("County");
1723 else if (_column == "a_index")
1724 return QObject::tr("A_Index");
1725 else if (_column == "ant_az")
1726 return QObject::tr("Ant_Az");
1727 else if (_column == "ant_el")
1728 return QObject::tr("Ant_El");
1729 else if (_column == "ant_path")
1730 return QObject::tr("Ant_Path");
1731 else if (_column == "arrl_sect")
1732 return QObject::tr("ARRL_SECT");
1733 else if (_column == "award_submitted")
1734 return QObject::tr("Award_Submitted");
1735 else if (_column == "award_granted")
1736 return QObject::tr("Award_granted");
1737 else if (_column == "band_rx")
1738 return QObject::tr("Band_RX");
1739 else if (_column == "checkcontest")
1740 return QObject::tr("CheckContest");
1741 else if (_column == "class")
1742 return QObject::tr("Class");
1743 else if (_column == "clublog_qso_upload_date")
1744 return QObject::tr("ClubLog SDate");
1745 else if (_column == "clublog_qso_upload_staus")
1746 return QObject::tr("ClubLog status");
1747 else if (_column == "cont")
1748 return QObject::tr("Continent");
1749 else if (_column == "contacted_op")
1750 return QObject::tr("Contacted Op");
1751 else if (_column == "contest_id")
1752 return QObject::tr("Contest Id");
1753 else if (_column == "country")
1754 return QObject::tr("Country");
1755 else if (_column == "credit_submitted")
1756 return QObject::tr("Credit Submitted");
1757 else if (_column == "credit_granted")
1758 return QObject::tr("Credit granted");
1759 else if (_column == "dark_dok")
1760 return QObject::tr("Dark Dok", "Do not translate if unsure, common hamradio term.");
1761 else if (_column == "distance")
1762 return QObject::tr("Distance");
1763 else if (_column == "email")
1764 return QObject::tr("Email");
1765 else if (_column == "eq_call")
1766 return QObject::tr("EQ_Call");
1767 else if (_column == "eqsl_qslrdate")
1768 return QObject::tr("eQSL RDate");
1769 else if (_column == "eqsl_qslsdate")
1770 return QObject::tr("eQSL SDate");
1771 else if (_column == "eqsl_qsl_rcvd")
1772 return QObject::tr("eQSL Rcvd");
1773 else if (_column == "eqsl_qsl_sent")
1774 return QObject::tr("eQSL Sent");
1775 else if (_column == "fists")
1776 return QObject::tr("Fists", "Do not translate if unsure, common hamradio term.");
1777 else if (_column == "fists_cc")
1778 return QObject::tr("Fists CC", "Do not translate if unsure, common hamradio term.");
1779 else if (_column == "force_init")
1780 return QObject::tr("Force Init");
1781 else if (_column == "freq")
1782 return QObject::tr("Freq");
1783 else if (_column == "freq_rx")
1784 return QObject::tr("Freq RX");
1785 else if (_column == "gridsquare")
1786 return QObject::tr("Gridsquare");
1787 else if (_column == "guest_op")
1788 return QObject::tr("Guest OP");
1789 else if (_column == "hrdlog_qso_upload_date")
1790 return QObject::tr("HRDLog SDate");
1791 else if (_column == "hrdlog_qso_upload_status")
1792 return QObject::tr("HRDLog status");
1793 else if (_column == "iota")
1794 return QObject::tr("IOTA");
1795 else if (_column == "iota_island_id")
1796 return QObject::tr("IOTA Island id");
1797 else if (_column == "k_index")
1798 return QObject::tr("K Index");
1799 else if (_column == "lat")
1800 return QObject::tr("Lat");
1801 else if (_column == "lon")
1802 return QObject::tr("Lon");
1803 else if (_column == "lotw_qslrdate")
1804 return QObject::tr("LoTW RDate");
1805 else if (_column == "lotw_qslsdate")
1806 return QObject::tr("LoTW SDate");
1807 else if (_column == "lotw_qsl_rcvd")
1808 return QObject::tr("LoTW Rcvd");
1809 else if (_column == "lotw_qsl_sent")
1810 return QObject::tr("LoTW Sent");
1811 else if (_column == "max_bursts")
1812 return QObject::tr("Max Bursts");
1813 else if (_column == "multiplier")
1814 return QObject::tr("Multiplier");
1815 else if (_column == "ms_shower")
1816 return QObject::tr("MS Shower");
1817 else if (_column == "my_antenna")
1818 return QObject::tr("My Antenna");
1819 else if (_column == "my_city")
1820 return QObject::tr("My City");
1821 else if (_column == "my_cnty")
1822 return QObject::tr("My Cnty");
1823 else if (_column == "my_country")
1824 return QObject::tr("My Country");
1825 else if (_column == "my_cq_zone")
1826 return QObject::tr("My CQz");
1827 else if (_column == "my_dxcc")
1828 return QObject::tr("My DXCC");
1829 else if (_column == "my_fists")
1830 return QObject::tr("My Fists", "Do not translate if unsure, common hamradio term.");
1831 else if (_column == "my_gridsquare")
1832 return QObject::tr("My Gridsquare");
1833 else if (_column == "my_iota")
1834 return QObject::tr("My IOTA");
1835 else if (_column == "my_iota_island_id")
1836 return QObject::tr("My IOTA island id");
1837 else if (_column == "my_itu_zone")
1838 return QObject::tr("My ITUz");
1839 else if (_column == "my_lat")
1840 return QObject::tr("My Lat");
1841 else if (_column == "my_lon")
1842 return QObject::tr("My Lon");
1843 else if (_column == "my_name")
1844 return QObject::tr("My Name");
1845 else if (_column == "my_postal_code")
1846 return QObject::tr("My Postal code");
1847 else if (_column == "my_rig")
1848 return QObject::tr("My Rig");
1849 else if (_column == "my_sig")
1850 return QObject::tr("My Sig");
1851 else if (_column == "my_sig_info")
1852 return QObject::tr("My Sig Info");
1853 else if (_column == "my_sota_ref")
1854 return QObject::tr("My SOTA ref");
1855 else if (_column == "my_state")
1856 return QObject::tr("My State");
1857 else if (_column == "my_street")
1858 return QObject::tr("My Street");
1859 else if (_column == "my_usaca_counties")
1860 return QObject::tr("My USACA counties");
1861 else if (_column == "my_vucc_grids")
1862 return QObject::tr("My VUCC grids");
1863 else if (_column == "name")
1864 return QObject::tr("Name");
1865 else if (_column == "notes")
1866 return QObject::tr("Notes");
1867 else if (_column == "nr_bursts")
1868 return QObject::tr("Nr bursts", "Do not translate if unsure, common hamradio term.");
1869 else if (_column == "nr_pings")
1870 return QObject::tr("Nr pings", "Do not translate if unsure, common hamradio term.");
1871 else if (_column == "operator")
1872 return QObject::tr("Operator");
1873 else if (_column == "owner_callsign")
1874 return QObject::tr("Owner Callsign");
1875 else if (_column == "pfx")
1876 return QObject::tr("Pfx");
1877 else if (_column == "points")
1878 return QObject::tr("Points");
1879 else if (_column == "precedence")
1880 return QObject::tr("Precedence");
1881 else if (_column == "prop_mode")
1882 return QObject::tr("Prop Mode");
1883 else if (_column == "public_key")
1884 return QObject::tr("Public Key");
1885 else if (_column == "qrzcom_qso_upload_date")
1886 return QObject::tr("QRZcom SDate");
1887 else if (_column == "qrzcom_qso_upload_status")
1888 return QObject::tr("QRZcom status");
1889 else if (_column == "qslmsg")
1890 return QObject::tr("QSL msg");
1891 else if (_column == "qslrdate")
1892 return QObject::tr("QSL RDate");
1893 else if (_column == "qslsdate")
1894 return QObject::tr("QSL SDate");
1895 else if (_column == "qsl_rcvd")
1896 return QObject::tr("QSL Rcvd");
1897 else if (_column == "qsl_sent")
1898 return QObject::tr("QSL Sent");
1899 else if (_column == "qsl_rcvd_via")
1900 return QObject::tr("QSL rcvd via");
1901 else if (_column == "qsl_sent_via")
1902 return QObject::tr("QSL sent via");
1903 else if (_column == "qsl_via")
1904 return QObject::tr("QSL via");
1905 else if (_column == "qso_complete")
1906 return QObject::tr("QSO complete");
1907 else if (_column == "qso_random")
1908 return QObject::tr("QSO random");
1909 else if (_column == "qth")
1910 return QObject::tr("QTH");
1911 else if (_column == "region")
1912 return QObject::tr("Region");
1913 else if (_column == "rig")
1914 return QObject::tr("Rig");
1915 else if (_column == "rx_pwr")
1916 return QObject::tr("RX Pwr");
1917 else if (_column == "sat_mode")
1918 return QObject::tr("Sat mode");
1919 else if (_column == "sat_name")
1920 return QObject::tr("Sat name");
1921 else if (_column == "sfi")
1922 return QObject::tr("SFI");
1923 else if (_column == "sig")
1924 return QObject::tr("Sig");
1925 else if (_column == "sig_info")
1926 return QObject::tr("Sig Info");
1927 else if (_column == "silent_key")
1928 return QObject::tr("Silent key", "Do not translate if unsure, common hamradio term.");
1929 else if (_column == "skcc")
1930 return QObject::tr("SKCC");
1931 else if (_column == "sota_ref")
1932 return QObject::tr("SOTA Ref");
1933 else if (_column == "srx_string")
1934 return QObject::tr("SRX String");
1935 else if (_column == "srx")
1936 return QObject::tr("SRX");
1937 else if (_column == "stx_string")
1938 return QObject::tr("STX String");
1939 else if (_column == "state")
1940 return QObject::tr("State");
1941 else if (_column == "station_callsign")
1942 return QObject::tr("Station Callsign");
1943 else if (_column == "submode")
1944 return QObject::tr("Submode");
1945 else if (_column == "swl")
1946 return QObject::tr("SWL", "Do not translate if unsure, common hamradio term.");
1947 else if (_column == "uksmg")
1948 return QObject::tr("UKSMG");
1949 else if (_column == "usaca_counties")
1950 return QObject::tr("USACA counties");
1951 else if (_column == "ve_prov")
1952 return QObject::tr("VE prov");
1953 else if (_column == "vucc_grids")
1954 return QObject::tr("VUCC grids");
1955 else if (_column == "ten_ten")
1956 return QObject::tr("Ten-Ten", "Do not translate, it is a hamradio group name.");
1957 else if (_column == "tx_pwr")
1958 return QObject::tr("TX Pwr");
1959 else if (_column == "web")
1960 return QObject::tr("Web");
1961 else if (_column == "qso_date_off")
1962 return QObject::tr("QSO Date off");
1963 else if (_column == "transmiterid")
1964 return QObject::tr("Transmitter id");
1965 else if (_column == "lognumber")
1966 return QObject::tr("Log number");
1967 else
1968 {
1969 return _column;
1970 }
1971 }
1972