diff --git a/Changelog b/Changelog index 6da4463c..47c15f2e 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,26 @@ +2024/10/05 - 0.39.0 +- [NEW] - DXC - Added Full-text search +- [NEW] - Select S in RST Edit when focused (issue #454) +- [NEW] - Alerts - Added Member Column +- [CHANGED] - HamlibDrv Rig/Rot- Added multiplatform reliable sleep +- [CHANGED] - Changed Backup policy +- [CHANGED] - Logbook page size - improved performance +- [CHANGED] - Logbook - CTRL-A (Select All) is disabled +- [CHANGED] - Awards - Bands are displayed based on the Settings (issue #452) +- [CHANGED] - WSJTX - More reliable detection of CQ stations (PR #471 @aa5sh) +- [CHANGED] - WSJTX - SOTA/POTA/WWFF/SIG are being added to the logged QSO (PR #463 @aa5sh) +- [CHANGED] - Stats - Add a confirmation dialog for displaying over 50k QSOs on the map +- [CHANGED] - New Contact - Starting QSO Timer when Rig online and WSJTX Update Callsign Status is received +- [CHANGED] - Added a postponed handling for Rig soft errors (issue #472) +- Fixed WSJT-X does not emit band change if rig is disconnected (issue #447) +- Fixed Wrong import of ADIF file of another log program (issue #455) +- Fixed WSJTX log record is stored incorrectly if it contains non-ASCII chars(issue #458) +- Fixed ADIF import does not import records with old DXCC Entities (issue #459) +- Fixed ADIF import incorrectly uses Station Profile parameters (issue #461) +- Fixed Logbook - QSO Table Column Width Does Not Stick (issue #464) +- Fixed Alerts Window displays OOB Spots (issue #469) +- Fixed Field values from past QSOs are used incorrectly in case of WSJTX QSOs (#issue 470) + 2024/08/29 - 0.38.0 - [NEW] - Logbook - Added Send DX Spot to the QSO Context Menu - [NEW] - DX Filter - Added Dedup Time/Freq difference setting (@aa5sh) diff --git a/QLog.pro b/QLog.pro index 7783673f..442b2853 100644 --- a/QLog.pro +++ b/QLog.pro @@ -10,7 +10,7 @@ greaterThan(QT_MAJOR_VERSION, 5): QT += widgets TARGET = qlog TEMPLATE = app -VERSION = 0.38.0 +VERSION = 0.39.0 DEFINES += VERSION=\\\"$$VERSION\\\" @@ -90,7 +90,6 @@ SOURCES += \ data/CWKeyProfile.cpp \ data/CWShortcutProfile.cpp \ data/Data.cpp \ - data/Dxcc.cpp \ data/MainLayoutProfile.cpp \ data/RigProfile.cpp \ data/RotProfile.cpp \ @@ -107,6 +106,7 @@ SOURCES += \ models/LogbookModel.cpp \ models/RigTypeModel.cpp \ models/RotTypeModel.cpp \ + models/SearchFilterProxyModel.cpp \ models/ShortcutEditorModel.cpp \ models/SqlListModel.cpp \ models/WsjtxTableModel.cpp \ @@ -242,6 +242,7 @@ HEADERS += \ models/LogbookModel.h \ models/RigTypeModel.h \ models/RotTypeModel.h \ + models/SearchFilterProxyModel.h \ models/ShortcutEditorModel.h \ models/SqlListModel.h \ models/WsjtxTableModel.h \ diff --git a/core/AlertEvaluator.cpp b/core/AlertEvaluator.cpp index 1298a8a6..82d9642c 100644 --- a/core/AlertEvaluator.cpp +++ b/core/AlertEvaluator.cpp @@ -6,7 +6,6 @@ #include "debug.h" #include "data/DxSpot.h" #include "data/WsjtxEntry.h" -#include "data/StationProfile.h" #include "data/SpotAlert.h" #include "data/BandPlan.h" @@ -35,7 +34,7 @@ void AlertEvaluator::dxSpot(const DxSpot & spot) QStringList matchedRules; - for ( const AlertRule *rule : qAsConst(ruleList) ) + for ( const AlertRule *rule : static_cast&>(ruleList) ) { qCDebug(runtime) << "Processing " << *rule; @@ -76,7 +75,7 @@ void AlertEvaluator::WSJTXCQSpot(const WsjtxEntry &wsjtx) QStringList matchedRules; - for ( const AlertRule *rule : qAsConst(ruleList) ) + for ( const AlertRule *rule : static_cast&>(ruleList) ) { qCDebug(runtime) << "Processing " << *rule; if ( rule->match(wsjtx) ) @@ -344,11 +343,11 @@ bool AlertRule::match(const DxSpot &spot) const && (sourceMap & SpotAlert::DXSPOT) && (dxCountry == 0 || dxCountry == spot.dxcc.dxcc) && (spot.status & dxLogStatusMap) - && (mode == "*" || mode.contains("|" + spot.modeGroupString)) - && (band == "*" || band.contains("|" + spot.band)) + && (mode == "*" || (!spot.modeGroupString.isEmpty() && mode.contains("|" + spot.modeGroupString))) + && (band == "*" || (!spot.band.isEmpty() && band.contains("|" + spot.band))) && (spotterCountry == 0 || spotterCountry == spot.dxcc_spotter.dxcc ) - && (dxContinent == "*" || dxContinent.contains("|" + spot.dxcc.cont)) - && (spotterContinent == "*" || spotterContinent.contains("|" + spot.dxcc_spotter.cont)) + && (dxContinent == "*" || (!spot.dxcc.cont.isEmpty() && dxContinent.contains("|" + spot.dxcc.cont))) + && (spotterContinent == "*" || (!spot.dxcc_spotter.cont.isEmpty() && spotterContinent.contains("|" + spot.dxcc_spotter.cont))) && (dxMember == QStringList("*") || spot.memberList2Set().intersects(dxMemberSet)) ) { diff --git a/core/ClubLog.cpp b/core/ClubLog.cpp index e353a96f..fc417a3a 100644 --- a/core/ClubLog.cpp +++ b/core/ClubLog.cpp @@ -11,7 +11,6 @@ #include "ClubLog.h" #include "debug.h" #include "core/CredentialStore.h" -#include "core/Callsign.h" #define API_KEY "21507885dece41ca049fec7fe02a813f2105aff2" #define API_LIVE_UPLOAD_URL "https://clublog.org/realtime.php" diff --git a/core/CredentialStore.cpp b/core/CredentialStore.cpp index ad2657da..2102d565 100644 --- a/core/CredentialStore.cpp +++ b/core/CredentialStore.cpp @@ -16,14 +16,6 @@ CredentialStore::CredentialStore(QObject *parent) : QObject(parent) FCT_IDENTIFICATION; } -CredentialStore* CredentialStore::instance() -{ - FCT_IDENTIFICATION; - - static CredentialStore instance; - return &instance; -} - int CredentialStore::savePassword(const QString &storage_key, const QString &user, const QString &pass) { FCT_IDENTIFICATION; diff --git a/core/CredentialStore.h b/core/CredentialStore.h index d6b57dd3..a763e955 100644 --- a/core/CredentialStore.h +++ b/core/CredentialStore.h @@ -9,7 +9,11 @@ class CredentialStore : public QObject Q_OBJECT public: explicit CredentialStore(QObject *parent = nullptr); - static CredentialStore* instance(); + static CredentialStore* instance() + { + static CredentialStore instance; + return &instance; + }; int savePassword(const QString &storage_key, const QString &user, const QString &pass); QString getPassword(const QString &storage_key, const QString &user); diff --git a/core/Fldigi.cpp b/core/Fldigi.cpp index b46245a9..48b4a432 100644 --- a/core/Fldigi.cpp +++ b/core/Fldigi.cpp @@ -7,7 +7,6 @@ #include "Fldigi.h" #include "logformat/AdiFormat.h" #include "debug.h" -#include "data/StationProfile.h" MODULE_IDENTIFICATION("qlog.core.fldigi"); diff --git a/core/KSTChat.cpp b/core/KSTChat.cpp index 21b7d747..47d41c26 100644 --- a/core/KSTChat.cpp +++ b/core/KSTChat.cpp @@ -75,7 +75,7 @@ KSTUsersInfo KSTChat::getUserInfo(const QString &username) const qCDebug(function_parameters) << username; - for ( const KSTUsersInfo &info : qAsConst(userList) ) + for ( const KSTUsersInfo &info : static_cast&>(userList) ) { if ( info.callsign == username ) return info; @@ -250,9 +250,9 @@ void KSTChat::receiveData() QRegularExpression chatCMDEndRE("([0-9]{4})Z " + userName.toUpper() + " " + QRegularExpression::escape(chatName) + " chat>(.*)"); QRegularExpressionMatch chatCMDEndMatch; - QStringList lines = joinLines(socket->readAll()); + const QStringList &lines = joinLines(socket->readAll()); - for (const QString &line : qAsConst(lines) ) + for (const QString &line : lines ) { qCDebug(runtime) << "Processing Line" << line << "CMD" << currCommand; // Skip empty lines @@ -461,7 +461,7 @@ void KSTChat::finalizeShowUsersCommand(const QStringList &buffer) userList.clear(); - for ( const QString &record : qAsConst(buffer) ) + for ( const QString &record : static_cast&>(buffer) ) { QRegularExpressionMatch match = recordRE.match(record); @@ -596,7 +596,7 @@ bool chatHighlightEvaluator::shouldHighlight(const KSTChatMsg &msg, { FCT_IDENTIFICATION; - for ( const chatHighlightRule *rule : qAsConst(ruleList) ) + for ( const chatHighlightRule *rule : static_cast&>(ruleList) ) { qCDebug(runtime) << "Processing " << rule->ruleName; if ( rule->match(roomIndex, msg) ) @@ -696,7 +696,7 @@ QByteArray chatHighlightRule::toJson() QJsonArray conditionsArray; - for ( const Condition &condition : qAsConst(conditions) ) + for ( const Condition &condition : static_cast&>(conditions) ) { QJsonObject conditionObject; @@ -733,8 +733,8 @@ void chatHighlightRule::fromJson(const QJsonDocument &ruleDefinition) enabled = ruleDefinition["enabled"].toBool(); ruleRoomIndex = ruleDefinition["roomId"].toInt(); interConditionOperand = static_cast(ruleDefinition["operand"].toInt()); - QJsonArray conditionArray = ruleDefinition["conditions"].toArray(); - for ( const QJsonValue &value : qAsConst(conditionArray) ) + const QJsonArray &conditionArray = ruleDefinition["conditions"].toArray(); + for ( const QJsonValue &value : conditionArray ) { QJsonObject obj = value.toObject(); Condition condition; @@ -779,7 +779,7 @@ bool chatHighlightRule::match(const int inRoomIndex, bool result = false; bool isFirstCondition = true; - for ( const Condition &condition : qAsConst(conditions) ) + for ( const Condition &condition : static_cast&>(conditions) ) { QString columnValue; diff --git a/core/MembershipQE.cpp b/core/MembershipQE.cpp index cc7857ec..c7adf5ac 100644 --- a/core/MembershipQE.cpp +++ b/core/MembershipQE.cpp @@ -93,14 +93,6 @@ void MembershipQE::statusQueryFinished(const QString &callsign, emit clubStatusResult(callsign, statuses); } -MembershipQE *MembershipQE::instance() -{ - FCT_IDENTIFICATION; - - static MembershipQE instance; - return &instance; -} - void MembershipQE::saveEnabledClubLists(const QStringList &enabledLists) { QSettings settings; @@ -124,7 +116,7 @@ void MembershipQE::removeClubsFromEnabledClubLists(const QList& toRemoveClub: qAsConst(toRemove)) + for ( const QPair& toRemoveClub : toRemove ) { current.removeAll(toRemoveClub.first); } @@ -492,13 +484,6 @@ ClubStatusQuery::ClubStatusQuery(QObject *parent) : ClubStatusQuery::~ClubStatusQuery() { FCT_IDENTIFICATION; - { - qCDebug(runtime) << "Closing connection to DB"; - QSqlDatabase db1 = QSqlDatabase::database(dbConnectionName); - db1.close(); - } - - QSqlDatabase::removeDatabase(dbConnectionName); } void ClubStatusQuery::getClubStatus(const QString &in_callsign, @@ -562,25 +547,25 @@ void ClubStatusQuery::getClubStatus(const QString &in_callsign, while ( ++records && query.next() ) { QString clubid = query.value(0).toString(); - QVariant band = query.value(1); - QVariant mode = query.value(2); + QString band = query.value(1).toString(); + QString mode = query.value(2).toString(); QVariant confirmed = query.value(3); - QVariant current_mode = query.value(4); + QString current_mode = query.value(4).toString(); qCDebug(runtime) << "Processing" << currentProcessedClub << clubid - << band.isNull() << band - << mode.isNull() << mode - << confirmed.isNull() << confirmed - << current_mode.isNull(); + << band.isEmpty() << band + << mode.isEmpty() << mode + << confirmed.toString().isEmpty() << confirmed + << current_mode.isEmpty(); // the select generates starting line for a new club // Changing the club if ( currentProcessedClub != clubid - && band.isNull() - && mode.isNull() - && confirmed.isNull() - && current_mode.isNull() ) + && band.isEmpty() + && mode.isEmpty() + && confirmed.toString().isEmpty() + && current_mode.isEmpty() ) { if ( !currentProcessedClub.isEmpty() ) { @@ -599,10 +584,10 @@ void ClubStatusQuery::getClubStatus(const QString &in_callsign, if ( currentProcessedClub == clubid ) { - if ( band.toString() == in_band ) + if ( band == in_band ) { bandMatched = true; - if ( mode.toString() == current_mode.toString() ) + if ( mode == current_mode ) { bandModeMatched = true; @@ -613,7 +598,7 @@ void ClubStatusQuery::getClubStatus(const QString &in_callsign, } } - if ( mode.toString() == current_mode.toString() ) + if ( mode == current_mode ) { modeMatched = true; } diff --git a/core/MembershipQE.h b/core/MembershipQE.h index 2fe25f3f..57da3b49 100644 --- a/core/MembershipQE.h +++ b/core/MembershipQE.h @@ -75,7 +75,11 @@ class MembershipQE : public QObject Q_OBJECT public: - static MembershipQE *instance(); + static MembershipQE *instance() + { + static MembershipQE instance; + return &instance; + }; static void saveEnabledClubLists(const QStringList &enabledLists); static QStringList getEnabledClubLists(); diff --git a/core/Migration.cpp b/core/Migration.cpp index d62590c1..3329c225 100644 --- a/core/Migration.cpp +++ b/core/Migration.cpp @@ -9,6 +9,7 @@ #include "LogParam.h" #include "LOVDownloader.h" #include "ClubLog.h" +#include "logformat/AdxFormat.h" MODULE_IDENTIFICATION("qlog.core.migration"); @@ -28,14 +29,17 @@ bool Migration::run() { //refreshUploadStatusTrigger(); return true; } - else if (currentVersion < latestVersion) { - qCDebug(runtime) << "Starting database migration"; - } - else { - qCritical() << "database from the future"; + else if ( currentVersion > latestVersion ) + { + qCritical() << "Database from the future" << currentVersion; return false; } + qCDebug(runtime) << "Backup before migration"; + backupDatabase(true); + + qCDebug(runtime) << "Starting database migration"; + QProgressDialog progress("Migrating the database...", nullptr, currentVersion, latestVersion); progress.show(); @@ -76,6 +80,107 @@ bool Migration::run() { return true; } +bool Migration::backupDatabase(bool force) +{ + FCT_IDENTIFICATION; + + const int backupCount = 10; + const int backupIntervalDays = 7; + const QString lastBackupParamName("last_backup"); + + QDate lastBackupDate = LogParam::getParam(lastBackupParamName).toDate(); + QDate now = QDate::currentDate(); + + qCDebug(runtime) << "The last backup date" << lastBackupDate + << "Force" << force; + + if ( !force + && lastBackupDate.isValid() + && lastBackupDate.addDays(backupIntervalDays) > now ) + { + qCDebug(runtime) << "Backup skipped"; + return true; + } + + const QDir dir(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation)); + const QString todayBackupName = "qlog_backup_" + QDateTime::currentDateTime().toString("yyyyMMdd") + ".adx"; + const QString todayBackupPath = dir.filePath(todayBackupName); + + // old backup file had a timestamp YYYYMMDDHHmmSS + // new backup file has only YYYYMMDD + // to be able to clean new and old backup files, following regexp is needed + const QRegularExpression regex("^qlog_backup_\\d{8}(\\d{6})?\\.adx$"); + + const QFileInfoList &fileList = dir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot); + QFileInfoList filteredList; + + for ( const QFileInfo &fileInfo : fileList ) + { + if ( regex.match(fileInfo.fileName()).hasMatch() ) // clazy:exclude=use-static-qregularexpression + { + filteredList.append(fileInfo); + } + } + + qCDebug(runtime) << filteredList; + + // does today backup exists ? + if ( !force ) + { + for ( const QFileInfo &fileInfo : filteredList ) + { + if ( fileInfo.fileName() == todayBackupName ) + { + qCDebug(runtime) << "Backup for today already exists: " << todayBackupName; + return true; + } + } + } + + /* Keep the minimum number of backups */ + /* If a number of backups is greater than backupCount, remove oldest files */ + if ( filteredList.size() >= backupCount ) + { + std::sort(filteredList.begin(), filteredList.end(), [](const QFileInfo &a, const QFileInfo &b) { + return a.fileName() < b.fileName(); + }); + + // remove old files + while ( filteredList.size() > backupCount ) + { + QFileInfo oldestFile = filteredList.takeFirst(); + const QString &filepath = oldestFile.absoluteFilePath(); + if ( QFile::remove(filepath) ) + qCDebug(runtime) << "Removing old backup file: " << filepath; + else + qWarning() << "Failed to remove old backup file: " << filepath; + } + } + + /* Make a backup file */ + QFile backupFile(todayBackupPath); + + if ( !backupFile.open(QFile::ReadWrite | QIODevice::Text) ) + { + qWarning() << "Cannot open backup file " << todayBackupPath << " for writing"; + return false; + } + + qCDebug(runtime) << "Exporting a Database backup to " << todayBackupPath; + + QTextStream stream(&backupFile); + AdxFormat adx(stream); + + adx.runExport(); + stream.flush(); + backupFile.close(); + + LogParam::setParam(lastBackupParamName, now); + + qCDebug(runtime) << "Database backup finished"; + return true; +} + /** * Returns the current user_version of the database. */ @@ -528,7 +633,7 @@ bool Migration::importQSLCards2DB() QString qslFolder = settings.value("paperqsl/qslfolder", QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation)).toString(); QDir dir(qslFolder); - QFileInfoList file_list = dir.entryInfoList(QStringList("????????_*_*_qsl_*.*"), + const QFileInfoList &file_list = dir.entryInfoList(QStringList("????????_*_*_qsl_*.*"), QDir::Files, QDir::Name); if ( !insert.prepare("INSERT INTO contacts_qsl_cards (contactid, source, name, data) " @@ -538,7 +643,7 @@ bool Migration::importQSLCards2DB() return false; } - for ( auto &file : qAsConst(file_list) ) + for ( auto &file : file_list ) { qCDebug(runtime) << "Processing file" << file.fileName(); QRegularExpressionMatch match = re.match(file.fileName()); @@ -774,7 +879,7 @@ bool Migration::refreshUploadStatusTrigger() QStringList clublogSupportedColumns; - for ( const QString &clublogColumn : qAsConst(ClubLog::supportedDBFields) ) + for ( const QString &clublogColumn : static_cast(ClubLog::supportedDBFields) ) clublogSupportedColumns << QString("old.%1 != new.%2").arg(clublogColumn, clublogColumn); if ( !stmt.exec(QString("CREATE TRIGGER update_contacts_upload_status " diff --git a/core/Migration.h b/core/Migration.h index 310b5676..26a49625 100644 --- a/core/Migration.h +++ b/core/Migration.h @@ -16,17 +16,15 @@ class Migration : public QObject Migration(QObject *parent = nullptr) : QObject(parent) {} bool run(); - bool functionMigration(int version); + static bool backupDatabase(bool force = false); + private: + bool functionMigration(int version); bool migrate(int toVersion); int getVersion(); bool setVersion(int version); - bool runSqlFile(QString filename); - - int tableRows(QString name); - bool updateExternalResource(); bool updateExternalResourceProgress(QProgressDialog&, LOVDownloader&, diff --git a/core/MultiselectCompleter.h b/core/MultiselectCompleter.h index 15319639..8bb0c9fe 100644 --- a/core/MultiselectCompleter.h +++ b/core/MultiselectCompleter.h @@ -1,5 +1,5 @@ -#ifndef MULTISELECTCOMPLETER_H -#define MULTISELECTCOMPLETER_H +#ifndef QLOG_CORE_MULTISELECTCOMPLETER_H +#define QLOG_CORE_MULTISELECTCOMPLETER_H #include @@ -17,4 +17,4 @@ class MultiselectCompleter : public QCompleter QStringList splitPath( const QString& path ) const; }; -#endif // MULTISELECTCOMPLETER_H +#endif // QLOG_CORE_MULTISELECTCOMPLETER_H diff --git a/core/NetworkNotification.cpp b/core/NetworkNotification.cpp index 1a6c4e36..a00c2008 100644 --- a/core/NetworkNotification.cpp +++ b/core/NetworkNotification.cpp @@ -225,9 +225,9 @@ void NetworkNotification::send(const QByteArray &data, const HostsPortString &de return; } - QList addrList = dests.getAddrList(); + const QList &addrList = dests.getAddrList(); - for ( const HostPortAddress &addr : qAsConst(addrList) ) + for ( const HostPortAddress &addr : addrList ) { QUdpSocket udpSocket; diff --git a/core/NetworkNotification.h b/core/NetworkNotification.h index 59583388..7ecc200f 100644 --- a/core/NetworkNotification.h +++ b/core/NetworkNotification.h @@ -8,7 +8,6 @@ #include "core/HostsPortString.h" #include "logformat/LogFormat.h" #include "data/DxSpot.h" -#include "Wsjtx.h" #include "data/WsjtxEntry.h" #include "data/SpotAlert.h" #include "data/WCYSpot.h" diff --git a/core/PropConditions.cpp b/core/PropConditions.cpp index b00c6d02..5b054720 100644 --- a/core/PropConditions.cpp +++ b/core/PropConditions.cpp @@ -140,8 +140,8 @@ void PropConditions::processReply(QNetworkReply* reply) double skipElement = 0.0; qCDebug(runtime) << "Aurora forecast Time:" << doc["Forecast Time"].toString(); - QJsonArray jsonArray = doc["coordinates"].toArray(); - for (const QJsonValue &value : qAsConst(jsonArray)) + const QJsonArray &jsonArray = doc["coordinates"].toArray(); + for (const QJsonValue &value : jsonArray) { QJsonArray obj = value.toArray(); if ( obj.size() == 3 ) @@ -166,8 +166,8 @@ void PropConditions::processReply(QNetworkReply* reply) { double skipElement = 0.0; - QJsonArray jsonArray = doc.array(); - for (const QJsonValue &value : qAsConst(jsonArray)) + const QJsonArray &jsonArray = doc.array(); + for (const QJsonValue &value : jsonArray) { QJsonObject obj = value.toObject(); QJsonObject station = obj["station"].toObject(); diff --git a/core/UpdatableSQLRecord.cpp b/core/UpdatableSQLRecord.cpp index 13b1514e..1638f866 100644 --- a/core/UpdatableSQLRecord.cpp +++ b/core/UpdatableSQLRecord.cpp @@ -50,8 +50,8 @@ void UpdatableSQLRecord::updateRecord(const QSqlRecord &record) if ( !internalRecord.contains(fieldName) ) internalRecord.append(record.field(i)); - else if ( internalRecord.value(i).toString().isEmpty() - && !record.value(i).toString().isEmpty() ) + else if ( !record.value(i).toString().isEmpty() + && internalRecord.value(fieldName).toString().isEmpty() ) internalRecord.setValue(fieldName, record.value(i)); } } diff --git a/core/UpdatableSQLRecord.h b/core/UpdatableSQLRecord.h index 6cb9edaa..9f9b5599 100644 --- a/core/UpdatableSQLRecord.h +++ b/core/UpdatableSQLRecord.h @@ -1,5 +1,5 @@ -#ifndef UPDATABLESQLRECORD_H -#define UPDATABLESQLRECORD_H +#ifndef QLOG_CORE_UPDATABLESQLRECORD_H +#define QLOG_CORE_UPDATABLESQLRECORD_H #include #include @@ -42,4 +42,4 @@ private slots: int interval; }; -#endif // UPDATABLESQLRECORD_H +#endif // QLOG_CORE_UPDATABLESQLRECORD_H diff --git a/core/Wsjtx.cpp b/core/Wsjtx.cpp index bf53761f..75df1af7 100644 --- a/core/Wsjtx.cpp +++ b/core/Wsjtx.cpp @@ -106,9 +106,9 @@ void Wsjtx::forwardDatagram(const QNetworkDatagram &datagram) HostsPortString forwardAddresses(getConfigForwardAddresses()); - QList addrList = forwardAddresses.getAddrList(); + const QList &addrList = forwardAddresses.getAddrList(); - for ( const HostPortAddress &addr : qAsConst(addrList) ) + for ( const HostPortAddress &addr : addrList ) { QUdpSocket udpSocket; diff --git a/core/debug.h b/core/debug.h index 463498a6..2b19fa38 100644 --- a/core/debug.h +++ b/core/debug.h @@ -11,8 +11,12 @@ Q_DECLARE_LOGGING_CATEGORY(logPlugin) static const QLoggingCategory function_parameters(m".function.parameters"); \ static const QLoggingCategory runtime(m".runtime"); \ -#define FCT_IDENTIFICATION QString logging_cat(mod_name); logging_cat.append(".function.entered"); \ - qCDebug(QLoggingCategory(logging_cat.toLatin1().constData()))<<"***" +#define FCT_IDENTIFICATION QString logging_cat(mod_name); \ + logging_cat.append(".function.entered"); \ + QByteArray logging_cat_latin1 = logging_cat.toLatin1(); \ + const char* category_name = logging_cat_latin1.isEmpty() ? "default_category" : logging_cat_latin1.constData(); \ + QLoggingCategory log_category(category_name); \ + qCDebug(log_category)<<"***" typedef enum debug_level { diff --git a/core/main.cpp b/core/main.cpp index e7bb75e3..e5f46d0a 100644 --- a/core/main.cpp +++ b/core/main.cpp @@ -21,13 +21,11 @@ #include "rotator/Rotator.h" #include "cwkey/CWKeyer.h" #include "AppGuard.h" -#include "logformat/AdxFormat.h" -#include "ui/SettingsDialog.h" -#include "data/StationProfile.h" #include "core/zonedetect.h" #include "ui/SplashScreen.h" #include "core/MembershipQE.h" #include "core/KSTChat.h" +#include "data/Data.h" MODULE_IDENTIFICATION("qlog.core.main"); @@ -105,7 +103,7 @@ static void setupTranslator(QApplication* app, translationFolders << qApp->applicationDirPath() << QStandardPaths::standardLocations(QStandardPaths::AppLocalDataLocation); - for ( const QString& folder : qAsConst(translationFolders) ) + for ( const QString& folder : static_cast(translationFolders) ) { qCDebug(runtime) << "Looking for a translation in" << folder << QString("i18n%1qlog_%2").arg(QDir::separator(), localeLang); QTranslator* translator = new QTranslator(app); @@ -221,8 +219,8 @@ static bool createSQLFunctions() SQLITE_UTF16, nullptr, [](void *, int ll, const void * l, int rl, const void * r) { - const QString &left = QString::fromUtf16((const ushort *)l, ll/2); - const QString &right = QString::fromUtf16((const ushort *)r, rl/2); + const QString &left = QString::fromUtf16(reinterpret_cast(l), ll/2); + const QString &right = QString::fromUtf16(reinterpret_cast(r), rl/2); return QString::localeAwareCompare(left, right); // controlled by LC_COLLATE }); } @@ -236,65 +234,6 @@ static bool createSQLFunctions() return true; } -static bool backupDatabase() -{ - FCT_IDENTIFICATION; - /* remove old backups */ - /* retention time is 30 days but a minimum number of backup files is 5 */ - const int retention_time = 30; - const int min_backout_count = 5; - - QDir dir(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation)); - QString path = dir.filePath("qlog_backup_" + QDateTime::currentDateTime().toString("yyyyMMddhhmmss") + ".adx"); - QString filter("qlog_backup_%1%1%1%1%1%1%1%1%1%1%1%1%1%1.adx"); - filter = filter.arg("[0123456789]"); - - QFileInfoList file_list = QDir(dir).entryInfoList(QStringList(filter), QDir::Files, QDir::Name); - - qCDebug(runtime) << file_list; - - /* Keep the minimum number of backups */ - /* If a number of backup is greater than min_backout_count then remove files older 30 days but always - protect a minimum number of backup file files */ - for (int i = 0; i < qMin(min_backout_count, file_list.size()); i++) - { - file_list.takeLast(); // remove last 5 files from sorted list by name to protect them from removing. - } - - /* remove those older than 30 days from the remaining files. */ - Q_FOREACH (auto fileInfo, file_list) - { - if (fileInfo.lastModified().date().daysTo(QDate::currentDate()) > retention_time) - { - QString filepath = fileInfo.absoluteFilePath(); - QDir deletefile; - deletefile.setPath(filepath); - deletefile.remove(filepath); - qCDebug(runtime) << "Removing file: " << filepath; - } - } - - /* make a backup file */ - QFile backup_file(path); - - if ( !backup_file.open(QFile::ReadWrite | QIODevice::Text)) - { - qWarning()<<"Cannot open backup file " << path << "for writing"; - return false; - } - - qCDebug(runtime)<<"Exporting a Database backup to " << path; - - QTextStream stream(&backup_file); - AdxFormat adx(stream); - - adx.runExport(); - stream.flush(); - backup_file.close(); - - qCDebug(runtime)<<"Database backup finished"; - return true; -} static bool migrateDatabase() { FCT_IDENTIFICATION; @@ -469,7 +408,7 @@ int main(int argc, char* argv[]) QString lang = parser.value(forceLanguage); app.setOrganizationName("hamradio"); - app.setApplicationName("QLog" + ((environment.isNull()) ? "" : environment.prepend("-"))); + app.setApplicationName("QLog" + ((environment.isEmpty()) ? "" : environment.prepend("-"))); /* If the Style parameter is not present then use a default - Fusion style */ if ( !stylePresent ) @@ -529,7 +468,7 @@ int main(int argc, char* argv[]) splash.showMessage(QObject::tr("Backuping Database"), Qt::AlignBottom|Qt::AlignCenter); /* a migration can break a database therefore a backup is call before it */ - if (!backupDatabase()) + if (!Migration::backupDatabase()) { QMessageBox::critical(nullptr, QMessageBox::tr("QLog Error"), QMessageBox::tr("Could not export a QLog database to ADIF as a backup.

Try to export your log to ADIF manually")); diff --git a/cwkey/CWKeyer.cpp b/cwkey/CWKeyer.cpp index bab41589..4fa73992 100644 --- a/cwkey/CWKeyer.cpp +++ b/cwkey/CWKeyer.cpp @@ -7,20 +7,11 @@ #include "cwkey/drivers/CWFldigiKey.h" #include "core/debug.h" #include "data/CWKeyProfile.h" -#include "rig/Rig.h" MODULE_IDENTIFICATION("qlog.cwkey.cwkeyer"); #define TIME_PERIOD 1000 -CWKeyer *CWKeyer::instance() -{ - FCT_IDENTIFICATION; - - static CWKeyer instance; - return &instance; -} - void CWKeyer::start() { FCT_IDENTIFICATION; diff --git a/cwkey/CWKeyer.h b/cwkey/CWKeyer.h index 8f484b0e..72496c22 100644 --- a/cwkey/CWKeyer.h +++ b/cwkey/CWKeyer.h @@ -11,7 +11,11 @@ class CWKeyer : public QObject Q_OBJECT public: - static CWKeyer* instance(); + static CWKeyer* instance() + { + static CWKeyer instance; + return &instance; + }; void stopTimer(); signals: diff --git a/cwkey/drivers/CWCatKey.h b/cwkey/drivers/CWCatKey.h index 32a2c936..6aa17875 100644 --- a/cwkey/drivers/CWCatKey.h +++ b/cwkey/drivers/CWCatKey.h @@ -15,7 +15,7 @@ class CWCatKey : public CWKey explicit CWCatKey(const CWKey::CWKeyModeID mode, const qint32 defaultSpeed, QObject *parent = nullptr); - ~CWCatKey(); + virtual ~CWCatKey(); virtual bool open() override; virtual bool close() override; diff --git a/cwkey/drivers/CWDaemonKey.h b/cwkey/drivers/CWDaemonKey.h index 5736e925..ab0e380c 100644 --- a/cwkey/drivers/CWDaemonKey.h +++ b/cwkey/drivers/CWDaemonKey.h @@ -15,7 +15,7 @@ class CWDaemonKey : public CWKey, const CWKey::CWKeyModeID mode, const qint32 defaultSpeed, QObject *parent = nullptr); - ~CWDaemonKey(){}; + virtual ~CWDaemonKey(){}; virtual bool open() override; virtual bool close() override; diff --git a/cwkey/drivers/CWDummyKey.cpp b/cwkey/drivers/CWDummyKey.cpp index 1cf5d1a6..389dea6e 100644 --- a/cwkey/drivers/CWDummyKey.cpp +++ b/cwkey/drivers/CWDummyKey.cpp @@ -1,6 +1,5 @@ #include "CWDummyKey.h" #include "core/debug.h" -#include "rig/Rig.h" MODULE_IDENTIFICATION("qlog.cwkey.driver.cwdummykey"); diff --git a/cwkey/drivers/CWFldigiKey.cpp b/cwkey/drivers/CWFldigiKey.cpp index 4b0f12c1..0b39fd37 100644 --- a/cwkey/drivers/CWFldigiKey.cpp +++ b/cwkey/drivers/CWFldigiKey.cpp @@ -265,7 +265,7 @@ bool CWFldigiKey::sendXMLRPCCall(const QString & methodName, { writer.writeStartElement("params"); - for( const QPair& param : qAsConst(*params) ) + for( const QPair& param : static_cast>&>(*params) ) { writer.writeStartElement("param"); writer.writeStartElement("value"); diff --git a/cwkey/drivers/CWFldigiKey.h b/cwkey/drivers/CWFldigiKey.h index 3f060cfc..24701f2f 100644 --- a/cwkey/drivers/CWFldigiKey.h +++ b/cwkey/drivers/CWFldigiKey.h @@ -14,7 +14,7 @@ class CWFldigiKey : public CWKey const CWKey::CWKeyModeID mode, const qint32 defaultSpeed, QObject *parent = nullptr); - ~CWFldigiKey(){ nam->deleteLater();}; + virtual ~CWFldigiKey(){ nam->deleteLater();}; virtual bool open() override; virtual bool close() override; diff --git a/cwkey/drivers/CWWinKey.cpp b/cwkey/drivers/CWWinKey.cpp index 399e62ad..0899bc00 100644 --- a/cwkey/drivers/CWWinKey.cpp +++ b/cwkey/drivers/CWWinKey.cpp @@ -2,7 +2,6 @@ #include "CWWinKey.h" #include "core/debug.h" -#include "rig/Rig.h" /* Based on WinKey v2 Spec: https://k1el.tripod.com/WinkeyUSBman.pdf */ diff --git a/cwkey/drivers/CWWinKey.h b/cwkey/drivers/CWWinKey.h index 51387e9c..36b0d9cb 100644 --- a/cwkey/drivers/CWWinKey.h +++ b/cwkey/drivers/CWWinKey.h @@ -15,7 +15,7 @@ class CWWinKey2 : public CWKey, const CWKey::CWKeyModeID mode, const qint32 defaultSpeed, QObject *parent = nullptr); - ~CWWinKey2(); + virtual ~CWWinKey2(); virtual bool open() override; virtual bool close() override; diff --git a/data/AntProfile.cpp b/data/AntProfile.cpp index 434419bf..2e6fda84 100644 --- a/data/AntProfile.cpp +++ b/data/AntProfile.cpp @@ -57,15 +57,6 @@ AntProfilesManager::AntProfilesManager(QObject *parent) : } } -AntProfilesManager *AntProfilesManager::instance() -{ - FCT_IDENTIFICATION; - - static AntProfilesManager instance; - return &instance; - -} - void AntProfilesManager::save() { FCT_IDENTIFICATION; @@ -88,10 +79,10 @@ void AntProfilesManager::save() if ( deleteQuery.exec() ) { - auto keys = profileNameList(); - for ( auto &key: qAsConst(keys) ) + const QStringList &keys = profileNameList(); + for ( auto &key: keys ) { - AntProfile antProfile = getProfile(key); + const AntProfile &antProfile = getProfile(key); insertQuery.bindValue(":profile_name", key); insertQuery.bindValue(":desc", antProfile.description); diff --git a/data/AntProfile.h b/data/AntProfile.h index 686cd6dd..9d3c4c9b 100644 --- a/data/AntProfile.h +++ b/data/AntProfile.h @@ -38,7 +38,11 @@ class AntProfilesManager : QObject, public ProfileManagerSQL explicit AntProfilesManager(QObject *parent = nullptr); ~AntProfilesManager() { }; - static AntProfilesManager *instance(); + static AntProfilesManager *instance() + { + static AntProfilesManager instance; + return &instance; + }; void save(); }; diff --git a/data/CWKeyProfile.cpp b/data/CWKeyProfile.cpp index 9b3f89f1..386be182 100644 --- a/data/CWKeyProfile.cpp +++ b/data/CWKeyProfile.cpp @@ -71,14 +71,6 @@ CWKeyProfilesManager::CWKeyProfilesManager(QObject *parent) : } } -CWKeyProfilesManager *CWKeyProfilesManager::instance() -{ - FCT_IDENTIFICATION; - - static CWKeyProfilesManager instance; - return &instance; -} - void CWKeyProfilesManager::save() { FCT_IDENTIFICATION; @@ -101,10 +93,10 @@ void CWKeyProfilesManager::save() if ( deleteQuery.exec() ) { - auto keys = profileNameList(); - for ( auto &key: qAsConst(keys) ) + const QStringList &keys = profileNameList(); + for ( auto &key: keys ) { - CWKeyProfile cwKeyProfile = getProfile(key); + const CWKeyProfile &cwKeyProfile = getProfile(key); insertQuery.bindValue(":profile_name", key); insertQuery.bindValue(":model", cwKeyProfile.model); diff --git a/data/CWKeyProfile.h b/data/CWKeyProfile.h index 7bc8136e..a20bd775 100644 --- a/data/CWKeyProfile.h +++ b/data/CWKeyProfile.h @@ -54,7 +54,11 @@ class CWKeyProfilesManager : QObject, public ProfileManagerSQL explicit CWKeyProfilesManager(QObject *parent = nullptr); ~CWKeyProfilesManager() { }; - static CWKeyProfilesManager* instance(); + static CWKeyProfilesManager* instance() + { + static CWKeyProfilesManager instance; + return &instance; + }; void save(); }; diff --git a/data/CWShortcutProfile.cpp b/data/CWShortcutProfile.cpp index 786e1ad9..5dfedddd 100644 --- a/data/CWShortcutProfile.cpp +++ b/data/CWShortcutProfile.cpp @@ -80,14 +80,6 @@ CWShortcutProfilesManager::CWShortcutProfilesManager(QObject *parent) : } } -CWShortcutProfilesManager *CWShortcutProfilesManager::instance() -{ - FCT_IDENTIFICATION; - - static CWShortcutProfilesManager instance; - return &instance; -} - void CWShortcutProfilesManager::save() { FCT_IDENTIFICATION; @@ -114,10 +106,10 @@ void CWShortcutProfilesManager::save() if ( deleteQuery.exec() ) { - auto keys = profileNameList(); - for ( auto &key: qAsConst(keys) ) + const QStringList &keys = profileNameList(); + for ( auto &key: keys ) { - CWShortcutProfile cwShortcutProfile = getProfile(key); + const CWShortcutProfile &cwShortcutProfile = getProfile(key); insertQuery.bindValue(":profile_name", key); for ( int i = 0; i < cwShortcutProfile.shortDescs.size(); i++ ) diff --git a/data/CWShortcutProfile.h b/data/CWShortcutProfile.h index bc939158..6842454d 100644 --- a/data/CWShortcutProfile.h +++ b/data/CWShortcutProfile.h @@ -41,7 +41,11 @@ class CWShortcutProfilesManager : QObject, public ProfileManagerSQL&>(callsign_member) ) { ret << member.getClubInfo(); } @@ -36,7 +36,7 @@ class DxSpot { QSet ret; - for ( const ClubInfo &member : qAsConst(callsign_member) ) + for ( const ClubInfo &member : static_cast&>(callsign_member) ) { ret << member.getClubInfo(); } diff --git a/data/Dxcc.cpp b/data/Dxcc.cpp deleted file mode 100644 index 78c86736..00000000 --- a/data/Dxcc.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "Dxcc.h" diff --git a/data/MainLayoutProfile.cpp b/data/MainLayoutProfile.cpp index e081e286..ed4867dd 100644 --- a/data/MainLayoutProfile.cpp +++ b/data/MainLayoutProfile.cpp @@ -74,14 +74,6 @@ MainLayoutProfilesManager::MainLayoutProfilesManager(QObject *parent) : } } -MainLayoutProfilesManager *MainLayoutProfilesManager::instance() -{ - FCT_IDENTIFICATION; - - static MainLayoutProfilesManager instance; - return &instance; -} - void MainLayoutProfilesManager::save() { FCT_IDENTIFICATION; @@ -104,10 +96,10 @@ void MainLayoutProfilesManager::save() if ( deleteQuery.exec() ) { - auto keys = profileNameList(); - for ( auto &key: qAsConst(keys) ) + const QStringList &keys = profileNameList(); + for ( auto &key: keys ) { - MainLayoutProfile layoutProfile = getProfile(key); + const MainLayoutProfile &layoutProfile = getProfile(key); insertQuery.bindValue(":profile_name", key); insertQuery.bindValue(":row_A", toDBStringList(layoutProfile.rowA)); diff --git a/data/MainLayoutProfile.h b/data/MainLayoutProfile.h index 63456b16..eb7a1351 100644 --- a/data/MainLayoutProfile.h +++ b/data/MainLayoutProfile.h @@ -43,7 +43,11 @@ class MainLayoutProfilesManager : QObject, public ProfileManagerSQL &list) const; diff --git a/data/ProfileManager.h b/data/ProfileManager.h index c2fe3172..51068f86 100644 --- a/data/ProfileManager.h +++ b/data/ProfileManager.h @@ -6,12 +6,8 @@ #include #include #include -#include "core/debug.h" #include -#define MOD_NAME "qlog.data.profilemanager" - - /* the header file contains function implementation because * https://stackoverflow.com/questions/8752837/undefined-reference-to-template-class-constructor */ @@ -98,9 +94,6 @@ class ProfileManagerSQL explicit ProfileManagerSQL(const QString &tableName) : tableName(tableName) { - QString logging_cat(MOD_NAME); logging_cat.append(".function.entered"); - qCDebug(QLoggingCategory(logging_cat.toLatin1().constData())); - QSqlQuery query(QString("SELECT profile_name FROM %1 WHERE IFNULL(selected, 0) = 1").arg(tableName)); currentProfile1 = query.first() ? query.value(0).toString() : QString(); @@ -111,9 +104,6 @@ class ProfileManagerSQL const T getCurProfile1() { - QString logging_cat(MOD_NAME); logging_cat.append(".function.entered"); - qCDebug(QLoggingCategory(logging_cat.toLatin1().constData())); - return ( ! currentProfile1.isEmpty() ) ? getProfile(currentProfile1) : T(); }; @@ -153,9 +143,6 @@ class ProfileManagerSQL void setCurProfile1(const QString &profileName) { - QString logging_cat(MOD_NAME); logging_cat.append(".function.entered"); - qCDebug(QLoggingCategory(logging_cat.toLatin1().constData())); - currProfMutex.lock(); __setCurProfile1(profileName); currProfMutex.unlock(); @@ -163,9 +150,6 @@ class ProfileManagerSQL void saveCurProfile1() { - QString logging_cat(MOD_NAME); logging_cat.append(".function.entered"); - qCDebug(QLoggingCategory(logging_cat.toLatin1().constData())); - currProfMutex.lock(); __setCurProfile1(currentProfile1); currProfMutex.unlock(); @@ -173,9 +157,6 @@ class ProfileManagerSQL const T getProfile(const QString &profileName) { - QString logging_cat(MOD_NAME); logging_cat.append(".function.entered"); - qCDebug(QLoggingCategory(logging_cat.toLatin1().constData())); - if ( profiles.contains(profileName) ) { profilesMutex.lock(); @@ -193,9 +174,6 @@ class ProfileManagerSQL void addProfile(const QString &profileName, T profile) { - QString logging_cat(MOD_NAME); logging_cat.append(".function.entered"); - qCDebug(QLoggingCategory(logging_cat.toLatin1().constData())); - profilesMutex.lock(); profiles.insert(profileName, QVariant::fromValue(profile)); profilesMutex.unlock(); @@ -203,9 +181,6 @@ class ProfileManagerSQL int removeProfile(const QString &profileName) { - QString logging_cat(MOD_NAME); logging_cat.append(".function.entered"); - qCDebug(QLoggingCategory(logging_cat.toLatin1().constData())); - currProfMutex.lock(); if ( currentProfile1 == profileName ) { @@ -222,9 +197,6 @@ class ProfileManagerSQL const QStringList profileNameList() { - QString logging_cat(MOD_NAME); logging_cat.append(".function.entered"); - qCDebug(QLoggingCategory(logging_cat.toLatin1().constData())); - profilesMutex.lock(); QStringList ret(profiles.keys()); profilesMutex.unlock(); diff --git a/data/RigProfile.cpp b/data/RigProfile.cpp index 48275e17..628b8aea 100644 --- a/data/RigProfile.cpp +++ b/data/RigProfile.cpp @@ -129,14 +129,6 @@ RigProfilesManager::RigProfilesManager(QObject *parent) : } } -RigProfilesManager *RigProfilesManager::instance() -{ - FCT_IDENTIFICATION; - - static RigProfilesManager instance; - return &instance; -} - void RigProfilesManager::save() { FCT_IDENTIFICATION; @@ -167,10 +159,10 @@ void RigProfilesManager::save() if ( deleteQuery.exec() ) { - auto keys = profileNameList(); - for ( auto &key: qAsConst(keys) ) + const QStringList &keys = profileNameList(); + for ( auto &key: keys ) { - RigProfile rigProfile = getProfile(key); + const RigProfile &rigProfile = getProfile(key); insertQuery.bindValue(":profile_name", key); insertQuery.bindValue(":model", rigProfile.model); diff --git a/data/RigProfile.h b/data/RigProfile.h index b74cbc2f..3c110734 100644 --- a/data/RigProfile.h +++ b/data/RigProfile.h @@ -86,7 +86,11 @@ class RigProfilesManager : QObject, public ProfileManagerSQL explicit RigProfilesManager(QObject *parent = nullptr); ~RigProfilesManager() { }; - static RigProfilesManager* instance(); + static RigProfilesManager* instance() + { + static RigProfilesManager instance; + return &instance; + }; void save(); }; diff --git a/data/RotProfile.cpp b/data/RotProfile.cpp index ad8f65a1..63a9d308 100644 --- a/data/RotProfile.cpp +++ b/data/RotProfile.cpp @@ -106,10 +106,10 @@ void RotProfilesManager::save() if ( deleteQuery.exec() ) { - auto keys = profileNameList(); - for ( auto &key: qAsConst(keys) ) + const QStringList &keys = profileNameList(); + for ( auto &key: keys ) { - RotProfile rigProfile = getProfile(key); + const RotProfile &rigProfile = getProfile(key); insertQuery.bindValue(":profile_name", key); insertQuery.bindValue(":model", rigProfile.model); diff --git a/data/RotUsrButtonsProfile.cpp b/data/RotUsrButtonsProfile.cpp index 7a822cca..724dffed 100644 --- a/data/RotUsrButtonsProfile.cpp +++ b/data/RotUsrButtonsProfile.cpp @@ -2,6 +2,7 @@ #include #include "RotUsrButtonsProfile.h" +#include "core/debug.h" MODULE_IDENTIFICATION("qlog.data.rotusrbuttonsprofile"); @@ -81,14 +82,6 @@ RotUsrButtonsProfilesManager::RotUsrButtonsProfilesManager(QObject *parent) : } -RotUsrButtonsProfilesManager *RotUsrButtonsProfilesManager::instance() -{ - FCT_IDENTIFICATION; - - static RotUsrButtonsProfilesManager instance; - return &instance; -} - void RotUsrButtonsProfilesManager::save() { FCT_IDENTIFICATION; @@ -113,10 +106,10 @@ void RotUsrButtonsProfilesManager::save() if ( deleteQuery.exec() ) { - auto keys = profileNameList(); - for ( auto &key: qAsConst(keys) ) + const QStringList &keys = profileNameList(); + for ( auto &key: keys ) { - RotUsrButtonsProfile rotUsrButtonProfile = getProfile(key); + const RotUsrButtonsProfile &rotUsrButtonProfile = getProfile(key); insertQuery.bindValue(":profile_name", key); for ( int i = 0; i < rotUsrButtonProfile.shortDescs.size(); i++ ) diff --git a/data/RotUsrButtonsProfile.h b/data/RotUsrButtonsProfile.h index 8ba1bdd2..8929d3bb 100644 --- a/data/RotUsrButtonsProfile.h +++ b/data/RotUsrButtonsProfile.h @@ -42,7 +42,11 @@ class RotUsrButtonsProfilesManager : QObject, public ProfileManagerSQL&>(callsign_member) ) { ret << member.getClubInfo(); } diff --git a/data/StationProfile.cpp b/data/StationProfile.cpp index 4d4d62aa..f96ac92e 100644 --- a/data/StationProfile.cpp +++ b/data/StationProfile.cpp @@ -87,14 +87,6 @@ StationProfilesManager::StationProfilesManager(QObject *parent) : } } -StationProfilesManager *StationProfilesManager::instance() -{ - FCT_IDENTIFICATION; - - static StationProfilesManager instance; - return &instance; -} - void StationProfilesManager::save() { FCT_IDENTIFICATION; diff --git a/data/StationProfile.h b/data/StationProfile.h index f7353944..2b0ffbed 100644 --- a/data/StationProfile.h +++ b/data/StationProfile.h @@ -54,7 +54,11 @@ class StationProfilesManager : QObject, public ProfileManagerSQL explicit StationProfilesManager(QObject *parent = nullptr); ~StationProfilesManager() {}; - static StationProfilesManager* instance(); + static StationProfilesManager* instance() + { + static StationProfilesManager instance; + return &instance; + }; void save(); }; diff --git a/data/WsjtxEntry.h b/data/WsjtxEntry.h index 056fbbdd..0aeacdd6 100644 --- a/data/WsjtxEntry.h +++ b/data/WsjtxEntry.h @@ -2,8 +2,8 @@ #define QLOG_DATA_WSJTXENTRY_H #include "core/Wsjtx.h" -#include "data/Data.h" #include "core/MembershipQE.h" +#include "data/Dxcc.h" struct WsjtxEntry { WsjtxDecode decode; @@ -23,7 +23,7 @@ struct WsjtxEntry { QStringList memberList2StringList() const { QStringList ret; - for ( const ClubInfo &member : qAsConst(callsign_member) ) + for ( const ClubInfo &member : static_cast&>(callsign_member) ) { ret << member.getClubInfo(); } @@ -34,7 +34,7 @@ struct WsjtxEntry { { QSet ret; - for ( const ClubInfo &member : qAsConst(callsign_member) ) + for ( const ClubInfo &member : static_cast&>(callsign_member) ) { ret << member.getClubInfo(); } diff --git a/debian/changelog b/debian/changelog index 4a71b2c8..c5dc28c2 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,28 @@ +qlog (0.39.0-1) UNRELEASED; urgency=low + * [NEW] - DXC - Added Full-text search + * [NEW] - Select S in RST Edit when focused (issue #454) + * [NEW] - Alerts - Added Member Column + * [CHANGED] - HamlibDrv Rig/Rot- Added multiplatform reliable sleep + * [CHANGED] - Changed Backup policy + * [CHANGED] - Logbook page size - improved performance + * [CHANGED] - Logbook - CTRL-A (Select All) is disabled + * [CHANGED] - Awards - Bands are displayed based on the Settings (issue #452) + * [CHANGED] - WSJTX - More reliable detection of CQ stations (PR #471 @aa5sh) + * [CHANGED] - WSJTX - SOTA/POTA/WWFF/SIG are being added to the logged QSO (PR #463 @aa5sh) + * [CHANGED] - Stats - Add a confirmation dialog for displaying over 50k QSOs on the map + * [CHANGED] - New Contact - Starting QSO Timer when Rig online and WSJTX Update Callsign Status is received + * [CHANGED] - Added a postponed handling for Rig soft errors (issue #472) + * Fixed WSJT-X does not emit band change if rig is disconnected (issue #447) + * Fixed Wrong import of ADIF file of another log program (issue #455) + * Fixed WSJTX log record is stored incorrectly if it contains non-ASCII chars(issue #458) + * Fixed ADIF import does not import records with old DXCC Entities (issue #459) + * Fixed ADIF import incorrectly uses Station Profile parameters (issue #461) + * Fixed Logbook - QSO Table Column Width Does Not Stick (issue #464) + * Fixed Alerts Window displays OOB Spots (issue #469) + * Fixed Field values from past QSOs are used incorrectly in case of WSJTX QSOs (#issue 470) + + -- foldynl Sat, 5 Oct 2024 13:33:52 +0200 + qlog (0.38.0-1) UNRELEASED; urgency=low * [NEW] - Logbook - Added Send DX Spot to the QSO Context Menu * [NEW] - DX Filter - Added Dedup Time/Freq difference setting (@aa5sh) diff --git a/i18n/qlog_cs.qm b/i18n/qlog_cs.qm index 06da5d8c..9aa25e06 100644 Binary files a/i18n/qlog_cs.qm and b/i18n/qlog_cs.qm differ diff --git a/i18n/qlog_cs.ts b/i18n/qlog_cs.ts index 054fc615..ae3980e8 100644 --- a/i18n/qlog_cs.ts +++ b/i18n/qlog_cs.ts @@ -108,44 +108,44 @@ Kontinent - - + + North America Severní Amerika - - + + Africa Afrika - - + + Antarctica Antarktida - - + + South America Jižní Amerika - + Asia Asie - + Europe Evropa - - + + Oceania Oceánie @@ -189,17 +189,17 @@ Pravidla - + Add Přidat - + Edit Upravit - + Remove Vymazat @@ -251,6 +251,11 @@ Last Comment Zpráva + + + Member + Člen + AlertWidget @@ -363,117 +368,117 @@ Zobrazit - + DXCC DXCC - + ITU ITU - + WAC WAC - + WAZ WAZ - + WAS WAS - + WPX WPX - + IOTA IOTA - + POTA Hunter POTA Lovec - + POTA Activator POTA Aktivátor - + SOTA SOTA - + WWFF WWFF - + Done Dokončit - + North America Severní Amerika - + South America Jižní Amerika - + Europe Evropa - + Africa Afrika - + Asia Asie - + Antarctica Antarktida - + Oceania Oceánie - + TOTAL Worked Celkem Pracováno - + TOTAL Confirmed Celkem Potvrzeno - + Confirmed Potvrzeno - + Worked Pracováno @@ -706,17 +711,17 @@ Zastavi&t - + Rig must be connected Rig musí být připojen - + Word Slovo - + Whole Celek @@ -814,27 +819,27 @@ CWKeyer - + No CW Keyer Profile selected Není vybrán žádný profil klíče - + Initialization Error Chyba inicializace - + Internal Error Interní Chyba - + Connection Error Chyba připojení - + Cannot open the Keyer connection Nelze přijipoji klíč @@ -842,39 +847,39 @@ CWWinKey2 - + Connected device is not WinKey Připojené zařízení není WinKey - + Connected device is not WinKey v2 or newer Připojené zařízení není WinKey v2 nebo novější - - - + + + Keyer is not connected Klíč není připojen - + Cannot send Text to Rig Nelze odeslat Text do rádia - + Cannot set Keyer Speed Nelze nastavit rychlost klíče - + Cannot stop Text Sending Nelze zastavit odesílání textu - + Communication Error Chyba připojení @@ -962,7 +967,7 @@ ClubLog - + Clublog Operation for Callsign %1 failed.<br>%2 Clublog operace pro značku %1 se nezdrařila.<br>%2 @@ -2840,151 +2845,151 @@ Data - + New Entity Nová země - + New Band Nové pásmo - + New Mode Nový druh provozu - + New Band&Mode Nové pásmo&druh - + New Slot Nový slot - + Confirmed Potvrzeno - + Worked Pracováno - + Hz Hz - + kHz kHz - + GHz GHz - + MHz MHz + + + + + + + Yes + Ano + - Yes - Ano - - - - - - - No Ne - - + + Requested Vyžádáno - + Queued Ve frontě - - + + Invalid Chybné - + Bureau Bureau - + Direct Direct - + Electronic Elektronicky - - - - - + + + + + Blank Nevyplněno - + Modified Upraveno - + Grayline - + Other Jiné - + Short Path - + Long Path - + Not Heard Neslyšeno - + Uncertain Nejistý @@ -3276,57 +3281,57 @@ DxTableModel - + Time Čas - + Callsign Značka - + Frequency Frekvence - + Mode Mode - + Spotter Spotter - + Comment Poznámka - + Continent Kontinent - + Spotter Continent Kontinent Spottera - + Band Pásmo - + Member Člen - + Country Země @@ -3334,13 +3339,13 @@ DxWidget - + Send DX Cluster Command Odeslat příkaz do DX Clusteru - + Connect Připojit @@ -3375,150 +3380,180 @@ Konzole - + + Full-text search + Fulltextové vyhledávání + + + + Search + Hledat + + + + Close Search + Zavřít vyhledávání + + + Filter... Filtr... - + Spot Last QSO Spotni poslední QSO - + Send last QSO spot Odeslat poslední QSO spot - + Show HF Stats Zobrazit KV Stats - + Show VHF Stats Zobrazit VKV Stats - + Show WCY Zobrazit WCY - + Show WWV Zobrazit WWV - + Column Visibility... Zobrazení sloupců... - + Connect on startup Připojit při spuštění - + Automatic connection after start Automatické připojení po startu aplikace - + Delete Server Vymazat server - + DXC - Delete Server DXC - Vymazat server - + Clear Password Vymazat heslo - + Keep Spots Zachovat Spoty - + Spots are not cleared when connecting to a new DX Cluster. Při přepojení serverů nejsou spoty smazány. - + Clear Vymazat - + Clear all data Vše vymazat - + + Search... + Hledat... + + + + DXC - Search + DXC- Hledat + + + Which columns should be displayed Který sloupec by měl být zobrazen - + Filter DXC Filtr DXC - + Connecting... Připojování... - + DX Cluster is temporarily unavailable DX Cluster je dočasně nedostupný - + DXC Server Error Chyba DXC Serveru - + An invalid callsign Nesprávná značka - + DX Cluster Password DX Cluster Heslo - + Security Notice Bezpečnostní upozornění - + The password can be sent via an unsecured channel Heslo může být posláno přes nezabezpečený kanál - + Server Server - + Username Uživatelské jméno - + Disconnect Odpojit + + + DX Cluster Command + Příkaz DX Clusteru + DxccTableModel @@ -3546,7 +3581,7 @@ DxccTableWidget - + Mode Druh provozu @@ -4036,23 +4071,23 @@ Neodesílat - + Uploading to HRDLOG Nahrávání do HRDLog - + Cancel Zrušit - - + + QLog Information Informace QLog - + %n QSO(s) uploaded. %n QSO bylo nahráno. @@ -4061,17 +4096,17 @@ - + QLog Warning Upozornění QLog - + Cannot upload the QSO(s): Není možné nahrát QSO: - + No QSOs found to upload. Nenalezeny žádné QSO pro nahrání. @@ -4087,87 +4122,173 @@ HamlibRigDrv - + None Žádné - + CAT CAT - + DTR DTR - + RTS RTS - - + + Initialization Error Chyba inicializace - + Cannot set PTT Type Nelze nastavit PTT Typ - + Cannot set PTT Share Nelze nastavit PTT Sdílení - + Unsupported Rig Driver Nepodporovaný ovladač - + + Rig Open Error + Spojení nelze navázat + + + Set Frequency Error Chyba v nastavení frekvence - + + Set Mode Error + Chyba nastavení režimu + + + Set PTT Error Chyba v získaní stavu PTT - + + Cannot sent Morse + This cannot be displayed + + + + + Cannot stop Morse + This cannot be displayed + + + + + Get PTT Error + This cannot be displayed + + + + Get Frequency Error Chyba v získání frekvence - + Get Mode Error Chyba v získání druhu provozu + + + Get VFO Error + Chyba v získání VFO + + + + Get PWR Error + This cannot be displayed + + + + + Get PWR (power2mw) Error + This cannot be displayed + + + + + Get RIT Function Error + This cannot be displayed + + + + + Get RIT Error + This cannot be displayed + + + + + Get XIT Function Error + This cannot be displayed + + + + + Get XIT Error + This cannot be displayed + + + + + Get KeySpeed Error + This cannot be displayed + + + + + Set KeySpeed Error + This cannot be displayed + + HamlibRotDrv - - + + Initialization Error Chyba inicializace - + Unsupported Rotator Driver Nepodporovaný ovladač - + + Rot Open Error + Spojení nelze navázat + + + Set Possition Error Chyba v nastavení pozice - + Get Possition Error Chyba v získání pozice @@ -4201,7 +4322,7 @@ - + Comment Komentář @@ -4246,69 +4367,69 @@ Přepočítat DXCC Informace (DXCC, jméno země, kontinent atd.) - + &Import &Import - + Select File Vybrat soubor - + The value is used when an input record does not contain the ADIF value Hodnota je použita v případě, když importovaný záznam má příslušné ADIF pole prázdné - - + + The values below will be used when an input record does not contain the ADIF values Hodnoty jsou použity v případě, když importovaný záznam má příslušné ADIF pole prázdné - + <p><b>In-Log QSO:</b></p><p> <p><b>QSO v logu:</b></p><p> - + <p><b>Importing:</b></p><p> <p><b>Importováno:</b></p><p> - + Duplicate QSO Duplicitní QSO - + <p>Do you want to import duplicate QSO?</p>%1 %2 <p>Přejete si importovat toto duplicitní QSO?</p>%1 %2 - + Save to File Uložit do souboru - + QLog Import Summary QLog Shrnutí Importu - + Import date Datum Importu - + Imported file Soubor importu - + Imported: %n contact(s) Importovano: %n kontaktů @@ -4317,7 +4438,7 @@ - + Warning(s): %n Upozornění: %n @@ -4326,7 +4447,7 @@ - + Error(s): %n Chyb: %n @@ -4335,17 +4456,17 @@ - + Details Detaily - + Import Result Výsledek Importu - + Save Details... Uložit detaily... @@ -4612,48 +4733,61 @@ LogFormat - + + + Cannot find My DXCC Entity Info + Nelze dohledat Mé DXCC Informace + + + A minimal set of fields not present (start_time, call, band, mode, station_callsign) Zaznam neobsahuje minimální počet polí (start_time, call, band, mode, station_callsign) - + Outside the selected Date Range Mimo vybraný rozsah datumů - - + + Duplicate Duplicitní - + Cannot find DXCC Entity Info Nelze dohledat DXCC Informace - - Cannot find own DXCC Entity Info - Nelze dohledat vlastní DXCC Informace + + DXCC Info is missing + Chybí informace o DXCC - + + + + no Station Callsign present + Značka stanice není k dispozici + + + Cannot insert to database Nelze vložit do databáze - + Imported Importováno - + Error Chyba - + Warning Upozornění @@ -5553,20 +5687,20 @@ - + Club Klub - + User Filter Uživatelský filtr - - + + Delete Vymazat @@ -5632,32 +5766,32 @@ Logbook - Odeslat DX Spot - + Delete the selected contacts? Vymazat vybraný kontakt? - + Clublog's <b>Immediately Send</b> supports only one-by-one deletion<br><br>Do you want to continue despite the fact<br>that the DELETE operation will not be sent to Clublog? Clublog <b>Okamžité odeslání</b> podporuje pouze mazání po jednom záznamu<br><br>Chcete pokračovat navzdory skutečnosti,<br>že operace DELETE nebude odeslána do Clublogu? - + Deleting QSOs Mazání QSO - + Update Aktualizace - + By updating, all selected rows will be affected.<br>The value currently edited in the column will be applied to all selected rows.<br><br>Do you want to edit them? Aktualizací budou ovlivněny všechny vybrané řádky<br>Aktuálněupravená hodnota ve sloupci se použije na všechny vybrané řádky.<br>Chcete je upravit? - + Count: %n Anzahl: %n @@ -5667,23 +5801,23 @@ - + Downloading eQSL Image Stahování eQSL obrázku - - + + Cancel Zrušit - + QLog Error Chyba QLog - + eQSL Download Image failed: Stažení eQSL obrázku selhalo: @@ -6058,7 +6192,7 @@ Nesmí být prázdné - + Unsaved Neuloženo @@ -6396,7 +6530,7 @@ Zobrazit upozornění - + About O aplikaci @@ -6406,73 +6540,73 @@ Wsjtx - + Not enabled for non-Fusion style Není povoleno pro jiný styl než Fusion - + Press to tune the alert Stiskni pro naladění alertu - + Clublog Immediately Upload Error Chyba Okamžitého nahrávání do Clublog - - + + <b>Error Detail:</b> <b>Detail chyby:</b> - + Classic Klasické - - - - - + + + + + QLog Warning Upozornění QLog - + LoTW is not configured properly.<p> Please, use <b>Settings</b> dialog to configure it.</p> LoTW není správně nastaven.<p> Prosím, použijte dialog <b>Nastavení</b> pro konfiguraci služby.</p> - + eQSL is not configured properly.<p> Please, use <b>Settings</b> dialog to configure it.</p> eQSL není správně nastaven.<p> Prosím, použijte dialog <b>Nastavení</b> pro konfiguraci služby.</p> - + Clublog is not configured properly.<p> Please, use <b>Settings</b> dialog to configure it.</p> Clublog není správně nastaven.<p> Prosím, použijte dialog <b>Nastavení</b> pro konfiguraci služby.</p> - + HRDLog is not configured properly.<p> Please, use <b>Settings</b> dialog to configure it.</p> HRDLog není správně nastaven.<p> Prosím, použijte dialog <b>Nastavení</b> pro konfiguraci služby.</p> - + QRZ.com is not configured properly.<p> Please, use <b>Settings</b> dialog to configure it.</p> QRZ.com není správně nastaven.<p> Prosím, použijte dialog <b>Nastavení</b> pro konfiguraci služby.</p> - + <h1>QLog %1</h1><p>&copy; 2019 Thomas Gatzweiler DL2IC<br/>&copy; 2021-2024 Ladislav Foldyna OK1MLG</p><p>Based on Qt %2<br/>%3<br/>%4<br/>%5</p><p>Icon by <a href='http://www.iconshock.com'>Icon Shock</a><br />Satellite images by <a href='http://www.nasa.gov'>NASA</a><br />ZoneDetect by <a href='https://github.com/BertoldVdb/ZoneDetect'>Bertold Van den Bergh</a><br />TimeZone Database by <a href='https://github.com/evansiroky/timezone-boundary-builder'>Evan Siroky</a> <h1>QLog %1</h1><p>&copy; 2019 Thomas Gatzweiler DL2IC<br/>&copy; 2021-2024 Ladislav Foldyna OK1MLG</p><p>Záloženo na Qt %2<br/>%3<br/>%4<br/>%5</p><p>Ikony <a href='http://www.iconshock.com'>Icon Shock</a><br />Satelitní snímky <a href='http://www.nasa.gov'>NASA</a><br />ZoneDetect <a href='https://github.com/BertoldVdb/ZoneDetect'>Bertold Van den Bergh</a><br />TimeZone <a href='https://github.com/evansiroky/timezone-boundary-builder'>Evan Siroky</a> - + N/A - @@ -6539,52 +6673,52 @@ Migration - + DXCC Entities DXCC Země - + Sats Info Sat Info - + SOTA Summits SOTA Summit - + WWFF Records WWFF záznamy - + IOTA Records IOTA záznamy - + POTA Records POTA záznamy - + Membership Directory Records Klubové informace - + List of Values Seznam hodnot - + Updating Aktualizuji - + Update Failed Aktualizace selhala @@ -6592,12 +6726,12 @@ NewContactWidget - + 59 59 - + Mode Mode @@ -6622,165 +6756,165 @@ - + 80m 80m - + Date Datum - + Reset Vymazat - + Save Uložit - + RSTr RSTr - + RSTs RSTs - + Lookup the call on the web. The query URL can be changed in Settings -> Callbook Vyhledet informace o značce na webu. URL dotazu lze změnit v Nastavení -> Callbook - + Web Web - + Time On Čas od - + Info Info - + Member: Člen: - + World Wide Flora & Fauna World Wide Flora & Fauna - + QSL Send Status QSL Send Status - - + + Paper QSL - - - + + + <b>Yes</b> - an outgoing QSL card has been sent; the QSO has been uploaded to, and accepted by, the online service<br/><b>No</b> - do not send an outgoing QSL card; do not upload the QSO to the online service<br/><b>Requested</b> - the contacted station has requested a QSL card; the contacted station has requested the QSO be uploaded to the online service<br/><b>Queued</b> - an outgoing QSL card has been selected to be sent; a QSO has been selected to be uploaded to the online service<br/> <b>Odesláno</b> -QSL byl odeslán; QSO bylo nahráno a akceptováno online službou<br/><b>Neodesílat</b> -QSL nemá být odesláno; neodesílat do online služby<br/><b>Vyžádano</b> -protistanice vyžádala QSL; protistanice vyžádala opětovné nahrání do online služby<br/><b>Ve frontě</b> -QSL bylo zařazeno do fronty k vyřízení; QSO je ve frontě k nahrání do online služby<br/> - + LoTW LoTW - + eQSL eQSL - + QSL Send via QSL odeslat přes - + Blank Nevyplněno - + My &Notes Mé &poznámky - + &Details &Detaily - + D&XCC D&XCC - + M&y Station Mo&je Stanice - + Station Stanice - + the contacted station's DARC DOK (District Location Code) (ex. A01) DARC DOK (kód uzemí) (např A01) - + Duration Délka - + QSL via QSL Via - + Propagation Mode Podmínky šíření - + Rig Rig - + Power Výkon - + W W - + Antenna Anténa @@ -6790,147 +6924,147 @@ MHz - - - + + + No Neodesílat - - - + + + Yes Odesláno - - - + + + Requested Vyžádáno - - - + + + Queued Ve frontě - - - + + + Ignored Ignorovat - + Bureau Bureau - + Direct Direct - + Electronic Elektronicky - + QLog Error Chyba QLog - + Callbook login failed Selhalo přihlášení do Callbooku - + LP LP - + New Entity! Nová země! - + New Band! Nové pásmo! - + New Mode! Nový druh provozu! - + New Band & Mode! Nové pásmo & druh! - + New Slot! Nový slot! - + Worked Pracováno - + Confirmed Potvrzeno - + GE GE - + GM GM - + GA GA - + m m - + Callbook search is active Hledání v Callbooku je aktivní - + Callbook search is inactive Hledání v Callbooku není aktivní - + two or four adjacent Maidenhead grid locators, each four characters long, (ex. EN98,FM08,EM97,FM07) dva nebo čtyři sousední lokátory, každý o délce čtyř znaků (např. EN98,FM08,EM97,FM07) - + Special Activity Group - + Special Activity Group Information @@ -7109,7 +7243,7 @@ QCoreApplication - + QLog Help QLog Help @@ -7117,153 +7251,153 @@ QMessageBox - - - - - + + + + + - - - + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + QLog Warning Upozornění QLog - + Club List Update failed. Cannot remove old records Nepovedlo se aktualizovat Club List. Není možné odstranit staré záznamy - + Club List Update failed. Cannot plan new downloads Nepovedlo se aktualizovat Club List. Není možné naplánovat stažení listů - - - + + + QLog Critical Chyba QLog - + Cannot save a password for %1 to the Credential Store Do uložiště hesel nelze uložit heslo pro %1 - + Cannot get a password for %1 from the Credential Store Z uložiště hesel nelze získat heslo pro %1 - + Unexpected Club List download. Canceling next downloads Neočekávaná odpověď Club Listu. Ruším aktualizaci - + Unexpected Club List content for Neočekávaný obsah Club List pro - + Network error. Cannot download Club List for Síťová chyba. Nepovedlo se stáhnout Club List pro - - - - - + + + + + - + - - + + QLog Error Chyba QLog - + QLog is already running QLog již běží - + Could not connect to database. Nelze se připojit k databázi. - + Could not export a QLog database to ADIF as a backup.<p>Try to export your log to ADIF manually Nelze exportovat QLog databázi do ADIF jako backup.<p>Pokuste se ručně exportovat log do ADIF - + Database migration failed. Migrace databaze selhala. - + Could not connect to database (2). Nelze se připojit k databázi (2). - + DXC Server Name Error Chyba jména DXC Serveru - + DXC Server address must be in format<p><b>[username@]hostname:port</b> (ex. hamqth.com:7300)</p> Adresa DXC Serveru musí být ve formátu <p><b>[uživatel@]hostname:port</b> (např. hamqth.com:7300)</p> - + DX Cluster Password DX Cluster heslo - + Invalid Password Nesprávné heslo - + DXC Server Connection Error Chyba připojení k DXC serveru - + Your callsign is empty. Please, set your Station Profile Vaše značka není vyplněna. Prosím, nastavte Profil Stanice @@ -7319,89 +7453,89 @@ Nepovedlo se aktualizovat QSO Filtr - - - + + Please, define at least one Station Locations Profile Prosím, definujte alespoň jeden Profil Stanice - + WSJTX Multicast is enabled but the Address is not a multicast address. WSJTX Multicast je aktivní ale adresa není multicast IP adresa. - + Rig port must be a valid COM port.<br>For Windows use COMxx, for unix-like OS use a path to device Port musí být platný COM port.<br>Použijte COMxx pro Windows, pro ostatní cestu k souboru zařízení - + Rig PTT port must be a valid COM port.<br>For Windows use COMxx, for unix-like OS use a path to device PTT Port musí být platný COM port.<br>Použijte COMxx pro Windows, pro ostatní cestu k souboru zařízení - + <b>TX Range</b>: Max Frequency must not be 0. <b>Rozsah TX</b>: Koncová frekvence nesmí být 0. - + <b>TX Range</b>: Max Frequency must not be under Min Frequency. <b>Rozsah TX</b>: Koncová frekvence nesmí být menší než počáteční. - + Rotator port must be a valid COM port.<br>For Windows use COMxx, for unix-like OS use a path to device Port musí být platný COM port.<br>Použijte COMxx pro Windows, pro ostatní cestu k souboru zařízení - + CW Keyer port must be a valid COM port.<br>For Windows use COMxx, for unix-like OS use a path to device Port musí být platný COM port.<br>Použijte COMxx pro Windows, pro ostatní cestu k souboru zařízení - + Cannot change the CW Keyer Model to <b>Morse over CAT</b><br>No Morse over CAT support for Rig(s) <b>%1</b> Nelze změnit Model klíče na <b>Morse over CAT</b><br>Nasledující zařízení nepodporuji Morse over CAT support <b>%1</b> - + Cannot delete the CW Keyer Profile<br>The CW Key Profile is used by Rig(s): <b>%1</b> Nelze vymazat Profil Klíče<br>Profil je pouzívám temito zařízeními:<b>%1</b> - + Gridsquare has an invalid format Lokátor má chybný formát - + VUCC Grids have an invalid format (must be 2 or 4 Gridsquares separated by ',') VUCC lokátor má neplatný formát (musí být 2 nebo 4 lokátory oddělené ',') - + Country must not be empty Zěme nesmí být prázdná - + CQZ must not be empty CQZ nesmí být prázdné - + ITU must not be empty ITU nesmí být prázdné - + Callsign has an invalid format Značka má chybný formát - + Filename is empty Jméno souboru je zprázdné @@ -7425,17 +7559,17 @@ - + <b>Rig Error:</b> <b>Chyba Rig:</b> - + <b>Rotator Error:</b> <b>Chyba Rotátoru:</b> - + <b>CW Keyer Error:</b> <b>Chyba CW Klíče:</b> @@ -7453,149 +7587,149 @@ QObject - + Cannot connect to DXC Server <p>Reason <b>: Nelse se připojit k DXC serveru <p>Důvod <b>: - - + + Connection Refused Spojení odmítnuto - - + + Host closed the connection Server uzavřel spojení - - + + Host not found Server nenalezen - - + + Timeout Timeout - - + + Network Error Chyba sítě - - + + Internal Error Interní Chyba - + Opening Database Načítání Databáze - + Backuping Database Záloha Databáze - + Migrating Database Migrace Databáze - + Starting Application Start aplikace - + My Rig Můj Rig - + Logging Station Callsign Značka logující stanice - + My Gridsquare Můj lokátor - + My Name Mé jméno - + My City Mé město - + My IOTA Moje IOTA - + My SOTA Má SOTA - + My Special Interest Activity Má SIG - + My Spec. Interes Activity Info Mé SIG Info - + My VUCC Grids Mé VUCC lokátory - + My WWFF Můj WWFF - + My POTA Ref Má POTA - + My ITU Moje ITU - + My CQZ Moje CQZ - + My DXCC Moje DXCC - + <b>Imported</b>: %n contact(s) <b>Importován</b>: %n kontakt @@ -7604,7 +7738,7 @@ - + <b>Warning(s)</b>: %n <b>Upozornění</b>: %n @@ -7613,7 +7747,7 @@ - + <b>Error(s)</b>: %n <b>Chyb</b>: %n @@ -7688,23 +7822,23 @@ Neodesílat - + Uploading to QRZ.com Nahrávání do QRZ.com - + Cancel Zrušit - - + + QLog Information Informace QLog - + %n QSO(s) uploaded. %n QSO bylo nahráno. @@ -7713,17 +7847,17 @@ - + QLog Warning Upozornění QLog - + Cannot upload the QSO(s): Není možné nahrát QSO: - + No QSOs found to upload. Nenalezeny žádné QSO pro nahrání. @@ -8620,22 +8754,22 @@ Rig - + No Rig Profile selected Není vybrán žádný Rig profil - + Initialization Error Chyba inicializace - + Internal Error Interní Chyba - + Cannot open Rig Rig nelze připojit @@ -8668,7 +8802,7 @@ XIT: 0.00000 MHz - + PWR: %1W PWR: %1W @@ -8676,22 +8810,22 @@ Rotator - + No Rotator Profile selected Není vybrán žádný Rot profil - + Initialization Error Chyba inicializace - + Internal Error Interní Chyba - + Cannot open Rotator Rotátor nelze připojit @@ -8786,20 +8920,20 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + Add Přidat @@ -9225,20 +9359,20 @@ Flow Control - - + + None None - - + + Hardware Hardware - - + + Software Software @@ -9249,32 +9383,32 @@ Parity - - + + No No - - + + Even Even - - + + Odd Odd - - + + Space Space - - + + Mark Mark @@ -9436,7 +9570,7 @@ - + Serial Serial @@ -9604,102 +9738,102 @@ <b>Oznámení o zabezpečení:</b> QLog ukládá všechna hesla do zabezpečeného úložiště. ON4KST bohužel používá protokol, kde je toto heslo odesíláno přes nezabezpečený kanál jako prostý text.</p><p>Při výběru hesla pro tuto službu buďte opatrní, protože vaše heslo je odesíláno přes nezabezpečený kanál v podobě prostého textu.< /p> - + Raw UDP Forward UDP Forward - + <p>List of IP addresses to which QLog forwards raw UDP WSJT-X packets.</p>The IP addresses are separated by a space and have the form IP:PORT <p>Seznam IP adres, na které QLog přeposílá nezměněné UDP WSJTX pakety. </p>Adresy jsou odděleny mezerou a mají formát IP:PORT - + Join Multicast Použít Multicast - + Enable/Disable Multicast option for WSJTX Povolit/zakázat možnost Multicast pro WSJTX - + Multicast Address Multicast Adresa - + Specify Multicast Address. <br>On some Linux systems it may be necessary to enable multicast on the loop-back network interface. Zadejte Multicast adresu. <br>Na některých Linux systémech může být nutné povolit Multicast pro Loopback interface. - + TTL TTL - + Time-To-Live determines the range<br> over which a multicast packet is propagated in your intranet. Time-To-Live určuje vzdálenost<br>, do které se paket Multicastu v síti šíří. - + Notifications Notifikace - + DX Spots DX Spoty - + <p> List of IP addresses to which QLog sends UDP notification packets with DX Cluster Spots.</p>The IP addresses are separated by a space and have the form IP:PORT <p>Seznam IP adres, na které QLog přeposílá UDP notificate z DX Clusteru. </p>Adresy jsou odděleny mezerou a mají formát IP:PORT - + QSO Changes Změny QSO - + <p> List of IP addresses to which QLog sends UDP notification packets about a new/updated/deleted QSO in the log.</p>The IP addresses are separated by a space and have the form IP:PORT <p>Seznam IP adres, na které QLog přeposílá UDP notificate o novém/aktualizovaném/vymazaném QSO. </p>Adresy jsou odděleny mezerou a mají formát IP:PORT - + Wsjtx CQ Spots Wsjtx CQ Spoty - + <p> List of IP addresses to which QLog sends UDP notification packets with WSJTX CQ Spots.</p>The IP addresses are separated by a space and have the form IP:PORT <p>Seznam IP adres, na které QLog přeposílá UDP notificate s WSJTX CQ Spoty. </p>Adresy jsou odděleny mezerou a mají formát IP:PORT - + Shortcuts Zkratky - + Spot Alerts Upozornění na Spoty - + <p> List of IP addresses to which QLog sends UDP notification packets about user Spot Alerts.</p>The IP addresses are separated by a space and have the form IP:PORT <p>Seznam IP adres, na které QLog přeposílá UDP notifikace Upozornění na Spoty. </p>Adresy jsou odděleny mezerou a mají formát IP:PORT - + LogID LogID - + <p>Assigned LogID to the current log.</p>The LogID is sent in the Network Nofitication messages as a unique instance identified.<p> The ID is generated automatically and cannot be changed</> <p>LogID pro aktuální log</p>LogID se posílá ve všech UDP notifikacích jako unikátní identifikátor.<p> ID je generováno automaticky a nemůže být změněno.</> @@ -9725,8 +9859,8 @@ - - + + HamQTH HamQTH @@ -9752,22 +9886,22 @@ - - + + QRZ.com QRZ.com - + Port where QLog listens an incoming traffic from WSJT-X Port, kde QLog poslouchá příchozí zprávy z WSJT-X - - - - - + + + + + ex. 192.168.1.1:1234 192.168.2.1:1234 např. 192.168.1.1:1234 192.168.2.1:1234 @@ -9798,18 +9932,18 @@ - - + + Network Síť - + Wsjtx Wsjtx - + Port @@ -9887,161 +10021,161 @@ Pásma - + Modes Druhy provozu - + DXCC DXCC - - + + Name Jméno - + Report Report - - + + State Stav - - - + + + Disabled Vypnuto - + Press <b>Modify</b> to confirm the profile changes or <b>Cancel</b>. Stiskněte <b>Upravit</b> pro potvrzení změny profilu nebo <b>Zrušit</b>. - - - - - - - - - - + + + + + + + + + + Must not be empty Nesmí být prázdné - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + Modify Upravit - - + + Special - Omnirig Special - Omnirig - + Start (MHz) Pořátek (MHz) - + End (MHz) Konec (MHz) - + SAT Mode SAT Mode - + Dummy Dummy - + Morse Over CAT Morse Over CAT - + WinKey v2 WinKey v2 - + CWDaemon CWDaemon - + FLDigi FLDigi - + Single Paddle Single Paddle - + IAMBIC A IAMBIC A - + IAMBIC B IAMBIC B - + Ultimate Ultimate - + Select File Vybrat soubor - + members členů - + Required internet connection during application start Je vyžadováno připojení do internetu během startu aplikace @@ -10049,22 +10183,22 @@ ShortcutEditorModel - + Description Popis - + Shortcut Zkratky - + Conflict with a built-in shortcut Konflikt s vestavěnou klávesovou zkratkou - + Conflict with a user-defined shortcut Konflikt s klávesovou zkratkou @@ -10091,6 +10225,7 @@ StatisticsWidget + Statistics Statistiky @@ -10186,132 +10321,137 @@ - + Band Pásmo - + Year rok - + Month měsíc - + Day in Week den v týdnu - + Hour hodinu - + Mode druh provozu - + Continent kontinent - + Propagation Mode podmínky šíření - + Confirmed / Not Confirmed Potvrzeno / Nepotvrzeno - + Countries Země - + Big Gridsquares Velké čtverce - + Distance Vzdálenost - + QSOs QSO - + Confirmed/Worked Grids Potvrzené / Pracováno Lokátory - + ODX ODX - + Sun Ned - + Mon Pon - + Tue Út - + Wed Stř - + Thu Čtvr - + Fri Pát - + Sat Sob - + Not specified Neurčeno - + Confirmed Potvrzeno - + Not Confirmed Nepotvrzeno - + + Over 50000 QSOs. Display them? + Přes 50000 QSO. Zobrazit je? + + + All Vše @@ -10319,37 +10459,37 @@ TCIRigDrv - + Rig 0 Rig 0 - + Rig 1 Rig 1 - + Rig 2 Rig 2 - + Rig 3 Rig 3 - + Error Occured Nastala chyba - + Rig status changed Změna stavu Rigu - + Rig is not connected Rig není připojen @@ -10365,17 +10505,17 @@ ToAllTableModel - + Time Čas - + Spotter Spotter - + Message Zpráva @@ -10411,47 +10551,47 @@ WCYTableModel - + Time Čas - + K K - + expK expK - + A A - + R R - + SFI SFI - + SA SA - + GMF GMF - + Au Au @@ -10459,27 +10599,27 @@ WWVTableModel - + Time Čas - + SFI SFI - + A A - + K K - + Info Info @@ -10605,37 +10745,37 @@ WsjtxTableModel - + Callsign Značka - + Gridsquare Lokátor - + Distance Vzdálenost - + SNR SNR - + Last Activity Aktivita - + Last Message Zpráva - + Member Člen @@ -10676,32 +10816,32 @@ main - + Run with the specific namespace. Spustit ve specifickém jmeném prostoru. - + namespace namespace - + Translation file - absolute or relative path and QM file name. Soubor s překladem - absolutní nebo relativní cesta a jméno QM souboru. - + path/QM-filename path/QM-filename - + Set language. <code> example: 'en' or 'en_US'. Ignore environment setting. Nastavit jazyk. Příklad <code>: 'en' nebo 'en_US'. Ignoruje OS nastavení. - + code kód diff --git a/i18n/qlog_de.qm b/i18n/qlog_de.qm index 06691686..5a96d010 100644 Binary files a/i18n/qlog_de.qm and b/i18n/qlog_de.qm differ diff --git a/i18n/qlog_de.ts b/i18n/qlog_de.ts index 3f4eedf5..ce6ddc61 100644 --- a/i18n/qlog_de.ts +++ b/i18n/qlog_de.ts @@ -108,44 +108,44 @@ Kontinent - - + + North America Nordamerika - - + + Africa Afrika - - + + Antarctica Antarktis - - + + South America Südamerika - + Asia Asien - + Europe Europa - - + + Oceania Ozeanien @@ -189,17 +189,17 @@ Regeln - + Add Hinzufügen - + Edit Bearbeiten - + Remove Entfernen @@ -251,6 +251,11 @@ Last Comment Letzter Kommentar + + + Member + Mitglied + AlertWidget @@ -363,117 +368,117 @@ Anzeigen - + DXCC - + ITU - + WAC - + WAZ - + WAS - + WPX - + IOTA - + POTA Hunter - + POTA Activator - + SOTA SOTA - + WWFF - + Done erledigt - + North America Nordamerika - + South America Südamerika - + Europe Europa - + Africa Afrika - + Asia Asien - + Antarctica Antarktis - + Oceania Ozeanien - + TOTAL Worked Summe Gearbeitet - + TOTAL Confirmed Summe Bestätigt - + Confirmed Bestätigt - + Worked Gearbeitet @@ -706,17 +711,17 @@ Hal&t - + Rig must be connected Rig muss verbunden sein - + Word Wort - + Whole Ganze @@ -814,27 +819,27 @@ CWKeyer - + No CW Keyer Profile selected Kein CW-Keyer Profil ausgewählt - + Initialization Error Initialisierungsfehler - + Internal Error Interner Fehler - + Connection Error Verbindungsfehler - + Cannot open the Keyer connection Kann die Keyer-Verbindung nicht herstellen @@ -842,39 +847,39 @@ CWWinKey2 - + Connected device is not WinKey Angeschlossenes Gerät ist kein WinKey - + Connected device is not WinKey v2 or newer Angeschlossenes Gerät ist kein WinKey v2 oder neuer - - - + + + Keyer is not connected Kein Keyer verbunden - + Cannot send Text to Rig Kann Text nicht an Rig senden - + Cannot set Keyer Speed Kann Keyer-WPM nicht einstellen - + Cannot stop Text Sending Kann Textübertragung nicht beenden - + Communication Error Kommunikationsfehler @@ -962,7 +967,7 @@ ClubLog - + Clublog Operation for Callsign %1 failed.<br>%2 Clublog-Anfrage für Rufzeichen %1 fehlgeschlagen.<br>%2 @@ -2839,151 +2844,151 @@ Data - + New Entity Neuer Eintrag - + New Band Neues Band - + New Mode Neuer Mode - + New Band&Mode Neues Band&Mode - + New Slot Neuer Slot - + Confirmed Bestätigt - + Worked Gearbeitet - + Hz Hz - + kHz kHz - + GHz GHz - + MHz MHz + + + + + + + Yes + Ja + - Yes - Ja - - - - - - - No Nein - - + + Requested Angefordert - + Queued Wartend - - + + Invalid Ungültig - + Bureau Büro - + Direct Direkt - + Electronic Elektronisch - - - - - + + + + + Blank Leer - + Modified Geändert - + Grayline - + Other Andere - + Short Path - + Long Path - + Not Heard Nicht gehört - + Uncertain Unsicher @@ -3275,57 +3280,57 @@ DxTableModel - + Time Zeit - + Callsign Rufzeichen - + Frequency Frequenz - + Mode Betriebsart - + Spotter - + Comment Kommentar - + Continent Kontinent - + Spotter Continent Spotter Kontinent - + Band Band - + Member Mitglied - + Country Land @@ -3333,7 +3338,7 @@ DxWidget - + Send DX Cluster Command Sende DX-Cluster Kommando @@ -3363,97 +3368,122 @@ Konsole - + + Full-text search + Volltextsuche + + + + Search + Suchen + + + + Close Search + Suche schließen + + + Filter... Filter... - + Filter DXC Filter DXC - + Spot Last QSO Spot letztes QSO - + Send last QSO spot Letzten QSO-Spot senden - + Show HF Stats HF Statistik anzeigen - + Show VHF Stats VHF Statistik anzeigen - + Show WCY WCY anzeigen - + Show WWV WWV anzeigen - + Column Visibility... Spaltensichtbarkeit... - + Connect on startup Beim Start verbinden - + Automatic connection after start Automatische Verbindung nach dem Start - + Delete Server Löschen Server - + DXC - Delete Server DXC - Löschen Server - + Clear Password Passwort löschen - + Keep Spots Spots merken - + Spots are not cleared when connecting to a new DX Cluster. Spots werden nicht gelöscht, wenn eine Verbindung zu einem neuen DX-Cluster hergestellt wird. - + Clear Löschen - + Clear all data Alle Löschen - + + Search... + Suchen... + + + + DXC - Search + DXC- Suchen + + + Which columns should be displayed Welche Spalten sollen angezeigt werden @@ -3464,60 +3494,65 @@ - + Connect Verbinden - + Connecting... Verbinden... - + DX Cluster is temporarily unavailable DX-Cluster vorübergehend nicht erreichbar - + DXC Server Error DXC-Serverfehler - + An invalid callsign Ungültiges Rufzeichen - + DX Cluster Password DX Cluster Passwort - + Security Notice Sicherheitshinweis - + The password can be sent via an unsecured channel Das Passwort kann über einen ungesicherten Kanal gesendet werden - + Server Server - + Username Benutzername - + Disconnect Trennen + + + DX Cluster Command + DX-Cluster Kommando + DxccTableModel @@ -3545,7 +3580,7 @@ DxccTableWidget - + Mode Betriebsart @@ -4034,23 +4069,23 @@ "Nein" - + Uploading to HRDLOG Nach HRDLog hochladen - + Cancel Abbrechen - - + + QLog Information QLog Information - + %n QSO(s) uploaded. %n QSO(s) hochgeladen. @@ -4058,17 +4093,17 @@ - + QLog Warning QLog Warnung - + Cannot upload the QSO(s): Kann QSO(s) nicht hochladen: - + No QSOs found to upload. Keine QSOs zum Hochladen gefunden. @@ -4084,87 +4119,173 @@ HamlibRigDrv - + None - + CAT CAT - + DTR DTR - + RTS RTS - - + + Initialization Error Initialisierungsfehler - + Cannot set PTT Type PTT-Typ kann nicht eingestellt werden - + Cannot set PTT Share PTT-Share kann nicht eingestellt werden - + Unsupported Rig Driver Nicht unterstützter Rig-Treiber - + + Rig Open Error + Verbindung fehlgeschlagen + + + Set Frequency Error Fehler bei der Frequenzeinstellung - + + Set Mode Error + Fehler bei der Moduseinstellung + + + Set PTT Error Fehler beim Auslösen der PTT - + + Cannot sent Morse + This cannot be displayed + + + + + Cannot stop Morse + This cannot be displayed + + + + + Get PTT Error + This cannot be displayed + + + + Get Frequency Error Fehler bei der Frequenzabfrage - + Get Mode Error Fehler bei der Mode-Abfrage + + + Get VFO Error + Fehler beim Abrufen des VFO + + + + Get PWR Error + This cannot be displayed + + + + + Get PWR (power2mw) Error + This cannot be displayed + + + + + Get RIT Function Error + This cannot be displayed + + + + + Get RIT Error + This cannot be displayed + + + + + Get XIT Function Error + This cannot be displayed + + + + + Get XIT Error + This cannot be displayed + + + + + Get KeySpeed Error + This cannot be displayed + + + + + Set KeySpeed Error + This cannot be displayed + + HamlibRotDrv - - + + Initialization Error Initialisierungsfehler - + Unsupported Rotator Driver Nicht unterstützter Rotor-Treiber - + + Rot Open Error + Verbindung fehlgeschlagen + + + Set Possition Error Fehler beim Einstellen der Position - + Get Possition Error Fehler beim Abrufen der Position @@ -4183,7 +4304,7 @@ - + Comment Kommentar @@ -4243,69 +4364,69 @@ Aktualisierung der DXCC-Einträge - + &Import &Importieren - + Select File Datei auswählen - + The value is used when an input record does not contain the ADIF value Der Wert wird verwendet, wenn ein importierter Datensatz den ADIF-Wert nicht enthält - - + + The values below will be used when an input record does not contain the ADIF values Die folgenden Werte werden verwendet, wenn ein importierter Datensatz die ADIF-Werte nicht enthält - + <p><b>In-Log QSO:</b></p><p> <p><b>Logbuch QSO:</b></p><p> - + <p><b>Importing:</b></p><p> <p><b>Importieren:</b></p><p> - + Duplicate QSO Doppeltes QSO - + <p>Do you want to import duplicate QSO?</p>%1 %2 <p>Doppelte QSOs importieren?</p>%1 %2 - + Save to File In Datei speichern - + QLog Import Summary Zusammenfassung QLog Import - + Import date Datum importieren - + Imported file Datei importieren - + Imported: %n contact(s) Importiert: %n Kontakt(e) @@ -4313,7 +4434,7 @@ - + Warning(s): %n Warnungen: %n @@ -4321,7 +4442,7 @@ - + Error(s): %n Fehler: %n @@ -4329,17 +4450,17 @@ - + Details Details - + Import Result Ergebnis des Imports - + Save Details... Details speichern... @@ -4606,48 +4727,61 @@ LogFormat - + + + Cannot find My DXCC Entity Info + Meine DXCC-Informationen fehlen + + + A minimal set of fields not present (start_time, call, band, mode, station_callsign) Ein minimaler Satz von Datenfeldern, die nicht vorhanden sind (start_time, call, band, mode, station_callsign) - + Outside the selected Date Range Außerhalb des gewählten Datumsbereichs - - + + Duplicate Duplikate - + Cannot find DXCC Entity Info DXCC Entity Info nicht gefunden - - Cannot find own DXCC Entity Info - Eigene DXCC-Entity-Infos nicht gefunden + + DXCC Info is missing + DXCC-Informationen fehlen - + + + + no Station Callsign present + Kein Stationsrufzeichen vorhanden + + + Cannot insert to database Einfügen in die Datenbank nicht möglich - + Imported Importiert - + Error Fehler - + Warning Warnung @@ -5529,20 +5663,20 @@ - + Club - + User Filter Benutzer-Filter - - + + Delete Löschen @@ -5627,32 +5761,32 @@ Betriebsart - + Delete the selected contacts? Die ausgewählten Kontakte löschen? - + Clublog's <b>Immediately Send</b> supports only one-by-one deletion<br><br>Do you want to continue despite the fact<br>that the DELETE operation will not be sent to Clublog? Clublog <b>Sofort Upload</b> unterstützt nur das Löschen eines Datensatzes nach dem anderen.<br><br>Möchten Sie fortfahren, obwohl<br>der DELETE-Vorgang nicht an Clublog gesendet wird? - + Deleting QSOs QSOs Löschen - + Update Aktualisieren - + By updating, all selected rows will be affected.<br>The value currently edited in the column will be applied to all selected rows.<br><br>Do you want to edit them? Durch die Aktualisierung werden alle ausgewählten Zeilen beeinflusst.<br>Der aktuell bearbeitete Wert in der Spalte wird auf alle ausgewählten Zeilen angewendet.<br>Möchten Sie fortfahren? - + Count: %n Anzahl: %n @@ -5660,23 +5794,23 @@ - + Downloading eQSL Image eQSL-Bild herunterladen - - + + Cancel Abbrechen - + QLog Error QLog Fehler - + eQSL Download Image failed: eQSL-Bild download fehlgeschlagen: @@ -6050,7 +6184,7 @@ Darf nicht leer sein - + Unsaved Ungespeichert @@ -6387,7 +6521,7 @@ Alerts anzeigen - + About Über @@ -6398,73 +6532,73 @@ - + Not enabled for non-Fusion style Für keinen anderen Stil als Fusion zulässig - + Press to tune the alert Drücken zum Einstellen des Alarms - + Clublog Immediately Upload Error Clublog-Sofort-Upload-Fehler - - + + <b>Error Detail:</b> <b>Fehler-Detail:</b> - + Classic Klassisch - - - - - + + + + + QLog Warning QLog Warnung - + LoTW is not configured properly.<p> Please, use <b>Settings</b> dialog to configure it.</p> LoTW ist nicht richtig eingerichtet.<p> Bitte verwende den <b>Einstellungen</b> Dialog, um es einzurichten.</p> - + eQSL is not configured properly.<p> Please, use <b>Settings</b> dialog to configure it.</p> eQSL ist nicht richtig eingerichtet.<p> Bitte verwende den <b>Einstellungen</b> Dialog, um es einzurichten.</p> - + Clublog is not configured properly.<p> Please, use <b>Settings</b> dialog to configure it.</p> Clublog ist nicht richtig eingerichtet.<p> Bitte verwende den <b>Einstellungen</b> Dialog, um es einzurichten.</p> - + HRDLog is not configured properly.<p> Please, use <b>Settings</b> dialog to configure it.</p> HRDLog ist nicht richtig eingerichtet.<p> Bitte verwende den <b>Einstellungen</b> Dialog, um es einzurichten.</p> - + QRZ.com is not configured properly.<p> Please, use <b>Settings</b> dialog to configure it.</p> QRZ.com ist nicht richtig eingerichtet.<p> Bitte verwende den <b>Einstellungen</b> Dialog, um es einzurichten.</p> - + <h1>QLog %1</h1><p>&copy; 2019 Thomas Gatzweiler DL2IC<br/>&copy; 2021-2024 Ladislav Foldyna OK1MLG</p><p>Based on Qt %2<br/>%3<br/>%4<br/>%5</p><p>Icon by <a href='http://www.iconshock.com'>Icon Shock</a><br />Satellite images by <a href='http://www.nasa.gov'>NASA</a><br />ZoneDetect by <a href='https://github.com/BertoldVdb/ZoneDetect'>Bertold Van den Bergh</a><br />TimeZone Database by <a href='https://github.com/evansiroky/timezone-boundary-builder'>Evan Siroky</a> <h1>QLog %1</h1><p>&copy; 2019 Thomas Gatzweiler DL2IC<br/>&copy; 2021-2024 Ladislav Foldyna OK1MLG</p><p>Qt %2<br/>%3<br/>%4<br/>%5</p><p>Icon by <a href='http://www.iconshock.com'>Icon Shock</a><br />Satellite images by <a href='http://www.nasa.gov'>NASA</a><br />ZoneDetect by <a href='https://github.com/BertoldVdb/ZoneDetect'>Bertold Van den Bergh</a><br />TimeZone Database by <a href='https://github.com/evansiroky/timezone-boundary-builder'>Evan Siroky</a> - + N/A @@ -6531,52 +6665,52 @@ Migration - + DXCC Entities DXCC Einträge - + Sats Info SAT Info - + SOTA Summits SOTA Gipfel - + WWFF Records WWFF Datensätze - + IOTA Records IOTA Datensätze - + POTA Records POTA Datensätze - + Membership Directory Records Mitgliedschaftsverzeichnis - + List of Values Werteliste - + Updating Aktualisieren - + Update Failed Aktualisierung fehlgeschlagen @@ -6589,32 +6723,32 @@ Rufzeichen - + Date Datum - + Time On Startzeit - + Power Leistung - + W - + Rig - + RSTr RSTe @@ -6629,153 +6763,153 @@ - + RSTs RSTa - + 80m - + &Details &Details - + the contacted station's DARC DOK (District Location Code) (ex. A01) DARC-DOK (Ortsverbandkenner) der kontaktierten Station (z.B. A01) - + Station Station - + Info - + Lookup the call on the web. The query URL can be changed in Settings -> Callbook Suchen Sie das Rufzeichen im Internet. Die Abfrage-URL kann unter Einstellungen -> Callbook geändert werden - + Web - + Duration Dauer - + World Wide Flora & Fauna - + QSL Send Status QSL Ausgangsstatus - - + + Paper Papier - - - + + + <b>Yes</b> - an outgoing QSL card has been sent; the QSO has been uploaded to, and accepted by, the online service<br/><b>No</b> - do not send an outgoing QSL card; do not upload the QSO to the online service<br/><b>Requested</b> - the contacted station has requested a QSL card; the contacted station has requested the QSO be uploaded to the online service<br/><b>Queued</b> - an outgoing QSL card has been selected to be sent; a QSO has been selected to be uploaded to the online service<br/> <b>Ja</b> - eine ausgehende QSL-Karte wurde gesendet; das QSO wurde in den Online-Dienst hochgeladen und von diesem akzeptiert.<br/><b>Nein</b> - keine ausgehende QSL-Karte senden; das QSO nicht in den Online-Dienst hochladen.<br/><b>Angefordert</b> - die kontaktierte Station hat eine QSL-Karte angefordert; die kontaktierte Station hat angefordert, dass das QSO in den Online-Dienst hochgeladen wird.<br/><b>Wartend</b> - eine ausgehende QSL-Karte wurde zum Senden ausgewählt; ein QSO wurde zum Hochladen in den Online-Dienst ausgewählt.<br/> - + LoTW - + eQSL - + QSL Send via QSL Ausgang via - + Blank Leer - + My &Notes Eigene &Anmerkungen - + Member: Mitglied: - - - + + + No Nein - - - + + + Yes Ja - - - + + + Requested Angefordert - - - + + + Queued Wartend - + QSL via QSL via - + Propagation Mode Ausbreitungsmodus - + Bureau Büro - + Direct Direkt - + Antenna Antenne @@ -6785,22 +6919,22 @@ - + D&XCC - + M&y Station &Eigene Station - + Reset Zurücksetzen - + Save Speichern @@ -6810,119 +6944,119 @@ Frequenz - + 59 - + Mode Betriebsart - - - + + + Ignored Ignoriert - + Electronic Elektronisch - + QLog Error QLog Fehler - + Callbook login failed Callbook-Anmeldung fehlgeschlagen - + LP LP - + New Entity! Neuer Eintrag! - + New Band! Neues Band! - + New Mode! Neue Betriebsart! - + New Band & Mode! Neues Band & Betriebsart! - + New Slot! Neuer Slot! - + Worked Gearbeitet - + Confirmed Bestätigt - + GE GA - + GM GM - + GA GT - + m - + Callbook search is active Callbook-Suche ist aktiv - + Callbook search is inactive Callbook-Suche ist inaktiv - + two or four adjacent Maidenhead grid locators, each four characters long, (ex. EN98,FM08,EM97,FM07) zwei oder vier nebeneinander liegende, jeweils vier Zeichen lange Gitterfelder (z. B. EN98,FM08,EM97,FM07) - + Special Activity Group Spezielle Aktivitätsgruppe - + Special Activity Group Information @@ -7101,7 +7235,7 @@ QCoreApplication - + QLog Help QLog Hilfe @@ -7109,153 +7243,153 @@ QMessageBox - - - - - + + + + + - + - - + + QLog Error QLog Fehler - + QLog is already running QLog wird bereits ausgeführt - + Could not connect to database. Keine Verbindung zur Datenbank möglich. - + Could not export a QLog database to ADIF as a backup.<p>Try to export your log to ADIF manually Kann QLog-Datenbank nicht als Backup nach ADIF exportieren.<p>Versuchen Sie, Ihr Log manuell nach ADIF zu exportieren - + Database migration failed. Migration der Datenbank fehlgeschlagen. - + Could not connect to database (2). Keine Verbindung zur Datenbank möglich (2). - - - - - + + + + + - - - + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + QLog Warning QLog Warnung - + Club List Update failed. Cannot remove old records Aktualisierung der Clubliste fehlgeschlagen. Alte Datensätze können nicht entfernt werden - + Club List Update failed. Cannot plan new downloads Aktualisierung der Clubliste fehlgeschlagen. Kann keine neuen Downloads durchführen - - - + + + QLog Critical QLog kritischer Fehler - + Cannot save a password for %1 to the Credential Store Das Passwort für %1 kann nicht im Passwort Speicher gespeichert werden - + Cannot get a password for %1 from the Credential Store Es kann kein Passwort für %1 aus dem Passwort Speicher abgerufen werden - + Unexpected Club List download. Canceling next downloads Unerwartete Clubliste herunterladen. Nächste Downloads beenden - + Unexpected Club List content for Unerwarteter Inhalt der Clubliste für - + Network error. Cannot download Club List for Netzwerkfehler. Clubliste kann nicht heruntergeladen werden für - + DXC Server Name Error DXC Server Namensfehler - + DXC Server address must be in format<p><b>[username@]hostname:port</b> (ex. hamqth.com:7300)</p> Format der DXC-Server-Adresse <p><b>[benutzername@]hostname:Port</b> (z. B. hamqth.com:7300)</p> - + DX Cluster Password DX Cluster Passwort - + Invalid Password Falsches Passwort - + DXC Server Connection Error DXC Server Verbindungsfehler - + Your callsign is empty. Please, set your Station Profile Ihr Rufzeichen ist nicht angegeben. Bitte richten Sie Ihr Stationsprofil ein @@ -7311,89 +7445,89 @@ Kann QSO-Filterbedingungen nicht passend zum Typ aktualisieren - - - + + Please, define at least one Station Locations Profile Bitte definieren Sie mindestens ein Stationsstandortprofil - + WSJTX Multicast is enabled but the Address is not a multicast address. WSJTX Multicast ist aktiviert, aber die Adresse ist keine Multicast-Adresse. - + Rig port must be a valid COM port.<br>For Windows use COMxx, for unix-like OS use a path to device Rig port muss ein gültiger COM-Port sein.<br>Für Windows verwende COMxx, für Unix-ähnliche Betriebssysteme verwende einen Pfad zum Gerät - + Rig PTT port must be a valid COM port.<br>For Windows use COMxx, for unix-like OS use a path to device Rig-PTT-Port muss ein gültiger COM-Port sein. Für Windows verwenden Sie COMxx, für Unix-ähnliche Betriebssysteme verwenden Sie einen Pfad zum Gerät - + <b>TX Range</b>: Max Frequency must not be 0. <b>TX-Bereich</b>: Max Frequenz darf nicht 0 sein. - + <b>TX Range</b>: Max Frequency must not be under Min Frequency. <b>TX-Bereich</b>: Die Maximalfrequenz darf nicht niedriger als die Minimalfrequenz sein. - + Rotator port must be a valid COM port.<br>For Windows use COMxx, for unix-like OS use a path to device Rotor-Port muss ein gültiger COM-Port sein.<br>Für Windows verwenden Sie COMxx, für Unix-ähnliche Betriebssysteme verwenden Sie einen Pfad zum Gerät - + CW Keyer port must be a valid COM port.<br>For Windows use COMxx, for unix-like OS use a path to device CW Keyer Port muss ein gültiger COM-Port sein.<br>Für Windows verwenden Sie COMxx, für unix-ähnliche Betriebssysteme verwenden Sie einen Pfad zum Gerät - + Cannot change the CW Keyer Model to <b>Morse over CAT</b><br>No Morse over CAT support for Rig(s) <b>%1</b> Kann das CW-Keyer Modell nicht zu <b>CW-über-CAT</b> ändern.<br>Keine CW-über-CAT Unterstützung für Rig(s) <b>%1</b> - + Cannot delete the CW Keyer Profile<br>The CW Key Profile is used by Rig(s): <b>%1</b> Kann das CW-Keyer Profil nicht löschen.<br>Das Profil wird verwendet von Rig(s): <b>%1</b> - + Gridsquare has an invalid format Gitterfeld hat ein falsches Format - + VUCC Grids have an invalid format (must be 2 or 4 Gridsquares separated by ',') VUCC Gitterfeld hat ein falsches Format (es müssen 2 oder 4 Gitterfelder sein, getrennt durch ',') - + Country must not be empty Das Land darf nicht leer sein - + CQZ must not be empty CQZ darf nicht leer sein - + ITU must not be empty ITU darf nicht leer sein - + Callsign has an invalid format Rufzeichen hat ein falsches Format - + Filename is empty Dateiname ist leer @@ -7416,17 +7550,17 @@ - + <b>Rig Error:</b> <b>Rig Fehler:</b> - + <b>Rotator Error:</b> <b>Rotor Fehler:</b> - + <b>CW Keyer Error:</b> <b>CW-Keyer Fehler:</b> @@ -7444,149 +7578,149 @@ QObject - + Cannot connect to DXC Server <p>Reason <b>: Kann keine Verbindung zum DXC Server herstellen <p>Ursache <b>: - - + + Connection Refused Verbindung abgelehnt - - + + Host closed the connection Der Host hat die Verbindung beendet - - + + Host not found Host nicht gefunden - - + + Timeout Zeitüberschreitung - - + + Network Error Netzwerkfehler - - + + Internal Error Interner Fehler - + Opening Database Datenbank öffnen - + Backuping Database Datenbank sichern - + Migrating Database Datenbank migrieren - + Starting Application Anwendung starten - + My Rig Eigener Rig - + Logging Station Callsign Logging-Station Rufzeichen - + My Gridsquare Eigenes Gitterfeld - + My Name Eigener Name - + My City Eigene Stadt - + My IOTA Eigene IOTA Nummer - + My SOTA Eigene SOTA Nummer - + My Special Interest Activity Eigene spezielle Interessenaktivität - + My Spec. Interes Activity Info Eigene spezielle Interessenaktivität Info - + My VUCC Grids Eigenes VUCC Gitterfeld - + My WWFF Eigener WWFF - + My POTA Ref Eigene POTA Ref - + My ITU Eigene ITU Zone - + My CQZ Eigene CQZ - + My DXCC Eigenes DXCC Land - + <b>Imported</b>: %n contact(s) <b>Importiert</b>: %n Kontakt(e) @@ -7594,7 +7728,7 @@ - + <b>Warning(s)</b>: %n <b>Warnungen</b>: %n @@ -7602,7 +7736,7 @@ - + <b>Error(s)</b>: %n <b>Fehler</b>: %n @@ -7676,23 +7810,23 @@ "Nein" - + Uploading to QRZ.com Nach QRZ.com hochladen - + Cancel Abbrechen - - + + QLog Information QLog Information - + %n QSO(s) uploaded. %n QSO(s) hochgeladen. @@ -7700,17 +7834,17 @@ - + QLog Warning QLog Warnung - + Cannot upload the QSO(s): Kann QSO(s) nicht hochladen: - + No QSOs found to upload. Keine QSOs zum Hochladen gefunden. @@ -8607,22 +8741,22 @@ Rig - + No Rig Profile selected Kein Rig-Profil ausgewählt - + Initialization Error Initialisierungsfehler - + Internal Error Interner Fehler - + Cannot open Rig Kann Rig nicht öffnen @@ -8655,7 +8789,7 @@ - + PWR: %1W @@ -8663,22 +8797,22 @@ Rotator - + No Rotator Profile selected Kein Rotor-Profil ausgewählt - + Initialization Error Initialisierungsfehler - + Internal Error Interner Fehler - + Cannot open Rotator Kann Rotor nicht öffnen @@ -8768,20 +8902,20 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + Add Hinzufügen @@ -9054,20 +9188,20 @@ - - + + None - - + + Hardware - - + + Software @@ -9078,32 +9212,32 @@ - - + + No - - + + Even - - + + Odd - - + + Space - - + + Mark @@ -9312,8 +9446,8 @@ - - + + QRZ.com @@ -9328,12 +9462,12 @@ Verwendung einer internen TQSL - + Port where QLog listens an incoming traffic from WSJT-X Port, an dem QLog auf eingehenden Datenverkehr von WSJT-X wartet - + Raw UDP Forward UDP Rohdaten-Weiterleitung @@ -9427,7 +9561,7 @@ - + Serial Serial @@ -9621,106 +9755,106 @@ <b>Sicherheitshinweis:</b> QLog speichert alle Passwörter im Secure Storage. Leider verwendet ON4KST ein Protokoll, bei dem dieses Passwort über einen ungesicherten Kanal im Klartext gesendet wird.</p><p>Bitte seien Sie vorsichtig, wenn Sie Ihr Passwort für diesen Dienst wählen, da Ihr Passwort über einen ungesicherten Kanal im Klartext gesendet wird.</p> - + <p>List of IP addresses to which QLog forwards raw UDP WSJT-X packets.</p>The IP addresses are separated by a space and have the form IP:PORT <p>Liste der IP-Adressen, an die QLog unbearbeitete UDP WSJT-X-Pakete weiterleitet.</p>Die IP-Adressen werden durch ein Leerzeichen getrennt und haben die Form IP:PORT - + Join Multicast Multicast verbinden - + Enable/Disable Multicast option for WSJTX Aktivieren/Deaktivieren der Multicast-Option für WSJTX - + Multicast Address Multicast Adresse - + Specify Multicast Address. <br>On some Linux systems it may be necessary to enable multicast on the loop-back network interface. Geben Sie die Multicast-Adresse an. <br>Auf einigen Linux-Systemen kann es erforderlich sein, Multicast auf der Loopback-Netzwerkschnittstelle zu aktivieren. - + TTL - + Time-To-Live determines the range<br> over which a multicast packet is propagated in your intranet. Time-To-Live bestimmt den Bereich<br>, über den ein Multicast-Paket in Ihrem Intranet verbreitet wird. - + Notifications Benachrichtigungen - + DX Spots - + <p> List of IP addresses to which QLog sends UDP notification packets with DX Cluster Spots.</p>The IP addresses are separated by a space and have the form IP:PORT <p>Liste der IP-Adressen, an die QLog UDP-Notification-Pakete mit DX Cluster Spots sendet.</p>Die IP-Adressen sind durch ein Leerzeichen getrennt und haben das Format IP:PORT - + QSO Changes QSO Änderungen - + <p> List of IP addresses to which QLog sends UDP notification packets about a new/updated/deleted QSO in the log.</p>The IP addresses are separated by a space and have the form IP:PORT <p>Liste der IP-Adressen, an die QLog UDP-Benachrichtigungspakete über ein neues/aktualisiertes/gelöschtes QSO im Log sendet.</p>Die IP-Adressen sind durch ein Leerzeichen getrennt und haben das Format IP:PORT - + Wsjtx CQ Spots - + <p> List of IP addresses to which QLog sends UDP notification packets with WSJTX CQ Spots.</p>The IP addresses are separated by a space and have the form IP:PORT <p>Liste der IP-Adressen, an die QLog UDP-Benachrichtigungspakete mit WSJTX CQ Spots sendet.</p>Die IP-Adressen sind durch ein Leerzeichen getrennt und haben das Format IP:PORT - + Shortcuts Tastenkombinationen - + Spot Alerts - + <p> List of IP addresses to which QLog sends UDP notification packets about user Spot Alerts.</p>The IP addresses are separated by a space and have the form IP:PORT <p>Liste der IP-Adressen, an die QLog UDP-Benachrichtigungspakete über User Spot Alerts sendet.</p>Die IP-Adressen sind durch ein Leerzeichen getrennt und haben das Format IP:PORT - + LogID - + <p>Assigned LogID to the current log.</p>The LogID is sent in the Network Nofitication messages as a unique instance identified.<p> The ID is generated automatically and cannot be changed</> <p>Zugeordnete LogID für das aktuelle Protokoll.</p>Die LogID wird in den Netzwerk-Notifizierungsmeldungen als eindeutige Instanzkennung gesendet.<p>Die ID wird automatisch generiert und kann nicht geändert werden</> - - - - - + + + + + ex. 192.168.1.1:1234 192.168.2.1:1234 @@ -9751,18 +9885,18 @@ - - + + Network Netzwerk - + Wsjtx Wsjtx - + Port @@ -9792,12 +9926,12 @@ Bänder - + Modes Betriebsarten - + DXCC @@ -9859,8 +9993,8 @@ - - + + HamQTH @@ -9884,151 +10018,151 @@ Passwort - - + + Name Name - + Report Bericht - - + + State Staat - + Start (MHz) Beginn (MHz) - + End (MHz) Ende (MHz) - + SAT Mode SAT Betriebsart - - - + + + Disabled Inaktiv - + Dummy - + Morse Over CAT CW-über-CAT - + WinKey v2 - + CWDaemon - + FLDigi - + Single Paddle - + IAMBIC A - + IAMBIC B - + Ultimate - + Press <b>Modify</b> to confirm the profile changes or <b>Cancel</b>. Drücken Sie <b>Ändern</b>, um die Profiländerungen zu bestätigen oder <b>Abbrechen</b>. - - - - - - - - - - + + + + + + + + + + Must not be empty Darf nicht leer sein - + members Mitglieder - + Required internet connection during application start Erfordert Internetverbindung beim Start der Anwendung - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + Modify Ändern - - + + Special - Omnirig Special - Omnirig - + Select File Datei auswählen @@ -10036,22 +10170,22 @@ ShortcutEditorModel - + Description Beschreibung - + Shortcut Tastenkombination - + Conflict with a built-in shortcut Konflikt mit einer eingebauten Tastenkombination - + Conflict with a user-defined shortcut Konflikt mit einer benutzerdefinierten Tastenkombination @@ -10078,6 +10212,7 @@ StatisticsWidget + Statistics Statistik @@ -10173,132 +10308,137 @@ - + Band Band - + Year Jahr - + Month Monat - + Day in Week Wochentag - + Hour Stunde - + Mode Betriebsart - + Continent Kontinent - + Propagation Mode Ausbreitungsmodus - + Confirmed / Not Confirmed Bestätigt / nicht Bestätigt - + Countries Länder - + Big Gridsquares Grossfelder - + Distance Entfernung - + QSOs - + Confirmed/Worked Grids Bestätigte / gearbeitete Gitterfelder - + ODX ODX - + Sun Son - + Mon Mon - + Tue Die - + Wed Mit - + Thu Don - + Fri Fre - + Sat Sa - + Not specified Nicht angegeben - + Confirmed Bestätigt - + Not Confirmed Nicht Bestätigt - + + Over 50000 QSOs. Display them? + Über 50000 QSOs. Anzeigen? + + + All Alle @@ -10306,37 +10446,37 @@ TCIRigDrv - + Rig 0 Rig 0 - + Rig 1 Rig 1 - + Rig 2 Rig 2 - + Rig 3 Rig 3 - + Error Occured Fahler - + Rig status changed Rig-Status geändert - + Rig is not connected Rig nicht verbunden @@ -10352,17 +10492,17 @@ ToAllTableModel - + Time Zeit - + Spotter - + Message Nachricht @@ -10398,47 +10538,47 @@ WCYTableModel - + Time Zeit - + K - + expK - + A - + R - + SFI - + SA - + GMF - + Au @@ -10446,27 +10586,27 @@ WWVTableModel - + Time Zeit - + SFI - + A - + K - + Info @@ -10592,37 +10732,37 @@ WsjtxTableModel - + SNR SNR - + Callsign Rufzeichen - + Gridsquare Gitterfeld - + Distance Entfernung - + Last Activity Letzte Aktivität - + Last Message Letzte Nachricht - + Member Mitglied @@ -10663,32 +10803,32 @@ main - + Run with the specific namespace. Im spezifischen Namensraum ausführen. - + namespace Namensraum - + Translation file - absolute or relative path and QM file name. Übersetzungsdatei - Absoluter oder relativer Pfad und Name der QM-Datei. - + path/QM-filename path/QM-filename - + Set language. <code> example: 'en' or 'en_US'. Ignore environment setting. Sprache einstellen. Beispiel <code>: 'en' oder 'en_US'. Ignoriert Betriebssystemeinstellungen. - + code code diff --git a/i18n/qlog_es.qm b/i18n/qlog_es.qm index e8bd62a8..2b0ae720 100644 Binary files a/i18n/qlog_es.qm and b/i18n/qlog_es.qm differ diff --git a/i18n/qlog_es.ts b/i18n/qlog_es.ts index f69a1a06..bb9f1d84 100644 --- a/i18n/qlog_es.ts +++ b/i18n/qlog_es.ts @@ -108,44 +108,44 @@ Continente - - + + North America Norteamérica - - + + Africa África - - + + Antarctica Antártida - - + + South America Sudamérica - + Asia Asia - + Europe Europa - - + + Oceania Oceanía @@ -189,17 +189,17 @@ Reglas - + Add Agregar - + Edit Editar - + Remove Quitar @@ -251,6 +251,11 @@ Last Comment Último Comentario + + + Member + Miembro + AlertWidget @@ -375,131 +380,131 @@ Mostrar - + DXCC DXCC - + ITU ITU - + WAC WAC - + WAZ WAZ - + WAS WAS - + WPX WPX - + IOTA IOTA - + POTA Hunter Cazador de POTA Cazador de POTA - + POTA Activator Activador de POTA Activador de POTA - + SOTA Cumbres en el Aire SOTA - + WWFF Flora y Fauna Mundial WWFF - + Done Hecho Hecho - + North America América del Norte América del Norte - + South America América del Sur América del Sur - + Europe Europa Europa - + Africa África África - + Oceania Oceanía Oceanía - + Asia Asia - + Antarctica Antártida Antártida - + TOTAL Worked TOTAL Trabajado TOTAL Trabajado - + TOTAL Confirmed TOTAL Confirmado TOTAL Confirmado - + Confirmed Confirmado Confirmado - + Worked Trabajado Trabajado @@ -733,17 +738,17 @@ Borrar - + Rig must be connected La radio debe estar conectada - + Word Palabra - + Whole Todo @@ -841,27 +846,27 @@ CWKeyer - + No CW Keyer Profile selected No Hay Perfil de Manipulador Seleccionado - + Initialization Error Error al Inicializar - + Internal Error Error Interno - + Connection Error Error de Conexión - + Cannot open the Keyer connection No se puede conectar al Manipulador @@ -869,39 +874,39 @@ CWWinKey2 - + Connected device is not WinKey El dispositivo conectado no es Winkey - + Connected device is not WinKey v2 or newer El dispositivo conectado no es Winkey v2 o posterior - + Cannot send Text to Rig No se puede enviar el Texto a la Radio - - - + + + Keyer is not connected El manipulador no está conectado - + Communication Error Error de Comunicación - + Cannot set Keyer Speed No se puede establecer la velocidad del manipulador - + Cannot stop Text Sending No se puede detener el envío del Texto @@ -989,7 +994,7 @@ ClubLog - + Clublog Operation for Callsign %1 failed.<br>%2 La Operación de Clublog para el indicativo %1 ha fallado.<br>%2 @@ -2867,151 +2872,151 @@ Data - + New Entity Nueva Entidad - + New Band Nueva Banda - + New Mode Nuevo Modo - + New Band&Mode Nueva Banda y Modo - + New Slot Nuevo Slot - + Confirmed Confirmado - + Worked Trabajado - + Hz Hz - + kHz kHz - + GHz GHz - + MHz MHz + + + + + + + Yes + + - Yes - - - - - - - - No No - - + + Requested Solicitado - + Queued En Cola - - + + Invalid Inválido - + Bureau Bureau - + Direct Directa - + Electronic Electrónica - - - - - + + + + + Blank Vacío - + Modified Modificado - + Grayline Línea Gris - + Other Otro - + Short Path Paso Corto - + Long Path Paso Largo - + Not Heard No Escuchado - + Uncertain Dudoso @@ -3304,57 +3309,57 @@ DxTableModel - + Time Hora - + Callsign Indicativo - + Frequency Frecuencia - + Mode Modo - + Spotter Anunciante - + Comment Comentario - + Continent Continente - + Spotter Continent Continente del Anunciante - + Band Banda - + Member Miembro - + Country País @@ -3368,7 +3373,7 @@ - + Connect Conectar @@ -3398,155 +3403,185 @@ Consola - + + Full-text search + Búsqueda de texto completo + + + + Search + Búsqueda + + + + Close Search + Cerrar búsqueda + + + Send DX Cluster Command Enviar comando de Cluster DX - + Filter... Filtrar... - + Filter DXC Filtrar Cluster DX - + Spot Last QSO Anun. Últ. QSO - + Send last QSO spot Anunciar el último QSO realizado - + Show HF Stats Mostrar Estadísticas de HF - + Show VHF Stats Mostrar Estadísticas de VHF - + Show WCY Mostrar WCY - + Show WWV Mostrar WWV - + Column Visibility... Visibilidad de Columnas... - + Which columns should be displayed Qué columnas deben mostrarse - + Connect on startup Conectar al inicio - + Automatic connection after start Conectar automáticamente después de iniciar - + Delete Server Borrar Servidor - + DXC - Delete Server Cluster DX - Eliminar Servidor - + Clear Password Borrar Contraseña - + Keep Spots Mantener Anuncios - + Spots are not cleared when connecting to a new DX Cluster. Los anuncios no se borran al conectarse a un nuevo clúster DX. - + Clear Borrar - + Clear all data Borrar todos los datos - + + Search... + Búsqueda... + + + + DXC - Search + DXC - Búsqueda + + + Connecting... Conectando... - + DX Cluster is temporarily unavailable El Cluster DX no está disponible temporalmente - + DXC Server Error Error del Servidor del Cluster DX - + An invalid callsign Un indicativo inválido - + DX Cluster Password Contraseña del Cluster DX - + Security Notice Aviso de Seguridad - + The password can be sent via an unsecured channel - La contraseña se puede enviar a través de un canal no seguro. + La contraseña se puede enviar a través de un canal no seguro - + Server Servidor - + Username Nombre de Usuario - + Disconnect Desconectar + + + DX Cluster Command + Comando de DX Cluster + DxccTableModel @@ -3574,7 +3609,7 @@ DxccTableWidget - + Mode Modo @@ -4064,23 +4099,23 @@ "No" - + Uploading to HRDLOG Subiendo a HRDLOG - + Cancel Cancelar - - + + QLog Information Información de QLog - + %n QSO(s) uploaded. %n QSO/s subido/s. @@ -4088,17 +4123,17 @@ - + QLog Warning Alerta de QLog - + Cannot upload the QSO(s): No se puede subir el/los QSO/s: - + No QSOs found to upload. No se encontraron QSOs para subir. @@ -4114,93 +4149,179 @@ HamlibRigDrv - + None Ninguno Ninguno - + CAT Sintonización asistida por ordenador CAT - + DTR Terminal de datos listo (DTR) es una señal de control en comunicaciones serie RS-232, transmitida desde un equipo terminal de datos (DTE), como una computadora, a un equipo de comunicaciones de datos (DCE), por ejemplo un interface, para indicar que el terminal está listo para comunicaciones y el interface puede iniciar un canal de comunicaciones. DTR - + RTS Control de Señal del Puerto Serie RTS - - + + Initialization Error Error al Inicializar - + Cannot set PTT Type No se puede configurar el tipo de PTT No se puede configurar el tipo de PTT - + Cannot set PTT Share No se puede configurar la acción del PTT No se puede configurar la acción del PTT - + Unsupported Rig Driver Controlador de Radio No Soportado - + + Rig Open Error + Conexión fallida + + + Set Frequency Error Error al Establecer Frecuencia - + + Set Mode Error + Error al establecer el modo + + + Set PTT Error Error al Establecer PTT - + + Cannot sent Morse + This cannot be displayed + + + + + Cannot stop Morse + This cannot be displayed + + + + + Get PTT Error + This cannot be displayed + + + + Get Frequency Error Error al Obtener Frecuencia - + Get Mode Error Error al Obtener Modo + + + Get VFO Error + Error al obtener el VFO + + + + Get PWR Error + This cannot be displayed + + + + + Get PWR (power2mw) Error + This cannot be displayed + + + + + Get RIT Function Error + This cannot be displayed + + + + + Get RIT Error + This cannot be displayed + + + + + Get XIT Function Error + This cannot be displayed + + + + + Get XIT Error + This cannot be displayed + + + + + Get KeySpeed Error + This cannot be displayed + + + + + Set KeySpeed Error + This cannot be displayed + + HamlibRotDrv - - + + Initialization Error Error al Inicializar - + Unsupported Rotator Driver Controlador de Rotor No Soportado - + + Rot Open Error + Conexión fallida + + + Set Possition Error Error al Establecer Posición - + Get Possition Error Error al Obtener Posición @@ -4259,7 +4380,7 @@ - + The value is used when an input record does not contain the ADIF value El valor se utiliza cuando un registro de entrada no contiene el valor ADIF @@ -4280,68 +4401,68 @@ - + Comment Comentario - + &Import &Importar - + Select File Seleccionar Archivo - - + + The values below will be used when an input record does not contain the ADIF values Los valores siguientes se utilizarán cuando un registro de entrada no contenga los valores ADIF - + <p><b>In-Log QSO:</b></p><p> <p><b>QSO en Log:</b></p><p> - + <p><b>Importing:</b></p><p> <p><b>Importando:</b></p><p> - + Duplicate QSO QSO Duplicado - + <p>Do you want to import duplicate QSO?</p>%1 %2 <p>¿Quiere importar QSO duplicado?</p>%1 %2 - + Save to File Guardar al Archivo - + QLog Import Summary Resumen de Importación de QLog - + Import date Fecha de Importación - + Imported file Archivo Importado - + Imported: %n contact(s) Importado: %n contacto/s @@ -4349,7 +4470,7 @@ - + Warning(s): %n Alerta/s: %n @@ -4357,7 +4478,7 @@ - + Error(s): %n Error/s: %n @@ -4365,17 +4486,17 @@ - + Details Detalles - + Import Result Resultado de Importación - + Save Details... Guardar Detalles... @@ -4641,48 +4762,61 @@ LogFormat - + + + Cannot find My DXCC Entity Info + No se puede encontrar la información de mi entidad DXCC + + + A minimal set of fields not present (start_time, call, band, mode, station_callsign) Un conjunto mínimo de campos no presentes (hora_inicio, indicativo, banda, modo, indicativo de estación) - + Outside the selected Date Range Fuera del rango de fechas seleccionado - - + + Duplicate Duplicado - + Cannot find DXCC Entity Info No se puede encontrar la información de la entidad DXCC - - Cannot find own DXCC Entity Info - No se puede encontrar la información de la entidad DXCC propia + + DXCC Info is missing + La información DXCC falta + + + + + + no Station Callsign present + - + Cannot insert to database No se puede insertar en la base de datos - + Imported Importado - + Error Error - + Warning Alerta @@ -5582,20 +5716,20 @@ - + Club Club - + User Filter Filtro de Usuario - - + + Delete Eliminar @@ -5662,32 +5796,32 @@ Exportar los QSOs seleccionados - + Delete the selected contacts? ¿Eliminar los conactos seleccionados? - + Clublog's <b>Immediately Send</b> supports only one-by-one deletion<br><br>Do you want to continue despite the fact<br>that the DELETE operation will not be sent to Clublog? - + Deleting QSOs Borrando QSOs - + Update Actualizar - + By updating, all selected rows will be affected.<br>The value currently edited in the column will be applied to all selected rows.<br><br>Do you want to edit them? Al actualizar, todas las filas seleccionadas se verán afectadas.<br>El valor actualmente editado en la columna se aplicará a todas las filas seleccionadas.<br><br>¿Quieres editarlas? - + Count: %n QSO: %n @@ -5695,23 +5829,23 @@ - + Downloading eQSL Image Descargando Imágen de eQSL - - + + Cancel Cancelar - + QLog Error Error de QLog - + eQSL Download Image failed: La descarga de imágen de eQSL ha fallado: @@ -6086,7 +6220,7 @@ No debe estar vacío - + Unsaved Sin Guardar @@ -6429,78 +6563,78 @@ Radio - PTT Enc./Apag. - + Not enabled for non-Fusion style No habilitado para estilos que no sean Fusion - + Press to tune the alert Presione para sintonizar la alerta - + Clublog Immediately Upload Error Error de carga inmediata de Clublog - - + + <b>Error Detail:</b> <b>Detalle del Error:</b> - + Classic Clásico - - - - - + + + + + QLog Warning Alerta de QLog - + LoTW is not configured properly.<p> Please, use <b>Settings</b> dialog to configure it.</p> LoTW no está configurado apropiadamente.<p> Por favor usar <b>Ajustes</b> para configurarlo.</p> - + eQSL is not configured properly.<p> Please, use <b>Settings</b> dialog to configure it.</p> eQSL no está configurado apropiadamente.<p> Por favor usar <b>Ajustes</b> para configurarlo.</p> - + Clublog is not configured properly.<p> Please, use <b>Settings</b> dialog to configure it.</p> Clubog no está configurado apropiadamente.<p> Por favor usar <b>Ajustes</b> para configurarlo.</p> - + HRDLog is not configured properly.<p> Please, use <b>Settings</b> dialog to configure it.</p> HRDLog no está configurado apropiadamente.<p> Por favor usar <b>Ajustes</b> para configurarlo.</p> - + QRZ.com is not configured properly.<p> Please, use <b>Settings</b> dialog to configure it.</p> QRZ.com no está configurado apropiadamente.<p> Por favor usar <b>Ajustes</b> para configurarlo.</p> - + <h1>QLog %1</h1><p>&copy; 2019 Thomas Gatzweiler DL2IC<br/>&copy; 2021-2024 Ladislav Foldyna OK1MLG</p><p>Based on Qt %2<br/>%3<br/>%4<br/>%5</p><p>Icon by <a href='http://www.iconshock.com'>Icon Shock</a><br />Satellite images by <a href='http://www.nasa.gov'>NASA</a><br />ZoneDetect by <a href='https://github.com/BertoldVdb/ZoneDetect'>Bertold Van den Bergh</a><br />TimeZone Database by <a href='https://github.com/evansiroky/timezone-boundary-builder'>Evan Siroky</a> <h1>QLog %1</h1><p>&copy; 2019 Thomas Gatzweiler DL2IC<br/>&copy; 2021-2024 Ladislav Foldyna OK1MLG</p><p>Basado en Qt %2<br/>%3<br/>%4<br/>%5</p><p>Iconos por <a href='http://www.iconshock.com'>Icon Shock</a><br />Imágenes satelitales por <a href='http://www.nasa.gov'>NASA</a><br />Detección de zonas por <a href='https://github.com/BertoldVdb/ZoneDetect'>Bertold Van den Bergh</a><br />Base de datos de zonas horarias por <a href='https://github.com/evansiroky/timezone-boundary-builder'>Evan Siroky</a> - + About Acerca de - + N/A S/D @@ -6567,52 +6701,52 @@ Migration - + DXCC Entities Entidades DXCC - + Sats Info Informació de Satélites - + SOTA Summits Cumbres SOTA - + WWFF Records Registros WWFF - + IOTA Records Registros IOTA - + POTA Records Registros POTA - + Membership Directory Records Registros del Directorio de Miembros - + List of Values Lista de Valores - + Updating Actualizando - + Update Failed Actualización Fallida @@ -6645,320 +6779,320 @@ - + 80m - + RSTs RSTe - + RSTr RSTr - + 59 - + Mode Modo - + Save Guardar - + Lookup the call on the web. The query URL can be changed in Settings -> Callbook Consulta el indicativo en la web. La URL de consulta se puede cambiar en Ajustes ->Callbook - + Web Web - + Time On Hora Inicio - + Reset Reiniciar - + Date Fecha - + Duration Duración - + Info Información - + &Details &Detalles - + QSL Send Status Estado de envío de QSL - - + + Paper Papel - - - + + + <b>Yes</b> - an outgoing QSL card has been sent; the QSO has been uploaded to, and accepted by, the online service<br/><b>No</b> - do not send an outgoing QSL card; do not upload the QSO to the online service<br/><b>Requested</b> - the contacted station has requested a QSL card; the contacted station has requested the QSO be uploaded to the online service<br/><b>Queued</b> - an outgoing QSL card has been selected to be sent; a QSO has been selected to be uploaded to the online service<br/> <b>Sí</b>: se ha enviado una tarjeta QSL; el QSO ha sido cargado y aceptado por el servicio en línea<br/><b>No</b> - no envié una tarjeta QSL; no cargué el QSO al servicio en línea<br/><b>Solicitado</b> - la estación contactada ha solicitado una tarjeta QSL; la estación contactada ha solicitado que el QSO se cargue en el servicio en línea<br/><b>En cola</b> - se ha seleccionado una tarjeta QSL para enviar; Se ha seleccionado un QSO para subir al servicio online<br/> - + LoTW LoTW - + eQSL eQSL - + QSL Send via Enviar QSL vía - + QSL via QSL vía - + Propagation Mode Modo de Propagación - + D&XCC D&XCC - + M&y Station &Mi Estación - + Station Estación - + Rig Radio - + Antenna Antena - + Power Potencia - + Blank Vacío - + W W - + My &Notes Mis N&otas - + Member: Miembro: - - - + + + No No - - - + + + Yes - - - + + + Requested Solicitado - - - + + + Queued En Cola - - - + + + Ignored Ignorado - + Bureau Bureau - + Direct Directa - + Electronic Electrónica - + QLog Error Error de QLog - + Callbook login failed Error al iniciar sesión en el Callbook - + LP LP - + New Entity! Nueva Entidad! - + New Band! Nueva Banda! - + New Mode! Nuevo Modo! - + New Band & Mode! Nueva Banda y Modo! - + New Slot! Nuevo Slot! - + Worked Trabajado - + Confirmed Confirmado - + GE GE - + GM GM - + GA GA - + m - + Callbook search is inactive Búsqueda en Callbook desactivada - + Callbook search is active Búsqueda en Callbook activada - + two or four adjacent Maidenhead grid locators, each four characters long, (ex. EN98,FM08,EM97,FM07) dos o cuatro locators adyacentes, cada uno de cuatro caracteres (ej. EN98,FM08,EM97,FM07) - + the contacted station's DARC DOK (District Location Code) (ex. A01) el DARC DOK (código de ubicación de distrito) de la estación contactada (ej. A01) - + World Wide Flora & Fauna World Wide Flora & Fauna - + Special Activity Group Grupo de Actividades Especiales - + Special Activity Group Information Información Grupo de Actividades Especiales @@ -7137,7 +7271,7 @@ QCoreApplication - + QLog Help Ayuda de QLog @@ -7145,123 +7279,123 @@ QMessageBox - - - + + + QLog Critical QLog Crítico - + Cannot save a password for %1 to the Credential Store No se puede guardar una contraseña para %1 en el almacén de credenciales - + Cannot get a password for %1 from the Credential Store No se puede obtener una contraseña para %1 del almacén de credenciales - - - - - + + + + + - - - + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + QLog Warning Alerta de QLog - + Club List Update failed. Cannot remove old records Error al actualizar la lista de clubes. No se pueden eliminar registros antiguos - + Club List Update failed. Cannot plan new downloads Error al actualizar la lista de clubes. No se pueden planificar nuevas descargas - + Unexpected Club List download. Canceling next downloads Descarga inesperada de la lista de clubes. Cancelar próximas descargas - + Unexpected Club List content for Contenido inesperado de la lista de clubes para - + Network error. Cannot download Club List for Error de red. No se puede descargar la lista de clubes para - - - - - + + + + + - + - - + + QLog Error Error de QLog - + QLog is already running QLog ya se está ejecutando - + Could not connect to database. No se pudo conectar a la base de datos. - + Could not export a QLog database to ADIF as a backup.<p>Try to export your log to ADIF manually No se pudo exportar una base de datos QLog a ADIF como copia de seguridad.<p>Intente exportar su registro a ADIF manualmente - + Database migration failed. Error en la migración de la base de datos. - + Could not connect to database (2). No se pudo conectar a la base de datos (2). @@ -7296,33 +7430,33 @@ No se pueden actualizar las reglas de alerta - + DXC Server Name Error Error en el nombre del servidor del Cluster DX - + DXC Server address must be in format<p><b>[username@]hostname:port</b> (ex. hamqth.com:7300)</p> La dirección del servidor del Cluster DX debe tener el formato<p><b>[nombre de usuario@]nombre de host:puerto</b> (ej. hamqth.com:7300)</p> - + DX Cluster Password Contraseña del Cluster DX - + Invalid Password Contraseña incorrecta - + DXC Server Connection Error Error en la conexión del servidor del Cluster DX - + Filename is empty El nombre del archivo está vacío @@ -7361,22 +7495,22 @@ El nombre de la disposición ya existe. - + <b>Rig Error:</b> <b>Error de la Radio:</b> - + <b>Rotator Error:</b> <b>Error del Rotor:</b> - + <b>CW Keyer Error:</b> <b>Error del Manipulador:</b> - + Your callsign is empty. Please, set your Station Profile Tu indicativo está vacío. Por favor, configure su Perfil de Estación @@ -7396,84 +7530,84 @@ No se puede actualizar el tipo de coincidencia del filtro de QSO - - - + + Please, define at least one Station Locations Profile Por favor, defina al menos un Perfil de Ubicaciones de Estaciones - + WSJTX Multicast is enabled but the Address is not a multicast address. WSJTX Multicast está habilitada pero la dirección no es una dirección de multidifusión. - + Rig port must be a valid COM port.<br>For Windows use COMxx, for unix-like OS use a path to device El puerto de la Radio debe ser un puerto COM válido.<br>Para Windows use COMxx, para sistemas operativos tipo Unix use una ruta al dispositivo - + Rig PTT port must be a valid COM port.<br>For Windows use COMxx, for unix-like OS use a path to device El puerto de control del PTT debe ser un puerto COM válido.<br>Para Windows utilice COMxx, para SO tipo unix utilice una ruta al dispositivo - + <b>TX Range</b>: Max Frequency must not be 0. <b>Rango TX</b>: la frecuencia máxima no debe ser 0. - + <b>TX Range</b>: Max Frequency must not be under Min Frequency. <b>Rango TX</b>: la frecuencia máxima no debe estar por debajo de la frecuencia mínima. - + Rotator port must be a valid COM port.<br>For Windows use COMxx, for unix-like OS use a path to device El puerto del Rotor debe ser un puerto COM válido.<br>Para Windows use COMxx, para sistemas operativos tipo Unix use una ruta al dispositivo - + CW Keyer port must be a valid COM port.<br>For Windows use COMxx, for unix-like OS use a path to device El puerto del Manipulador debe ser un puerto COM válido.<br>Para Windows use COMxx, para sistemas operativos tipo Unix use una ruta al dispositivo - + Cannot change the CW Keyer Model to <b>Morse over CAT</b><br>No Morse over CAT support for Rig(s) <b>%1</b> No se puede cambiar el modelo de Manipulador a <b>Morse sobre CAT</b><br>No se admite Morse sobre CAT para la/s Radio/s <b>%1</b> - + Cannot delete the CW Keyer Profile<br>The CW Key Profile is used by Rig(s): <b>%1</b> No se puede eliminar el Perfil del Manipulador<br>El Perfil del Manipulador es utilizado por la/s radio/s: <b>%1</b> - + Callsign has an invalid format El Indicativo tiene un formato no válido - + Gridsquare has an invalid format La cuadrícula no es válida en ese formato. El Locator tiene un formato no válido - + VUCC Grids have an invalid format (must be 2 or 4 Gridsquares separated by ',') El Locator VUCC tiene un formato no válido (debe se 2 o 4 dígitos separadas por ',') - + Country must not be empty El País no debe estar vacío - + CQZ must not be empty La Zona CQ no debe estar vacía - + ITU must not be empty ITU no debe estar vacío @@ -7492,148 +7626,148 @@ - - + + Connection Refused Conexión Denegada - - + + Host closed the connection El host cerró la conexión - - + + Host not found Host no encontrado - - + + Timeout Se agotó el tiempo de espera - - + + Network Error Error de red - - + + Internal Error Error Interno - + Opening Database Abriendo Base de Datos - + Backuping Database Respaldando Base de Datos - + Migrating Database Migrando Base de Datos - + Starting Application Iniciando Aplicación - + My Rig Mi Radio - + Logging Station Callsign Indicativo de la Estación - + My Gridsquare Mi Locator - + My Name Mi Nombre - + My City Mi Ciudad - + My IOTA Mi IOTA - + My SOTA Mi SOTA - + My Special Interest Activity Mi Actividad de Interés Especial - + My Spec. Interes Activity Info Mi Info de Actividad de Interés Especial - + My VUCC Grids Mi Locator VUCC - + My WWFF Mi WWFF - + My POTA Ref Mi Ref POTA - + My ITU MI ITU - + My CQZ Mi Zona CQ - + My DXCC Mi DXCC - + Cannot connect to DXC Server <p>Reason <b>: No se puede conectar al servidor del Cluster DX <p>Razón <b>: - + <b>Imported</b>: %n contact(s) <b>Importado</b>: %n contacto/s @@ -7641,7 +7775,7 @@ - + <b>Warning(s)</b>: %n <b>Alerta/s</b>: %n @@ -7649,7 +7783,7 @@ - + <b>Error(s)</b>: %n <b>Error/es</b>: %n @@ -7713,23 +7847,23 @@ "No" - + Uploading to QRZ.com Subiendo a QRZ.com - + Cancel Cancelar - - + + QLog Information Información de QLog - + %n QSO(s) uploaded. %n QSO/s subido/s. @@ -7737,17 +7871,17 @@ - + QLog Warning Alerta de QLog - + Cannot upload the QSO(s): No se puede subir el/los QSO/s: - + No QSOs found to upload. No se encontraron QSOs para subir. @@ -8644,22 +8778,22 @@ Rig - + No Rig Profile selected No Hay Perfil de Radio Seleccionado - + Initialization Error Error al Inicializar - + Internal Error Error Interno - + Cannot open Rig No se puede abrir la Radio @@ -8692,7 +8826,7 @@ - + PWR: %1W @@ -8700,22 +8834,22 @@ Rotator - + No Rotator Profile selected No Hay Perfil de Rotor Seleccionado - + Initialization Error Error al Inicializar - + Internal Error Error Interno - + Cannot open Rotator No se puede abrir el Rotor @@ -8900,20 +9034,20 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + Add Agregar @@ -9513,14 +9647,14 @@ - + Serial Serie - - + + Network Red @@ -9571,8 +9705,8 @@ - - + + HamQTH @@ -9598,8 +9732,8 @@ - - + + QRZ.com @@ -9741,333 +9875,333 @@ Bandas - + Modes Modos - + DXCC - + Wsjtx - + Raw UDP Forward Reenvío UDP sin procesar - + <p>List of IP addresses to which QLog forwards raw UDP WSJT-X packets.</p>The IP addresses are separated by a space and have the form IP:PORT <p>Lista de direcciones IP a las que QLog reenvía paquetes UDP WSJT-X sin procesar.</p>Las direcciones IP están separadas por un espacio y tienen el formato IP:PUERTO - - - - - + + + + + ex. 192.168.1.1:1234 192.168.2.1:1234 ej. 192.168.1.1:1234 192.168.2.1:1234 - + Port Puerto - + Port where QLog listens an incoming traffic from WSJT-X Puerto donde QLog escucha el tráfico entrante de WSJT-X - + Join Multicast Unirse a Multidifusión - + Enable/Disable Multicast option for WSJTX Activar/desactivar la opción de multidifusión para WSJTX - + Multicast Address Dirección de multidifusión - + Specify Multicast Address. <br>On some Linux systems it may be necessary to enable multicast on the loop-back network interface. Especifique la dirección de multidifusión. <br>En algunos sistemas Linux, puede ser necesario habilitar la multidifusión en la interfaz de red de bucle invertido. - + TTL TTL - + Time-To-Live determines the range<br> over which a multicast packet is propagated in your intranet. Time-To-Live determina el rango<br> sobre el cual se propaga un paquete de multidifusión en su intranet. - + Notifications Notificaciones - + LogID - + <p>Assigned LogID to the current log.</p>The LogID is sent in the Network Nofitication messages as a unique instance identified.<p> The ID is generated automatically and cannot be changed</> <p>LogID asignado al registro actual.</p>El LogID se envía en los mensajes de notificación de red como una instancia única identificada.<p>El ID se genera automáticamente y no se puede cambiar</> - + DX Spots Anuncios DX - + <p> List of IP addresses to which QLog sends UDP notification packets with DX Cluster Spots.</p>The IP addresses are separated by a space and have the form IP:PORT <p> Lista de direcciones IP a las que QLog envía paquetes de notificación UDP con anuncios de Cluster DX.</p> Las direcciones IP están separadas por un espacio y tienen la forma IP:PUERTO - + Spot Alerts Alertas de Anuncios - + <p> List of IP addresses to which QLog sends UDP notification packets about user Spot Alerts.</p>The IP addresses are separated by a space and have the form IP:PORT <p> Lista de direcciones IP a las que QLog envía paquetes de notificación UDP sobre Alertas de Anuncios de usuario.</p> Las direcciones IP están separadas por un espacio y tienen el formato IP:PUERTO - + QSO Changes Cambios de QSO - + <p> List of IP addresses to which QLog sends UDP notification packets about a new/updated/deleted QSO in the log.</p>The IP addresses are separated by a space and have the form IP:PORT <p> Lista de direcciones IP a las que QLog envía paquetes de notificación UDP sobre un QSO nuevo/actualizado/eliminado en el registro.</p>Las direcciones IP están separadas por un espacio y tienen el formato IP:PUERTO - + Wsjtx CQ Spots Anuncios CQ de Wsjtx - + <p> List of IP addresses to which QLog sends UDP notification packets with WSJTX CQ Spots.</p>The IP addresses are separated by a space and have the form IP:PORT <p> Lista de direcciones IP a las que QLog envía paquetes de notificación UDP con Anuncios de CQ de WSJTX.</p>Las direcciones IP están separadas por un espacio y tienen el formato IP:PUERTO - + Shortcuts Atajos del teclado - - + + Special - Omnirig Especial - Omnirig - - + + Name Nombre - + Report Informe - - + + State Estado - + Start (MHz) Inicio (MHz) - + End (MHz) Fin (MHz) - + SAT Mode Modo del Satélite - - - + + + Disabled Desactivado - - + + None Ninguno - - + + Hardware Hardware - - + + Software Software - - + + No No - - + + Even Par - - + + Odd Impar - - + + Mark Marca - - + + Space Espacio - + Dummy - + Morse Over CAT Morse Sobre CAT - + WinKey v2 - + CWDaemon - + FLDigi - + Single Paddle Pala Simple - + IAMBIC A - + IAMBIC B - + Ultimate - + Press <b>Modify</b> to confirm the profile changes or <b>Cancel</b>. Presione <b>Modificar</b> para confirmar los cambios de perfil o <b>Cancelar</b>. - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + Modify Modificar - - - - - - - - - - + + + + + + + + + + Must not be empty No debe estar vacío - + Select File Seleccionar Archivo - + members Miembros - + Required internet connection during application start Required internet connection during application start @@ -10075,22 +10209,22 @@ ShortcutEditorModel - + Description Descripción - + Shortcut Atajo - + Conflict with a built-in shortcut Conflicto con un atajo integrado - + Conflict with a user-defined shortcut Conflicto con un atajo definido por el usuario @@ -10117,6 +10251,7 @@ StatisticsWidget + Statistics Estadísticas @@ -10182,7 +10317,7 @@ - + Band Banda @@ -10217,127 +10352,132 @@ - + Year Año - + Month Mes - + Day in Week Día de la Semana - + Hour Hora - + Mode Modo - + Continent Continente - + Propagation Mode Modo de Propagación - + Confirmed / Not Confirmed Confirmado / No Confirmado - + Countries Paises - + Big Gridsquares Grandes cuadrículas - + Distance Distancia - + QSOs QSOs - + Confirmed/Worked Grids Locators Confirmados/Trabajados - + ODX ODX - + Sun Dom - + Mon Lun - + Tue Mar - + Wed Mie - + Thu Jue - + Fri Vie - + Sat Sáb - + Not specified No Especificado - + Confirmed Confirmado - + Not Confirmed No Confirmado - + + Over 50000 QSOs. Display them? + Más de 50.000 QSO. ¿Mostrarlo? + + + All Todos @@ -10345,37 +10485,37 @@ TCIRigDrv - + Rig 0 Radio 0 - + Rig 1 Radio 1 - + Rig 2 Radio 2 - + Rig 3 Radio 3 - + Error Occured Ha ocurrido un error - + Rig status changed El estado de la radio ha cambiado - + Rig is not connected Radio no conectada @@ -10391,17 +10531,17 @@ ToAllTableModel - + Time Hora - + Spotter Anunciante - + Message Mensaje @@ -10437,47 +10577,47 @@ WCYTableModel - + Time Hora - + K - + expK - + A - + R - + SFI - + SA - + GMF - + Au @@ -10485,27 +10625,27 @@ WWVTableModel - + Time Hora - + SFI - + A - + K - + Info Info @@ -10631,37 +10771,37 @@ WsjtxTableModel - + Callsign Indicativo - + Gridsquare Cuadrícula - + Distance Distancia - + SNR - + Last Activity Última Actividad - + Last Message Último Mensaje - + Member Miembro @@ -10702,32 +10842,32 @@ main - + Run with the specific namespace. - + namespace - + Translation file - absolute or relative path and QM file name. - + path/QM-filename - + Set language. <code> example: 'en' or 'en_US'. Ignore environment setting. - + code diff --git a/i18n/qlog_it.qm b/i18n/qlog_it.qm index fd4771b1..a4c1dbe8 100644 Binary files a/i18n/qlog_it.qm and b/i18n/qlog_it.qm differ diff --git a/i18n/qlog_it.ts b/i18n/qlog_it.ts index e589d974..0b406554 100644 --- a/i18n/qlog_it.ts +++ b/i18n/qlog_it.ts @@ -108,44 +108,44 @@ Continente - - + + North America Nord America - - + + Africa Africa - - + + Antarctica Antartide - - + + South America Sud America - + Asia Asia - + Europe Europa - - + + Oceania Oceanía @@ -189,17 +189,17 @@ Regole - + Add Aggiungi - + Edit Modifica - + Remove Rimuovi @@ -251,6 +251,11 @@ Last Comment Último Commento + + + Member + Membro + AlertWidget @@ -363,117 +368,117 @@ Mostra - + DXCC DXCC - + ITU ITU - + WAC WAC - + WAZ WAZ - + WAS WAS - + WPX WPX - + IOTA IOTA - + POTA Hunter POTA Hunter - + POTA Activator POTA Activator - + SOTA SOTA - + WWFF WWFF - + Done Fatto - + North America Nord America - + South America South America - + Europe Europa - + Africa Africa - + Oceania Oceanía - + Asia Asia - + Antarctica Antartide - + TOTAL Worked TOTALE Lavorato - + TOTAL Confirmed TOTALE Confermato - + Confirmed Confermato - + Worked Lavorato @@ -706,17 +711,17 @@ Cancella - + Rig must be connected La radio deve essere connessa - + Word Parola - + Whole Tutto @@ -814,27 +819,27 @@ CWKeyer - + No CW Keyer Profile selected Nessun Profilo Keyer CW selezionato - + Initialization Error Errore di inizializzazione - + Internal Error Errore Interno - + Connection Error Errore di connessione - + Cannot open the Keyer connection Impossibile aprire la connessione Keyer @@ -842,39 +847,39 @@ CWWinKey2 - + Connected device is not WinKey Il dispositivo connesso non è Winkey - + Connected device is not WinKey v2 or newer Il dispositivo connesso non è Winkey v2 o successivo - + Cannot send Text to Rig Impossibile inviare Testo alla Radio - - - + + + Keyer is not connected Keyer non connesso - + Communication Error Errore di comunicazione - + Cannot set Keyer Speed Impossibile impostare velocità Keyer - + Cannot stop Text Sending Impossibile fermare invio Testo @@ -962,7 +967,7 @@ ClubLog - + Clublog Operation for Callsign %1 failed.<br>%2 Operazione Clublog per il nominativo %1 non riuscita.<br>%2 @@ -2839,151 +2844,151 @@ Data - + New Entity Nuova Entità - + New Band Nuova Banda - + New Mode Nuovo Modo - + New Band&Mode Nuovi Banda&Modo - + New Slot Nuovo Slot - + Confirmed Confermato - + Worked Lavorato - + Hz Hz - + kHz kHz - + GHz GHz - + MHz MHz + + + + + + + Yes + + - Yes - - - - - - - - No No - - + + Requested Richiesto - + Queued In coda - - + + Invalid non valido - + Bureau Bureau - + Direct Diretto - + Electronic Elettronica - - - - - + + + + + Blank Vuoto - + Modified Modificato - + Grayline Grayline - + Other Altro - + Short Path Short Path - + Long Path Long Path - + Not Heard Non ascoltato - + Uncertain Incerto @@ -3274,57 +3279,57 @@ DxTableModel - + Time Ora - + Callsign Indicativo - + Frequency Frequenza - + Mode Modo - + Spotter Spotter - + Comment Commento - + Continent Continente - + Spotter Continent Continente Spotter - + Band Banda - + Member Membro - + Country Nazione @@ -3338,7 +3343,7 @@ - + Connect Connette @@ -3368,156 +3373,186 @@ Console - + + Full-text search + Ricerca a testo completo + + + + Search + Ricerca + + + + Close Search + Chiudi ricerca + + + Send DX Cluster Command Invia comando DX Cluster - + Filter... Filtra... - + Filter DXC Filtro DXC - + Spot Last QSO Invia lo Spot dell'ultimo QSO salvato completabile con altre informazioni nella riga di invio comando al cluster Spot Ultimo QSO salvato - + Send last QSO spot Invia l'ultimo spot QSO - + Show HF Stats Mostra statistiche HF - + Show VHF Stats Mostra statistiche VHF - + Show WCY Mostra WCY - + Show WWV Mostra WWV - + Column Visibility... Visibilità della colonna... - + Which columns should be displayed Quali colonne devono essere visualizzate - + Connect on startup Connetti all'avvio - + Automatic connection after start Connessione automatica dopo l'avvio - + Delete Server Cancella Server - + DXC - Delete Server DXC - Elimina server - + Clear Password Cancella Password - + Keep Spots Mantieni Spots - + Spots are not cleared when connecting to a new DX Cluster. Gli spot non vengono cancellati quando ci si connette a un nuovo DX Cluster. - + Clear Cancella - + Clear all data Cancella Tutti i Dati - + + Search... + Ricerca... + + + + DXC - Search + DXC - Ricerca + + + Connecting... Sta Connettendo... - + DX Cluster is temporarily unavailable DX Cluster è temporaneamente non disponibile - + DXC Server Error DXC Errore del server - + An invalid callsign Indicativo non valido - + DX Cluster Password DX Cluster Password - + Security Notice Avviso di sicurezza - + The password can be sent via an unsecured channel La password può essere inviata tramite un canale non protetto - + Server Server - + Username Nome utente - + Disconnect Disconnette + + + DX Cluster Command + Comando del DX Cluster + DxccTableModel @@ -3545,7 +3580,7 @@ DxccTableWidget - + Mode Modo @@ -4034,23 +4069,23 @@ "No" - + Uploading to HRDLOG Caricamento su HRDLOG - + Cancel Elimina - - + + QLog Information Informazioni QLog - + %n QSO(s) uploaded. %n QSO caricato. @@ -4058,17 +4093,17 @@ - + QLog Warning Avviso QLog - + Cannot upload the QSO(s): Impossibile caricare il/i QSO: - + No QSOs found to upload. Nessun QSO trovato da caricare. @@ -4084,87 +4119,173 @@ HamlibRigDrv - + None Nessuno - + CAT CAT - + DTR DTR - + RTS RTS - - + + Initialization Error Errore di inizializzazione - + Cannot set PTT Type Impossibile impostare Tipo PTT - + Cannot set PTT Share Impossibile impostare Condividi PTT - + Unsupported Rig Driver Driver della Radio non Supportato - + + Rig Open Error + Connessione fallita + + + Set Frequency Error Errore impostazione fequenza - + + Set Mode Error + Errore nella impostazione della modalità + + + Set PTT Error Errore impostazione PTT - + + Cannot sent Morse + This cannot be displayed + + + + + Cannot stop Morse + This cannot be displayed + + + + + Get PTT Error + This cannot be displayed + + + + Get Frequency Error Errore di ricezione della frequenza - + Get Mode Error Errore di ricezione del modo + + + Get VFO Error + Errore nel recupero del VFO + + + + Get PWR Error + This cannot be displayed + + + + + Get PWR (power2mw) Error + This cannot be displayed + + + + + Get RIT Function Error + This cannot be displayed + + + + + Get RIT Error + This cannot be displayed + + + + + Get XIT Function Error + This cannot be displayed + + + + + Get XIT Error + This cannot be displayed + + + + + Get KeySpeed Error + This cannot be displayed + + + + + Set KeySpeed Error + This cannot be displayed + + HamlibRotDrv - - + + Initialization Error Errore di inizializzazione - + Unsupported Rotator Driver Driver del rotore non supportato - + + Rot Open Error + Connessione fallita + + + Set Possition Error Errore di impostazione della posizione - + Get Possition Error Errore di ricezione della posizione @@ -4223,7 +4344,7 @@ - + The value is used when an input record does not contain the ADIF value Il valore viene utilizzato quando una registrazione inserita non contiene il valore ADIF @@ -4244,68 +4365,68 @@ - + Comment Commento - + &Import &Importa - + Select File Seleziona File - - + + The values below will be used when an input record does not contain the ADIF values I valori seguenti verranno utilizzati quando una registrazione inserita non contiene i valori ADIF - + <p><b>In-Log QSO:</b></p><p> <p><b>In-Log QSO:</b></p><p> - + <p><b>Importing:</b></p><p> <p><b>Importazione:</b></p><p> - + Duplicate QSO QSO duplicato - + <p>Do you want to import duplicate QSO?</p>%1 %2 <p>Vuoi importare QSO duplicati?</p>%1 %2 - + Save to File Salva sul file - + QLog Import Summary Riepilogo dell'importazione QLog - + Import date Data di importazione - + Imported file File importato - + Imported: %n contact(s) Importato: %n contatto @@ -4313,7 +4434,7 @@ - + Warning(s): %n Allarme: %n @@ -4321,7 +4442,7 @@ - + Error(s): %n Errore: %n @@ -4329,17 +4450,17 @@ - + Details Dettagli - + Import Result Risultato importazione - + Save Details... Salva dettagli... @@ -4605,48 +4726,61 @@ LogFormat - + + + Cannot find My DXCC Entity Info + Impossibile trovare le informazioni sulla mia entità DXCC + + + A minimal set of fields not present (start_time, call, band, mode, station_callsign) Un minimo set di campi non presenti (start_time, call, band, mode, station_callsign) - + Outside the selected Date Range Otre il range di Data selezionata - - + + Duplicate Duplicato - + Cannot find DXCC Entity Info Impossibile trovare le informazioni sull'entità DXCC - - Cannot find own DXCC Entity Info - Impossibile trovare le informazioni sulla propria entità DXCC + + DXCC Info is missing + Le informazioni DXCC mancano + + + + + + no Station Callsign present + - + Cannot insert to database Impossibile inserire nel Database - + Imported Importato - + Error Errore - + Warning Attenzione @@ -5546,20 +5680,20 @@ - + Club Club - + User Filter Filtro Utente - - + + Delete Elimina @@ -5625,32 +5759,32 @@ Esporta QSO selezionati - + Delete the selected contacts? Eliminare i contatti selezionati? - + Clublog's <b>Immediately Send</b> supports only one-by-one deletion<br><br>Do you want to continue despite the fact<br>that the DELETE operation will not be sent to Clublog? L'<b>Invio immediato</b> di Clublog supporta solo l'eliminazione uno per uno<br><br>Vuoi continuare nonostante il fatto<br>che l'operazione DELETE non verrà inviata a Clublog? - + Deleting QSOs Elimina QSOs - + Update Aggiornare - + By updating, all selected rows will be affected.<br>The value currently edited in the column will be applied to all selected rows.<br><br>Do you want to edit them? L'aggiornamento avrà effetto su tutte le righe selezionate.<br>Il valore attualmente modificato nella colonna verrà applicato a tutte le righe selezionate.<br><br>Vuoi modificarle? - + Count: %n Conteggio: %n @@ -5658,23 +5792,23 @@ - + Downloading eQSL Image Download immagine da eQSL - - + + Cancel Elimina - + QLog Error Errore di QLog - + eQSL Download Image failed: Download immagine da eQSL fallito: @@ -6048,7 +6182,7 @@ Non deve essere vuoto - + Unsaved Non Salvato @@ -6391,78 +6525,78 @@ Radio - PTT On/Off - + Not enabled for non-Fusion style Non abilitato per stili diversi da Fusion - + Press to tune the alert Premi per sintonizzare l'allarme - + Clublog Immediately Upload Error Errore di caricamento immediato di Clublog - - + + <b>Error Detail:</b> <b>Dettagli errore:</b> - + Classic Classico - - - - - + + + + + QLog Warning Avviso QLog - + LoTW is not configured properly.<p> Please, use <b>Settings</b> dialog to configure it.</p> LoTW non è configurato correttamente.<p> Utilizza la finestra di dialogo <b>Impostazioni</b> per configurarlo.</p> - + eQSL is not configured properly.<p> Please, use <b>Settings</b> dialog to configure it.</p> eQSL non è configurato correttamente.<p> Utilizza la finestra di dialogo <b>Impostazioni</b> per configurarlo.</p> - + Clublog is not configured properly.<p> Please, use <b>Settings</b> dialog to configure it.</p> Clublog non è configurato correttamente.<p> Utilizza la finestra di dialogo <b>Impostazioni</b> per configurarlo.</p> - + HRDLog is not configured properly.<p> Please, use <b>Settings</b> dialog to configure it.</p> HRDLog non è configurato correttamente.<p> Utilizza la finestra di dialogo <b>Impostazioni</b> per configurarlo.</p> - + QRZ.com is not configured properly.<p> Please, use <b>Settings</b> dialog to configure it.</p> QRZ.com non è configurato correttamente.<p> Utilizza la finestra di dialogo <b>Impostazioni</b> per configurarlo.</p> - + <h1>QLog %1</h1><p>&copy; 2019 Thomas Gatzweiler DL2IC<br/>&copy; 2021-2024 Ladislav Foldyna OK1MLG</p><p>Based on Qt %2<br/>%3<br/>%4<br/>%5</p><p>Icon by <a href='http://www.iconshock.com'>Icon Shock</a><br />Satellite images by <a href='http://www.nasa.gov'>NASA</a><br />ZoneDetect by <a href='https://github.com/BertoldVdb/ZoneDetect'>Bertold Van den Bergh</a><br />TimeZone Database by <a href='https://github.com/evansiroky/timezone-boundary-builder'>Evan Siroky</a> <h1>QLog %1</h1><p>&copy; 2019 Thomas Gatzweiler DL2IC<br/>&copia; 2021-2024 Ladislav Foldyna OK1MLG</p><p>Basato su Qt %2<br/>%3<br/>%4<br/>%5</p><p>Icona di <a href=' http://www.iconshock.com'>Icon Shock</a><br />Immagini satellitari di <a href='http://www.nasa.gov'>NASA</a><br />ZoneDetect di <a href='https://github.com/BertoldVdb/ZoneDetect'>Bertold Van den Bergh</a><br />Database TimeZone di <a href='https://github.com/evansiroky/timezone -boundary-builder'>Evan Siroky</a> - + About A proposito di - + N/A N/A @@ -6529,52 +6663,52 @@ Migration - + DXCC Entities Entità DXCC - + Sats Info Info Satelliti - + SOTA Summits SOTA Summits - + WWFF Records WWFF Records - + IOTA Records IOTA Records - + POTA Records POTA Records - + Membership Directory Records Registro dell'elenco dei membri - + List of Values Lista di valori - + Updating In aggiornamento - + Update Failed Aggiornamento fallito @@ -6607,320 +6741,320 @@ - + 80m - + RSTs RSTs - + RSTr RSTr - + 59 - + Mode Modo - + Save Salva - + Lookup the call on the web. The query URL can be changed in Settings -> Callbook Cerca il call sul web. L'URL della query può essere modificato in Impostazioni -> Rubrica - + Web Web - + Time On Inizio - + Reset Reset - + Date Data - + Duration Durata - + Info Info - + &Details &Dettagli - + QSL Send Status Stato invio QSL - - + + Paper Cartaceo - - - + + + <b>Yes</b> - an outgoing QSL card has been sent; the QSO has been uploaded to, and accepted by, the online service<br/><b>No</b> - do not send an outgoing QSL card; do not upload the QSO to the online service<br/><b>Requested</b> - the contacted station has requested a QSL card; the contacted station has requested the QSO be uploaded to the online service<br/><b>Queued</b> - an outgoing QSL card has been selected to be sent; a QSO has been selected to be uploaded to the online service<br/> <b>Sì</b> - è stata inviata una QSL in uscita; il QSO è stato caricato e accettato dal servizio online<br/><b>No</b> - non inviare una cartolina QSL in uscita; non caricare il QSO sul servizio online<br/><b>Richiesto</b> - la stazione contattata ha richiesto una QSL; la stazione contattata ha richiesto il caricamento del QSO sul servizio online<br/><b>Queued</b> - è stata selezionata una QSL in uscita da inviare; è stato selezionato un QSO da caricare sul servizio online<br/> - + LoTW LoTW - + eQSL eQSL - + QSL Send via Invia QSL vía - + QSL via QSL vía - + Propagation Mode Modo di Propagazione - + D&XCC D&XCC - + M&y Station M&ia Stazione - + Station Stazione - + Rig Radio - + Antenna Antenna - + Power Potenza - + Blank Vuoto - + W W - + My &Notes Le mie N&ote - + Member: Membro: - - - + + + No No - - - + + + Yes - - - + + + Requested Richiesto - - - + + + Queued In coda - - - + + + Ignored Ignorato - + Bureau Bureau - + Direct Diretto - + Electronic Elettronica - + QLog Error Errore di QLog - + Callbook login failed Accesso al Logbook non riuscito - + LP LP - + New Entity! Nuova Entità! - + New Band! Nuova Banda! - + New Mode! Nuovo Modo! - + New Band & Mode! Nuova Banda e Modo! - + New Slot! Nuovo Slot! - + Worked Lavorato - + Confirmed Confermato - + GE GE - + GM GM - + GA GA - + m - + Callbook search is inactive Ricerca sul Callbook inattiva - + Callbook search is active Ricerca sul Callbook attiva - + two or four adjacent Maidenhead grid locators, each four characters long, (ex. EN98,FM08,EM97,FM07) due o quattro localizzatori di griglia Maidenhead adiacenti, ciascuno lungo quattro caratteri, (es. EN98,FM08,EM97,FM07) - + the contacted station's DARC DOK (District Location Code) (ex. A01) il DARC DOK (District Location Code) della stazione contattata (ex. A01) - + World Wide Flora & Fauna World Wide Flora & Fauna - + Special Activity Group Gruppo di Attività Speciali - + Special Activity Group Information Informazioni sul gruppo di attività speciali @@ -7099,7 +7233,7 @@ QCoreApplication - + QLog Help QLog Help @@ -7107,124 +7241,124 @@ QMessageBox - - - + + + QLog Critical QLog Crítico - + Cannot save a password for %1 to the Credential Store Impossibile salvare una password per %1 nell'archivio credenziali - + Cannot get a password for %1 from the Credential Store Impossibile ottenere una password per %1 dall'archivio credenziali - - - - - + + + + + - - - + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + QLog Warning Avviso QLog - + Club List Update failed. Cannot remove old records 50 / 5.000 Aggiornamento elenco club non riuscito. Impossibile rimuovere i vecchi record - + Club List Update failed. Cannot plan new downloads Aggiornamento elenco club non riuscito. Impossibile pianificare nuovi download - + Unexpected Club List download. Canceling next downloads Download imprevisto della Club-List. Annullamento dei download successivi - + Unexpected Club List content for Contenuti imprevisti della Club-List per - + Network error. Cannot download Club List for Errore di rete. Impossibile scaricare l'elenco dei club per - - - - - + + + + + - + - - + + QLog Error Errore di QLog - + QLog is already running QLog è già in esecuzione - + Could not connect to database. Impossibile collegare il Database. - + Could not export a QLog database to ADIF as a backup.<p>Try to export your log to ADIF manually Impossibile esportare un database QLog in ADIF come backup.<p>Prova a esportare manualmente il tuo Log in ADIF - + Database migration failed. Errore nella Migrazione del database. - + Could not connect to database (2). Impossibile connettere il Database (2). @@ -7259,33 +7393,33 @@ Aggiornamento elenco club non riuscito. Impossibile rimuovere i vecchi recordImpossibile aggiornare le Regole di allarme - + DXC Server Name Error Errore nel nome del server DXC - + DXC Server address must be in format<p><b>[username@]hostname:port</b> (ex. hamqth.com:7300)</p> L'indirizzo del server DXC deve essere nel formato<p><b>[nomeutente@]nomehost:porta</b> (es. hamqth.com:7300)</p> - + DX Cluster Password DX Cluster Password - + Invalid Password Password non corretta - + DXC Server Connection Error Errore di connessione al server DXC - + Filename is empty Filename vuoto @@ -7324,22 +7458,22 @@ Aggiornamento elenco club non riuscito. Impossibile rimuovere i vecchi recordIl nome del layout esiste già. - + <b>Rig Error:</b> <b>Errore della Radio:</b> - + <b>Rotator Error:</b> <b>Errore del rotore:</b> - + <b>CW Keyer Error:</b> <b>Errore Keyer CW:</b> - + Your callsign is empty. Please, set your Station Profile Il tuo nominativo è vuoto. Per favore, imposta il Profilo della tua Stazione @@ -7359,83 +7493,83 @@ Aggiornamento elenco club non riuscito. Impossibile rimuovere i vecchi recordImpossibile aggiornare il tipo di corrispondenza del filtro QSO - - - + + Please, define at least one Station Locations Profile Per favore, definisci almeno un profilo di posizioni della stazione - + WSJTX Multicast is enabled but the Address is not a multicast address. WSJTX Multicast è abilitato ma l'indirizzo non è un indirizzo multicast. - + Rig port must be a valid COM port.<br>For Windows use COMxx, for unix-like OS use a path to device La porta della Radio deve essere una porta COM valida.<br>Per Windows utilizzare COMxx, per sistemi operativi di tipo Unix utilizzare un percorso per il dispositivo - + Rig PTT port must be a valid COM port.<br>For Windows use COMxx, for unix-like OS use a path to device La porta PTT della Radio deve essere una porta COM valida.<br>Per Windows utilizzare COMxx, per sistemi operativi di tipo Unix utilizzare un percorso al dispositivo - + <b>TX Range</b>: Max Frequency must not be 0. <b>Intervallo TX</b>: la frequenza massima non deve essere 0. - + <b>TX Range</b>: Max Frequency must not be under Min Frequency. <b>Intervallo TX</b>: la frequenza massima non deve essere inferiore alla frequenza minima. - + Rotator port must be a valid COM port.<br>For Windows use COMxx, for unix-like OS use a path to device La porta del rotore deve essere una porta COM valida.<br>Per Windows utilizzare COMxx, per sistemi operativi di tipo Unix utilizzare un percorso per il dispositivo - + CW Keyer port must be a valid COM port.<br>For Windows use COMxx, for unix-like OS use a path to device La porta del keyer CW deve essere una porta COM valida.<br>Per Windows utilizzare COMxx, per sistemi operativi di tipo Unix utilizzare un percorso per il dispositivo - + Cannot change the CW Keyer Model to <b>Morse over CAT</b><br>No Morse over CAT support for Rig(s) <b>%1</b> Impossibile modificare il modello CW Keyer in <b>Morse su CAT</b><br>Nessun supporto Morse su CAT per a Radio <b>%1</b> - + Cannot delete the CW Keyer Profile<br>The CW Key Profile is used by Rig(s): <b>%1</b> Impossibile eliminare il profilo CW Keyer<br>Il profilo CW Keyer è utilizzato da Radio: <b>%1</b> - + Callsign has an invalid format L'indicativo ha un formato non valido - + Gridsquare has an invalid format La Griglia ha un formato non valido - + VUCC Grids have an invalid format (must be 2 or 4 Gridsquares separated by ',') Le griglie VUCC hanno un formato non valido (devono essere 2 o 4 Gridsquare separati da ',') - + Country must not be empty Nazione non deve essere vuoto - + CQZ must not be empty La CQ Zone non deve essere vuota - + ITU must not be empty ITU non deve essere vuoto @@ -7454,148 +7588,148 @@ Aggiornamento elenco club non riuscito. Impossibile rimuovere i vecchi record - - + + Connection Refused Connessione rifiutata - - + + Host closed the connection Host ha chiuso la connessione - - + + Host not found Host non trovato - - + + Timeout Timeout - - + + Network Error Errore di rete - - + + Internal Error Errore Interno - + Opening Database Apertura Database - + Backuping Database Backup del database - + Migrating Database Migrazione del database - + Starting Application Avvio applicazione - + My Rig Mia Radio - + Logging Station Callsign Indicativo della stazione - + My Gridsquare Mia Griglia - + My Name Mio nome - + My City Mia Città - + My IOTA Mio IOTA - + My SOTA Mio SOTA - + My Special Interest Activity Mie attività di interesse speciale - + My Spec. Interes Activity Info Informazioni sulle mie attività di interesse speciale - + My VUCC Grids Mia Griglia VUCC - + My WWFF Mio WWFF - + My POTA Ref Mio Ref POTA - + My ITU Mio ITU - + My CQZ Mia CQ Zone - + My DXCC Mio DXCC - + Cannot connect to DXC Server <p>Reason <b>: Impossibile connettersi al server DXC <p>Motivo <b>: - + <b>Imported</b>: %n contact(s) <b>Importato</b>: %n contatto @@ -7603,7 +7737,7 @@ Aggiornamento elenco club non riuscito. Impossibile rimuovere i vecchi record - + <b>Warning(s)</b>: %n <b>Allarme</b>: %n @@ -7611,7 +7745,7 @@ Aggiornamento elenco club non riuscito. Impossibile rimuovere i vecchi record - + <b>Error(s)</b>: %n <b>Errore</b>: %n @@ -7675,23 +7809,23 @@ Aggiornamento elenco club non riuscito. Impossibile rimuovere i vecchi record"No" - + Uploading to QRZ.com Carica su QRZ.com - + Cancel Cancella - - + + QLog Information Informazioni QLog - + %n QSO(s) uploaded. %n QSO caricato. @@ -7699,17 +7833,17 @@ Aggiornamento elenco club non riuscito. Impossibile rimuovere i vecchi record - + QLog Warning Avviso QLog - + Cannot upload the QSO(s): Impossibile caricare il/i QSO: - + No QSOs found to upload. Nessun QSO trovato da caricare. @@ -8606,22 +8740,22 @@ Aggiornamento elenco club non riuscito. Impossibile rimuovere i vecchi record Rig - + No Rig Profile selected Nessun Profilo Radio selezionato - + Initialization Error Errore di inizializzazione - + Internal Error Errore Interno - + Cannot open Rig Impossibile aprire Radio @@ -8654,7 +8788,7 @@ Aggiornamento elenco club non riuscito. Impossibile rimuovere i vecchi record - + PWR: %1W @@ -8662,22 +8796,22 @@ Aggiornamento elenco club non riuscito. Impossibile rimuovere i vecchi record Rotator - + No Rotator Profile selected Nessun Profilo Rotore selezionato - + Initialization Error Errore di inizializzazione - + Internal Error Errore Interno - + Cannot open Rotator Impossibile aprire Rotore @@ -8862,20 +8996,20 @@ Aggiornamento elenco club non riuscito. Impossibile rimuovere i vecchi record - - - - - - - - - - - - - - + + + + + + + + + + + + + + Add Aggiungi @@ -9473,14 +9607,14 @@ Aggiornamento elenco club non riuscito. Impossibile rimuovere i vecchi record - + Serial Seriale - - + + Network Rete @@ -9531,8 +9665,8 @@ Aggiornamento elenco club non riuscito. Impossibile rimuovere i vecchi record - - + + HamQTH @@ -9558,8 +9692,8 @@ Aggiornamento elenco club non riuscito. Impossibile rimuovere i vecchi record - - + + QRZ.com @@ -9701,333 +9835,333 @@ Aggiornamento elenco club non riuscito. Impossibile rimuovere i vecchi recordBande - + Modes Modi - + DXCC - + Wsjtx - + Raw UDP Forward Inoltro UDP non elaborato - + <p>List of IP addresses to which QLog forwards raw UDP WSJT-X packets.</p>The IP addresses are separated by a space and have the form IP:PORT <p>Elenco di indirizzi IP a cui QLog inoltra i pacchetti UDP WSJT-X grezzi.</p>Gli indirizzi IP sono separati da uno spazio e hanno la forma IP:PORT - - - - - + + + + + ex. 192.168.1.1:1234 192.168.2.1:1234 - + Port Porta - + Port where QLog listens an incoming traffic from WSJT-X Porta dove QLog ascolta il traffico in entrata da WSJT-X - + Join Multicast Unisciti a Multicast - + Enable/Disable Multicast option for WSJTX Abilita/Disabilita opzione Multicast per WSJTX - + Multicast Address Indirizzo Multicast - + Specify Multicast Address. <br>On some Linux systems it may be necessary to enable multicast on the loop-back network interface. Specificare l'indirizzo multicast. <br>Su alcuni sistemi Linux potrebbe essere necessario abilitare il multicast sull'interfaccia di rete loopback. - + TTL TTL - + Time-To-Live determines the range<br> over which a multicast packet is propagated in your intranet. Time-To-Live determina l'intervallo<br> entro il quale un pacchetto multicast viene propagato nella tua Intranet. - + Notifications Notifiche - + LogID - + <p>Assigned LogID to the current log.</p>The LogID is sent in the Network Nofitication messages as a unique instance identified.<p> The ID is generated automatically and cannot be changed</> <p>LogID assegnato al registro corrente.</p>Il LogID viene inviato nei messaggi di notifica di rete come un'istanza univoca identificata.<p> L'ID viene generato automaticamente e non può essere modificato</> - + DX Spots DX Spots - + <p> List of IP addresses to which QLog sends UDP notification packets with DX Cluster Spots.</p>The IP addresses are separated by a space and have the form IP:PORT <p>Elenco degli indirizzi IP a cui QLog invia pacchetti di notifiche UDP con DX Cluster Spots.</p>Gli indirizzi IP sono separati da uno spazio e hanno la forma IP:PORT - + Spot Alerts Allarmi Spot - + <p> List of IP addresses to which QLog sends UDP notification packets about user Spot Alerts.</p>The IP addresses are separated by a space and have the form IP:PORT <p>Elenco degli indirizzi IP a cui QLog invia pacchetti di notifiche UDP sugli Spot Alerts dell'utente.</p>Gli indirizzi IP sono separati da uno spazio e hanno la forma IP:PORT - + QSO Changes Modifiche al QSO - + <p> List of IP addresses to which QLog sends UDP notification packets about a new/updated/deleted QSO in the log.</p>The IP addresses are separated by a space and have the form IP:PORT <p> Elenco degli indirizzi IP a cui QLog invia pacchetti di notifica UDP relativi a un QSO nuovo/aggiornato/eliminato nel log.</p>Gli indirizzi IP sono separati da uno spazio e hanno la forma IP:PORT - + Wsjtx CQ Spots Wsjtx CQ Spots - + <p> List of IP addresses to which QLog sends UDP notification packets with WSJTX CQ Spots.</p>The IP addresses are separated by a space and have the form IP:PORT <p>Elenco degli indirizzi IP a cui QLog invia pacchetti di notifiche UDP con WSJTX CQ Spots.</p>Gli indirizzi IP sono separati da uno spazio e hanno la forma IP:PORT - + Shortcuts Scorciatoie - - + + Special - Omnirig Speciale - Omnirig - - + + Name Nome - + Report Report - - + + State Stato - + Start (MHz) Inizio (MHz) - + End (MHz) Fine (MHz) - + SAT Mode SAT Mode - - - + + + Disabled Disabilitato - - + + None Nessuno - - + + Hardware - - + + Software Software - - + + No No - - + + Even Pari - - + + Odd Dispari - - + + Mark Segna - - + + Space Spazio - + Dummy Fittizio - + Morse Over CAT Morse Over CAT - + WinKey v2 - + CWDaemon - + FLDigi - + Single Paddle Single Paddle - + IAMBIC A - + IAMBIC B - + Ultimate Definitivo - + Press <b>Modify</b> to confirm the profile changes or <b>Cancel</b>. Premi <b>Modifica</b> per confermare le modifiche al profilo o <b>Annulla</b>. - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + Modify Modifica - - - - - - - - - - + + + + + + + + + + Must not be empty Non deve essere vuoto - + Select File Seleziona File - + members Membri - + Required internet connection during application start Connessione Internet richiesta durante l'avvio dell'applicazione @@ -10035,22 +10169,22 @@ Aggiornamento elenco club non riuscito. Impossibile rimuovere i vecchi record ShortcutEditorModel - + Description Descrizione - + Shortcut Scorciatoia - + Conflict with a built-in shortcut Conflitto con una scorciatoia integrata - + Conflict with a user-defined shortcut Conflitto con una scorciatoia definita dall'utente @@ -10077,6 +10211,7 @@ Aggiornamento elenco club non riuscito. Impossibile rimuovere i vecchi recordStatisticsWidget + Statistics Statistiche @@ -10142,7 +10277,7 @@ Aggiornamento elenco club non riuscito. Impossibile rimuovere i vecchi record - + Band Banda @@ -10177,127 +10312,132 @@ Aggiornamento elenco club non riuscito. Impossibile rimuovere i vecchi record - + Year Anno - + Month Mese - + Day in Week Giorno della settimana - + Hour Ora - + Mode Modo - + Continent Continente - + Propagation Mode Modo di Propagazione - + Confirmed / Not Confirmed Confermato / Non Confermato - + Countries Nazioni - + Big Gridsquares Grandi quadrati della griglia - + Distance Distanza - + QSOs QSOs - + Confirmed/Worked Grids Griglia Confermata/Lavorata - + ODX ODX - + Sun Dom - + Mon Lun - + Tue Mar - + Wed Mer - + Thu Gio - + Fri Ven - + Sat Sab - + Not specified Non specificato - + Confirmed Confermato - + Not Confirmed Non confermato - + + Over 50000 QSOs. Display them? + Oltre 50000 QSO. Visualizzarli? + + + All Tutti @@ -10305,37 +10445,37 @@ Aggiornamento elenco club non riuscito. Impossibile rimuovere i vecchi record TCIRigDrv - + Rig 0 Radio 0 - + Rig 1 Radio 1 - + Rig 2 Radio 2 - + Rig 3 Radio 3 - + Error Occured C'è stato un'errore - + Rig status changed Stato della Radio cambiato - + Rig is not connected Radio non connessa @@ -10351,17 +10491,17 @@ Aggiornamento elenco club non riuscito. Impossibile rimuovere i vecchi record ToAllTableModel - + Time Ora - + Spotter Spotter - + Message Messaggio @@ -10397,47 +10537,47 @@ Aggiornamento elenco club non riuscito. Impossibile rimuovere i vecchi record WCYTableModel - + Time Ora - + K - + expK - + A - + R - + SFI - + SA - + GMF - + Au @@ -10445,27 +10585,27 @@ Aggiornamento elenco club non riuscito. Impossibile rimuovere i vecchi record WWVTableModel - + Time Ora - + SFI - + A - + K - + Info Info @@ -10591,37 +10731,37 @@ Aggiornamento elenco club non riuscito. Impossibile rimuovere i vecchi record WsjtxTableModel - + Callsign Indicativo - + Gridsquare Griglia - + Distance Distanza - + SNR - + Last Activity Ultima Attività - + Last Message Ultimo messaggio - + Member Membro @@ -10662,32 +10802,32 @@ Aggiornamento elenco club non riuscito. Impossibile rimuovere i vecchi record main - + Run with the specific namespace. Esegui con lo spazio dei nomi specifico. - + namespace spazio dei nomi - + Translation file - absolute or relative path and QM file name. File di traduzione: percorso assoluto o relativo e nome file QM. - + path/QM-filename percorso/nome file QM - + Set language. <code> example: 'en' or 'en_US'. Ignore environment setting. Imposta la lingua. <codice> esempio: 'en' o 'en_US'. Ignora l'impostazione dell'ambiente. - + code codice diff --git a/i18n/qlog_zh_CN.qm b/i18n/qlog_zh_CN.qm index 90572d8d..0b1985e0 100644 Binary files a/i18n/qlog_zh_CN.qm and b/i18n/qlog_zh_CN.qm differ diff --git a/i18n/qlog_zh_CN.ts b/i18n/qlog_zh_CN.ts index 32769f93..9af48992 100644 --- a/i18n/qlog_zh_CN.ts +++ b/i18n/qlog_zh_CN.ts @@ -108,44 +108,44 @@ 大洲 - - + + North America 北美洲 - - + + Africa 非洲 - - + + Antarctica 南极洲 - - + + South America 南美洲 - + Asia 亚洲 - + Europe 欧洲 - - + + Oceania 大洋洲 @@ -189,17 +189,17 @@ 规则 - + Add 添加 - + Edit 编辑 - + Remove 删除 @@ -251,6 +251,11 @@ Last Comment 最后备注 + + + Member + 成员 + AlertWidget @@ -363,117 +368,117 @@ - + DXCC DXCC - + ITU ITU - + WAC WAC - + WAZ WAZ - + WAS WAS - + WPX WPX - + IOTA IOTA - + POTA Hunter - + POTA Activator - + SOTA SOTA - + WWFF WWFF - + Done 完成 - + North America 北美 - + South America 南美 - + Europe 欧洲 - + Africa 非洲 - + Oceania 大洋洲 - + Asia 亚洲 - + Antarctica 南极洲 - + TOTAL Worked 全部已通联 - + TOTAL Confirmed 全部已确认 - + Confirmed 已确认 - + Worked 已通联 @@ -706,17 +711,17 @@ 清除 - + Rig must be connected 必须先连接设备 - + Word 单词 - + Whole 整句 @@ -814,27 +819,27 @@ CWKeyer - + No CW Keyer Profile selected 未选择 CW 电键配置文件 - + Initialization Error 初始化出错 - + Internal Error 内部错误 - + Connection Error 连接出错 - + Cannot open the Keyer connection 无法打开电键连接 @@ -842,39 +847,39 @@ CWWinKey2 - + Connected device is not WinKey 已连接的设备不是 WinKey - + Connected device is not WinKey v2 or newer 已连接的设备不是 WinKey v2 或者更新的版本 - + Cannot send Text to Rig 无法发送文字至设备 - - - + + + Keyer is not connected 电键未连接 - + Communication Error 通讯出错 - + Cannot set Keyer Speed 无法设置电键速度 - + Cannot stop Text Sending 无法停止文字发送 @@ -962,7 +967,7 @@ ClubLog - + Clublog Operation for Callsign %1 failed.<br>%2 呼号 %1 的 Clublog 操作失败。<br>%2 @@ -2838,151 +2843,151 @@ Data - + New Entity 新实体 - + New Band 新波段 - + New Mode 新模式 - + New Band&Mode 新波段模式(&M) - + New Slot 新组合 - + Confirmed 已确认 - + Worked 已通联 - + Hz Hz - + kHz kHz - + GHz GHz - + MHz MHz + + + + + + + Yes + + - Yes - - - - - - - - No - - + + Requested 已请求 - + Queued 排队中 - - + + Invalid 无效 - + Bureau 卡片局 - + Direct 直邮 - + Electronic 电子卡片 - - - - - + + + + + Blank 空白 - + Modified 已修改 - + Grayline 灰线 - + Other 其他 - + Short Path 短路径 - + Long Path 长路径 - + Not Heard 没听到过 - + Uncertain 不确定 @@ -3274,57 +3279,57 @@ DxTableModel - + Time 时间 - + Callsign 呼号 - + Frequency 频率 - + Mode 模式 - + Spotter 报告者 - + Comment 备注 - + Continent 大洲 - + Spotter Continent 报告者大洲 - + Band 波段 - + Member 成员 - + Country 国家/地区 @@ -3338,7 +3343,7 @@ - + Connect 连接 @@ -3368,155 +3373,185 @@ 控制台 - + + Full-text search + + + + + Search + + + + + Close Search + + + + Send DX Cluster Command 发送 DX 集群命令 - + Filter... 过滤器... - + Column Visibility... 列可见性... - + Connect on startup 启动时自动连接 - + Automatic connection after start 程序启动后自动连接服务器 - + Delete Server 删除服务器 - + DXC - Delete Server DXC - 删除服务器 - + Clear Password 清除密码 - + Keep Spots 保留报告 - + Spots are not cleared when connecting to a new DX Cluster. 连接至新的 DX 集群后,不清除旧的报告。 - + Clear 清除 - + Clear all data 清除所有数据 - + + Search... + + + + + DXC - Search + + + + Filter DXC DXC 过滤器 - + Spot Last QSO 报告最新的 QSO - + Send last QSO spot 发送最新的 QSO 报告 - + Show HF Stats 显示 HF 状态 - + Show VHF Stats 显示 VHF 状态 - + Show WCY 显示 WCY - + Show WWV 显示 WWV - + Which columns should be displayed 应该显示哪些列 - + Connecting... 正在连接... - + DX Cluster is temporarily unavailable DX 集群暂时不可用 - + DXC Server Error DXC 服务器出错 - + An invalid callsign 无效的呼号 - + DX Cluster Password DX 集群密码 - + Security Notice 安全注意 - + The password can be sent via an unsecured channel 密码可能通过不安全的通道发送 - + Server 服务器 - + Username 用户名 - + Disconnect 断开连接 + + + DX Cluster Command + + DxccTableModel @@ -3544,7 +3579,7 @@ DxccTableWidget - + Mode 模式 @@ -4032,40 +4067,40 @@ "否" - + Uploading to HRDLOG 上传至 HRDLOG - + Cancel 取消 - - + + QLog Information QLog 信息 - + %n QSO(s) uploaded. %n QSO(s) 已上传。 - + QLog Warning QLog告警 - + Cannot upload the QSO(s): 无法上传该 QSO(s): - + No QSOs found to upload. 没有找到可上传的 QSOs。 @@ -4081,87 +4116,162 @@ HamlibRigDrv - + None - + CAT - + DTR - + RTS - - + + Initialization Error 初始化出错 - + Cannot set PTT Type - + Cannot set PTT Share - + Unsupported Rig Driver 不支持的设备驱动 - + + Rig Open Error + + + + Set Frequency Error 设置频率出错 - + + Set Mode Error + + + + Set PTT Error 设置 PTT 出错 - + + Cannot sent Morse + + + + + Cannot stop Morse + + + + + Get PTT Error + + + + Get Frequency Error 获取频率出错 - + Get Mode Error 获取模式出错 + + + Get VFO Error + + + + + Get PWR Error + + + + + Get PWR (power2mw) Error + + + + + Get RIT Function Error + + + + + Get RIT Error + + + + + Get XIT Function Error + + + + + Get XIT Error + + + + + Get KeySpeed Error + + + + + Set KeySpeed Error + + HamlibRotDrv - - + + Initialization Error 初始化出错 - + Unsupported Rotator Driver 不支持的云台驱动 - + + Rot Open Error + + + + Set Possition Error 设置方位出错 - + Get Possition Error 获取方位出错 @@ -4220,7 +4330,7 @@ - + The value is used when an input record does not contain the ADIF value 当输入记录不包含ADIF值时使用该值 @@ -4241,99 +4351,99 @@ - + Comment 备注 - + &Import 导入(&I) - + Select File 选择文件 - - + + The values below will be used when an input record does not contain the ADIF values 当输入记录不包含ADIF值时,将使用下面的值 - + <p><b>In-Log QSO:</b></p><p> <p><b>在日志 QSO:</b></p><p> - + <p><b>Importing:</b></p><p> <p><b>导入中:</b></p><p> - + Duplicate QSO 重复的 QSO - + <p>Do you want to import duplicate QSO?</p>%1 %2 <p>是否要导入重复的QSO?</p> %1 %2 - + Save to File 保存至文件 - + QLog Import Summary QLog 导入摘要 - + Import date 导入日期 - + Imported file 导入的文件 - + Imported: %n contact(s) 已导入: %n 通联记录 - + Warning(s): %n 告警: %n - + Error(s): %n 错误: %n - + Details 详情 - + Import Result 导入结果 - + Save Details... 保存详情... @@ -4599,48 +4709,61 @@ LogFormat - + + + Cannot find My DXCC Entity Info + + + + A minimal set of fields not present (start_time, call, band, mode, station_callsign) 需要提供最小字段集 (start_time, call, band, mode, station_callsign) - + Outside the selected Date Range 超出指定的日期范围 - - + + Duplicate 重复 - + Cannot find DXCC Entity Info 无法找到 DXCC 实体信息 - - Cannot find own DXCC Entity Info - 无法找到自己的 DXCC 实体信息 + + DXCC Info is missing + + + + + + + no Station Callsign present + - + Cannot insert to database 无法插入到数据库中 - + Imported 已导入 - + Error 错误 - + Warning 告警 @@ -5540,20 +5663,20 @@ - + Club 俱乐部 - + User Filter 用户过滤器 - - + + Delete 删除 @@ -5619,55 +5742,55 @@ - + Delete the selected contacts? 删除选中的联系人? - + Clublog's <b>Immediately Send</b> supports only one-by-one deletion<br><br>Do you want to continue despite the fact<br>that the DELETE operation will not be sent to Clublog? Clublog's <b>Immediately Send</b> supports only one-by-one deletion<br><br>Do you want to continue despite the fact<br>that the DELETE operation will not be sent to Clublog? - + Deleting QSOs 删除 QSO - + Update 更新 - + By updating, all selected rows will be affected.<br>The value currently edited in the column will be applied to all selected rows.<br><br>Do you want to edit them? 通过更新,所有选定的行都将受到影响。<br>当前在列中编辑的值将应用于所有选定的行。<br><br>您想要编辑他们吗? - + Count: %n 计数:%n - + Downloading eQSL Image 正在下载 eQSL 图片 - - + + Cancel 取消 - + QLog Error QLog 错误 - + eQSL Download Image failed: eQSL 图片下载失败: @@ -6040,7 +6163,7 @@ 不能为空 - + Unsaved 未保存 @@ -6383,78 +6506,78 @@ 设备 - PTT ON/OFF - + Not enabled for non-Fusion style 非融合样式不允许使用 - + Press to tune the alert 按下调节提醒 - + Clublog Immediately Upload Error Clublog 立即上传出错 - - + + <b>Error Detail:</b> <b>错误详情:</b> - + Classic 经典 - - - - - + + + + + QLog Warning QLog 告警 - + LoTW is not configured properly.<p> Please, use <b>Settings</b> dialog to configure it.</p> LoTW 配置不正确。<p>请使用<b>设置</b>对话框进行配置。</p> - + eQSL is not configured properly.<p> Please, use <b>Settings</b> dialog to configure it.</p> eQSL 配置不正确。<p>请使用<b>设置</b>对话框进行配置。</p> - + Clublog is not configured properly.<p> Please, use <b>Settings</b> dialog to configure it.</p> Clublog 配置不正确。<p>请使用<b>设置</b>对话框进行配置。</p> - + HRDLog is not configured properly.<p> Please, use <b>Settings</b> dialog to configure it.</p> HRDLog 配置不正确。<p>请使用<b>设置</b>对话框进行配置。</p> - + QRZ.com is not configured properly.<p> Please, use <b>Settings</b> dialog to configure it.</p> QRZ.com 配置不正确。<p>请使用<b>设置</b>对话框进行配置。</p> - + <h1>QLog %1</h1><p>&copy; 2019 Thomas Gatzweiler DL2IC<br/>&copy; 2021-2024 Ladislav Foldyna OK1MLG</p><p>Based on Qt %2<br/>%3<br/>%4<br/>%5</p><p>Icon by <a href='http://www.iconshock.com'>Icon Shock</a><br />Satellite images by <a href='http://www.nasa.gov'>NASA</a><br />ZoneDetect by <a href='https://github.com/BertoldVdb/ZoneDetect'>Bertold Van den Bergh</a><br />TimeZone Database by <a href='https://github.com/evansiroky/timezone-boundary-builder'>Evan Siroky</a> <h1>QLog %1</h1><p>&copy; 2019 Thomas Gatzweiler DL2IC<br/>&copy; 2021-2024 Ladislav Foldyna OK1MLG</p><p>Based on Qt %2<br/>%3<br/>%4<br/>%5</p><p>Icon by <a href='http://www.iconshock.com'>Icon Shock</a><br />Satellite images by <a href='http://www.nasa.gov'>NASA</a><br />ZoneDetect by <a href='https://github.com/BertoldVdb/ZoneDetect'>Bertold Van den Bergh</a><br />TimeZone Database by <a href='https://github.com/evansiroky/timezone-boundary-builder'>Evan Siroky</a> - + About 关于 - + N/A N/A @@ -6521,52 +6644,52 @@ Migration - + DXCC Entities DXCC 实体 - + Sats Info 卫星信息 - + SOTA Summits SOTA 山峰 - + WWFF Records WWFF 记录 - + IOTA Records IOTA 记录 - + POTA Records POTA 记录 - + Membership Directory Records 会员名录记录 - + List of Values 值列表 - + Updating 更新 - + Update Failed 更新失败 @@ -6599,320 +6722,320 @@ MHz - + 80m 80m - + RSTs RST发 - + RSTr RST收 - + 59 59 - + Mode 模式 - + Lookup the call on the web. The query URL can be changed in Settings -> Callbook 在网络上查找呼号。查询 URL 可以在 <b>设置 -> 电台黄页</b> 中更改 - + Web 网站 - + Time On 开始时间 - + Date 日期 - + Save 保存 - + Duration 周期 - + Reset 重置 - + Info 信息 - + &Details 详情(&D) - + QSL Send Status QSL 发送状态 - - + + Paper 卡片 - - - + + + <b>Yes</b> - an outgoing QSL card has been sent; the QSO has been uploaded to, and accepted by, the online service<br/><b>No</b> - do not send an outgoing QSL card; do not upload the QSO to the online service<br/><b>Requested</b> - the contacted station has requested a QSL card; the contacted station has requested the QSO be uploaded to the online service<br/><b>Queued</b> - an outgoing QSL card has been selected to be sent; a QSO has been selected to be uploaded to the online service<br/> <b>是</b> -已发出 QSL 卡; QSO 已上传至在线服务<br/><b>否</b> -不发送 QSL 卡;<br/><b>已请求</b> -被联系站点已请求一张 QSL 卡; 被联系站点已请求将 QSO 上传到在线服务<br/><b>排队</b> 已选择要发送的 QSL 卡; QSO 已上传至网上服务<br/> - + LoTW LoTW - + eQSL eQSL - + QSL Send via QSL 发送通过 - + QSL via QSL 通过 - + Propagation Mode 传播模式 - + D&XCC D&XCC - + M&y Station 我的电台(&Y) - + Station 电台 - + Rig 设备 - + Antenna 天线 - + Power 功率 - + Blank 空白 - + W W - + My &Notes 我的笔记(&N) - + Member: 成员: - - - + + + No - - - + + + Yes - - - + + + Requested 已请求 - - - + + + Queued 排队中 - - - + + + Ignored 已忽视 - + Bureau 卡片局 - + Direct 直邮 - + Electronic 电子卡片 - + QLog Error QLog错误 - + Callbook login failed 电台黄页登陆失败 - + LP - + New Entity! 新实体! - + New Band! 新波段! - + New Mode! 新模式! - + New Band & Mode! 新波段与模式! - + New Slot! 新组合! - + Worked 已通联 - + Confirmed 已确认 - + GE GE - + GM GM - + GA GA - + m m - + Callbook search is active 电台黄页搜索可用 - + Callbook search is inactive 电台黄页搜索不可用 - + two or four adjacent Maidenhead grid locators, each four characters long, (ex. EN98,FM08,EM97,FM07) 两个或四个相邻的梅登黑德网格定位器,每个四个字符长,(例如 EN98, FM08, EM97, FM07) - + the contacted station's DARC DOK (District Location Code) (ex. A01) 联络电台的DARC DOK (地区位置代码) (例如 A01) - + World Wide Flora & Fauna 世界动植物 (可选参数) - + Special Activity Group 特别活动或兴趣团体名称 - + Special Activity Group Information 特别活动或兴趣团体信息 @@ -7091,7 +7214,7 @@ QCoreApplication - + QLog Help QLog 帮助 @@ -7099,123 +7222,123 @@ QMessageBox - - - + + + QLog Critical Qlog 临界值 - + Cannot save a password for %1 to the Credential Store 无法将 %1 的密码保存到凭据数据库 - + Cannot get a password for %1 from the Credential Store 无法从凭据数据库获取 %1 密码 - - - - - + + + + + - - - + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + QLog Warning QLog 告警 - + Club List Update failed. Cannot remove old records 俱乐部列表更新失败。无法删除旧记录 - + Club List Update failed. Cannot plan new downloads 俱乐部列表更新失败。无法规划新下载 - + Unexpected Club List download. Canceling next downloads 无法预料的俱乐部列表下载。取消下次下载 - + Unexpected Club List content for 未知的俱乐部列表内容 - + Network error. Cannot download Club List for 网络错误。无法下载俱乐部列表 - - - - - + + + + + - + - - + + QLog Error QLog 出错 - + QLog is already running 已经有 QLog 实例正在运行 - + Could not connect to database. 无法连接至数据库。 - + Could not export a QLog database to ADIF as a backup.<p>Try to export your log to ADIF manually 无法导出 QLog 数据库至 ADIF 备份。<p>请尝试手动导出您的日志至 ADIF - + Database migration failed. 数据库迁移失败。 - + Could not connect to database (2). 无法连接至数据库。 @@ -7250,33 +7373,33 @@ 无法更新告警规则 - + DXC Server Name Error DXC 服务器名称错误 - + DXC Server address must be in format<p><b>[username@]hostname:port</b> (ex. hamqth.com:7300)</p> DXC 服务器地址格式必须为<p><b>[用户名@]主机名:端口</b> (例. hamqth.com:7300)</p> - + DX Cluster Password DX 集群密码 - + Invalid Password 无效的密码 - + DXC Server Connection Error DXC 服务器连接出错 - + Filename is empty 文件名为空 @@ -7314,22 +7437,22 @@ 布局名称已存在。 - + <b>Rig Error:</b> <b>设备出错:</b> - + <b>Rotator Error:</b> <b>旋转云台出错:</b> - + <b>CW Keyer Error:</b> <b>CW 键控器出错:</b> - + Your callsign is empty. Please, set your Station Profile 你的呼号为空。请先设置台站配置文件 @@ -7349,83 +7472,83 @@ 无法更新 QSO 过滤规则匹配类型 - - - + + Please, define at least one Station Locations Profile 请至少定义一个站点配置文件 - + WSJTX Multicast is enabled but the Address is not a multicast address. WSJTX 多播已启用,但地址不是多播地址。 - + Rig port must be a valid COM port.<br>For Windows use COMxx, for unix-like OS use a path to device 设备端口必须是一个有效的 COM 端口。<br>Windows 使用 COMxxx,对于unix-like OS 使用设备路径 - + Rig PTT port must be a valid COM port.<br>For Windows use COMxx, for unix-like OS use a path to device - + <b>TX Range</b>: Max Frequency must not be 0. <b>TX 范围</b>: 最大频率不能为 0。 - + <b>TX Range</b>: Max Frequency must not be under Min Frequency. <b>TX 范围</b>: 最大频率不能低于最小频率。 - + Rotator port must be a valid COM port.<br>For Windows use COMxx, for unix-like OS use a path to device 旋转云台端口必须是一个有效的 COM 端口。<br>对于Windows 使用 COMxxx,对于unix-like OS 使用设备路径 - + CW Keyer port must be a valid COM port.<br>For Windows use COMxx, for unix-like OS use a path to device CW 键控器端口必须是一个有效的 COM 端口。<br>对于Windows 使用 COMxxx,对于unix-like OS 使用设备路径 - + Cannot change the CW Keyer Model to <b>Morse over CAT</b><br>No Morse over CAT support for Rig(s) <b>%1</b> 无法将 CW 键控器模型改为 <b>Morse over CAT</b><br>设备 <b>%1</b>不支持Morse over CAT - + Cannot delete the CW Keyer Profile<br>The CW Key Profile is used by Rig(s): <b>%1</b> 无法删除 CW 键控器配置文件<br>本 CW 键控器配置文件正在被设备<b>%1</b>使用 - + Callsign has an invalid format 呼号格式无效 - + Gridsquare has an invalid format 网格坐标格式无效 - + VUCC Grids have an invalid format (must be 2 or 4 Gridsquares separated by ',') VUCC 网格格式无效 (必须是 2 或 4 个被 ',' 分隔的网格坐标) - + Country must not be empty 国家/地区 不能为空 - + CQZ must not be empty CQ 分区不能为空 - + ITU must not be empty ITU 不能为空 @@ -7444,162 +7567,162 @@ - - + + Connection Refused 连接被拒绝 - - + + Host closed the connection 主机关闭连接 - - + + Host not found 找不到主机 - - + + Timeout 超时 - - + + Network Error 网络错误 - - + + Internal Error 内部错误 - + Opening Database 打开数据库 - + Backuping Database 备份数据库 - + Migrating Database 迁移数据库 - + Starting Application 启动应用程序 - + My Rig 我的设备 - + Logging Station Callsign 记录电台呼号 - + My Gridsquare 我的网格坐标 - + My Name 我的姓名 - + My City 我的城市 - + My IOTA 我的 IOTA - + My SOTA 我的 SOTA - + My Special Interest Activity 我的特殊兴趣活动 - + My Spec. Interes Activity Info 我的特殊兴趣活动信息 - + My VUCC Grids 我的 VUCC 网格 - + My WWFF 我的 WWFF - + My POTA Ref 我的 POTA 编号 - + My ITU 我的 ITU - + My CQZ 我的 CQ 分区 - + My DXCC 我的 DXCC - + Cannot connect to DXC Server <p>Reason <b>: 无法连接至 DXC 服务器 <p>原因 <b>: - + <b>Imported</b>: %n contact(s) <b>已导入</b>: %n 通联 - + <b>Warning(s)</b>: %n <b>告警</b>: %n - + <b>Error(s)</b>: %n <b>错误</b>: %n @@ -7662,40 +7785,40 @@ "否" - + Uploading to QRZ.com 上传至 QRZ.com - + Cancel 取消 - - + + QLog Information QLog 信息 - + %n QSO(s) uploaded. %n QSO(s) 已上传。 - + QLog Warning QLog 告警 - + Cannot upload the QSO(s): 无法上传该 QSO(s): - + No QSOs found to upload. 没有找到可上传的 QSOs。 @@ -8593,22 +8716,22 @@ Rig - + No Rig Profile selected 未选择设备配置文件 - + Initialization Error 初始化出错 - + Internal Error 内部错误 - + Cannot open Rig 无法打开设备 @@ -8641,7 +8764,7 @@ XIT: 0.00000 MHz - + PWR: %1W 功率: %1W @@ -8649,22 +8772,22 @@ Rotator - + No Rotator Profile selected 未选择旋转云台配置文件 - + Initialization Error 初始化出错 - + Internal Error 内部错误 - + Cannot open Rotator 无法打开云台 @@ -8849,20 +8972,20 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + Add 添加 @@ -9433,7 +9556,7 @@ QSO 将立即上传 - + Shortcuts 快捷键 @@ -9445,14 +9568,14 @@ - + Serial 串口 - - + + Network 网络 @@ -9528,8 +9651,8 @@ - - + + HamQTH HamQTH @@ -9555,8 +9678,8 @@ - - + + QRZ.com QRZ.com @@ -9693,328 +9816,328 @@ 波段 - + Modes 模式 - + DXCC DXCC - + Wsjtx Wsjtx - + Raw UDP Forward 原始UDP转发 - + <p>List of IP addresses to which QLog forwards raw UDP WSJT-X packets.</p>The IP addresses are separated by a space and have the form IP:PORT <p> QLog转发UDP WSJT-X原始报文的IP地址列表。</p> IP地址之间用空格分隔,格式为IP:PORT - - - - - + + + + + ex. 192.168.1.1:1234 192.168.2.1:1234 例. 192.168.1.1:1234 192.168.2.1:1234 - + Port 端口 - + Port where QLog listens an incoming traffic from WSJT-X QLog 监听来自 WSJT-X 的传入数据流的端口 - + Join Multicast 加入多播 - + Enable/Disable Multicast option for WSJTX 启用/禁用 WSJTX 的多播选项 - + Multicast Address 多播地址 - + Specify Multicast Address. <br>On some Linux systems it may be necessary to enable multicast on the loop-back network interface. 指定组播地址。<br>在某些Linux系统上,可能需要在环路网络接口上启用多播。 - + TTL TTL - + Time-To-Live determines the range<br> over which a multicast packet is propagated in your intranet. 生存时间 (Time-To-Live) 决定了组播数据包在内部网中传播的范围。 - + Notifications 通知 - + LogID 日志ID - + <p>Assigned LogID to the current log.</p>The LogID is sent in the Network Nofitication messages as a unique instance identified.<p> The ID is generated automatically and cannot be changed</> <p>为当前日志分配 LogID。</p> LogID作为唯一实例标识在网络通知消息中发送。<p>该ID为自动生成,不可手动修改</> - + DX Spots DX 报告 - + <p> List of IP addresses to which QLog sends UDP notification packets with DX Cluster Spots.</p>The IP addresses are separated by a space and have the form IP:PORT <p> QLog 发送 DX 集群报告 UDP 通知报文的 IP 地址列表。</p> IP 地址之间用空格分隔,格式为 IP:PORT - + Spot Alerts 报告预警 - + <p> List of IP addresses to which QLog sends UDP notification packets about user Spot Alerts.</p>The IP addresses are separated by a space and have the form IP:PORT <p> QLog 向用户发送 报告预警 UDP 报文的 IP 地址列表。</p> IP 地址之间用空格分隔,格式为 IP:PORT - + QSO Changes QSO 变更 - + <p> List of IP addresses to which QLog sends UDP notification packets about a new/updated/deleted QSO in the log.</p>The IP addresses are separated by a space and have the form IP:PORT <p>日志中 新增/更新/删 除QSO时,QLog 向其发送 UDP 通知报文的 IP 地址列表。</p> IP地址之间用空格分隔,格式为 IP:PORT - + Wsjtx CQ Spots WSJTX CQ 报告 - + <p> List of IP addresses to which QLog sends UDP notification packets with WSJTX CQ Spots.</p>The IP addresses are separated by a space and have the form IP:PORT <p> QLog 通过 WSJTX CQ 报告 发送 UDP 通知报文的 IP 地址列表。</p> IP地址之间用空格分隔,格式为 IP:PORT - - + + Special - Omnirig 特别的 - Ominirig - - + + Name 姓名 - + Report 报告 - - + + State 状态 - + Start (MHz) 起始(MHz) - + End (MHz) 结束(MHz) - + SAT Mode 卫星模式 - - - + + + Disabled 禁用 - - + + None - - + + Hardware 硬件 - - + + Software 软件 - - + + No - - + + Even 偶校验 - - + + Odd 奇校验 - - + + Mark 1校验 - - + + Space 0校验 - + Dummy 虚拟 - + Morse Over CAT Morse Over CAT - + WinKey v2 WinKey v2 - + CWDaemon CWDaemon - + FLDigi FLDigi - + Single Paddle 单桨电键 - + IAMBIC A IAMBIC A - + IAMBIC B IAMBIC B - + Ultimate Ultimate - + Press <b>Modify</b> to confirm the profile changes or <b>Cancel</b>. 按<b>修改</b>确认更改配置文件或按<b>取消</b>。 - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + Modify 修改 - - - - - - - - - - + + + + + + + + + + Must not be empty 不能为空 - + Select File 选择文件 - + members 成员 - + Required internet connection during application start 在应用程序启动时需要互联网连接 @@ -10022,22 +10145,22 @@ ShortcutEditorModel - + Description 描述 - + Shortcut 快捷键 - + Conflict with a built-in shortcut 与内置快捷键发生冲突 - + Conflict with a user-defined shortcut 与用户定义快捷键发生冲突 @@ -10064,6 +10187,7 @@ StatisticsWidget + Statistics 统计分析 @@ -10129,7 +10253,7 @@ - + Band 波段 @@ -10164,127 +10288,132 @@ about:blank - + Year - + Month - + Day in Week 星期几 - + Hour 小时 - + Mode 模式 - + Continent 大洲 - + Propagation Mode 传播模式 - + Confirmed / Not Confirmed 已确认/未确认 - + Countries 国家/地区 - + Big Gridsquares 大网格坐标 - + Distance 距离 - + QSOs QSO - + Confirmed/Worked Grids 确认/已通联 网格 - + ODX ODX - + Sun 星期日 - + Mon 星期一 - + Tue 星期二 - + Wed 星期三 - + Thu 星期四 - + Fri 星期五 - + Sat 星期六 - + Not specified 未指定 - + Confirmed 已确认 - + Not Confirmed 未确认 - + + Over 50000 QSOs. Display them? + + + + All 全部 @@ -10292,37 +10421,37 @@ TCIRigDrv - + Rig 0 设备 0 - + Rig 1 设备 1 - + Rig 2 设备 2 - + Rig 3 设备 3 - + Error Occured 发生错误 - + Rig status changed 设备状态已更改 - + Rig is not connected 设备未连接 @@ -10338,17 +10467,17 @@ ToAllTableModel - + Time 时间 - + Spotter 报告者 - + Message 消息 @@ -10384,47 +10513,47 @@ WCYTableModel - + Time 时间 - + K K - + expK expK - + A A - + R R - + SFI SFI - + SA SA - + GMF GMF - + Au Au @@ -10432,27 +10561,27 @@ WWVTableModel - + Time 时间 - + SFI SFI - + A A - + K K - + Info 信息 @@ -10578,37 +10707,37 @@ WsjtxTableModel - + Callsign 呼号 - + Gridsquare 网格坐标 - + Distance 距离 - + SNR SNR - + Last Activity 前次活跃 - + Last Message 前次消息 - + Member 成员 @@ -10649,32 +10778,32 @@ main - + Run with the specific namespace. 使用特定的命名空间运行。 - + namespace 命名空间 - + Translation file - absolute or relative path and QM file name. 翻译文件 - 绝对或相对路径及 QM 文件名。 - + path/QM-filename 路径/QM-文件名 - + Set language. <code> example: 'en' or 'en_US'. Ignore environment setting. 设置语言。<code> 示例: 'en' 或 'en_US'。忽略环境设置。 - + code 代码 diff --git a/installer/config/config.xml b/installer/config/config.xml index a3c67372..19e7cb11 100644 --- a/installer/config/config.xml +++ b/installer/config/config.xml @@ -1,7 +1,7 @@ QLog - 0.38.0 + 0.39.0 QLog OK1MLG QLog diff --git a/installer/packages/de.dl2ic.qlog/meta/package.xml b/installer/packages/de.dl2ic.qlog/meta/package.xml index 56760841..c00cf7b5 100644 --- a/installer/packages/de.dl2ic.qlog/meta/package.xml +++ b/installer/packages/de.dl2ic.qlog/meta/package.xml @@ -2,8 +2,8 @@ QLog The QLog main application. - 0.38.0-1 - 2024-08-29 + 0.39.0-1 + 2024-10-05 true true diff --git a/logformat/AdiFormat.cpp b/logformat/AdiFormat.cpp index 0de9945d..d5b4c1d6 100644 --- a/logformat/AdiFormat.cpp +++ b/logformat/AdiFormat.cpp @@ -510,8 +510,8 @@ void AdiFormat::preprocessINTLField(const QString &fieldName, // NOTE: If modify this, modify also function below!!!! - QVariant fld = contact.value(fieldName); - QVariant fldIntl = contact.value(fieldIntlName); + const QVariant &fld = contact.value(fieldName); + const QVariant &fldIntl = contact.value(fieldIntlName); /* In general, it is a hack because ADI must not contain * _INTL fields. But some applications generate _INTL fields in ADI files @@ -547,8 +547,8 @@ void AdiFormat::preprocessINTLField(const QString &fieldName, FCT_IDENTIFICATION; // NOTE: If modify this, modify also function above!!!! - QVariant fld = contact.value(fieldName); - QVariant fldIntl = contact.value(fieldIntlName); + const QVariant &fld = contact.value(fieldName); + const QVariant &fldIntl = contact.value(fieldIntlName); /* In general, it is a hack because ADI must not contain * _INTL fields. But some applications generate _INTL fields in ADI files @@ -603,6 +603,18 @@ bool AdiFormat::readContact(QMap& contact) return false; } +AdiFormat::AdiFormat(QTextStream &stream) : + LogFormat(stream) +{ + FCT_IDENTIFICATION; + +#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) + stream.setEncoding(QStringConverter::Latin1); +#else + stream.setCodec("ISO 8859-1"); +#endif +} + bool AdiFormat::importNext(QSqlRecord& record) { FCT_IDENTIFICATION; diff --git a/logformat/AdiFormat.h b/logformat/AdiFormat.h index 3bc25c77..71b06205 100644 --- a/logformat/AdiFormat.h +++ b/logformat/AdiFormat.h @@ -8,7 +8,7 @@ class AdiFormat : public LogFormat { public: - explicit AdiFormat(QTextStream& stream) : LogFormat(stream) {} + explicit AdiFormat(QTextStream& stream); virtual bool importNext(QSqlRecord& ) override; @@ -22,11 +22,9 @@ class AdiFormat : public LogFormat static void preprocessINTLFields(T &contact) { { - QStringList fieldMappingList = fieldname2INTLNameMapping.keys(); - for ( const QString& fieldName : qAsConst(fieldMappingList) ) - { + const QStringList &fieldMappingList = fieldname2INTLNameMapping.keys(); + for ( const QString& fieldName : fieldMappingList ) preprocessINTLField(fieldName, fieldname2INTLNameMapping.value(fieldName), contact); - } } } diff --git a/logformat/AdxFormat.cpp b/logformat/AdxFormat.cpp index 08f93fda..cfe95ac0 100644 --- a/logformat/AdxFormat.cpp +++ b/logformat/AdxFormat.cpp @@ -3,7 +3,6 @@ #include "logformat/AdxFormat.h" #include "logformat/AdiFormat.h" #include "core/debug.h" -#include "data/Data.h" MODULE_IDENTIFICATION("qlog.logformat.adxformat"); diff --git a/logformat/CSVFormat.cpp b/logformat/CSVFormat.cpp index 3b86c163..bd3bc695 100644 --- a/logformat/CSVFormat.cpp +++ b/logformat/CSVFormat.cpp @@ -32,10 +32,10 @@ void CSVFormat::exportEnd() FCT_IDENTIFICATION; // Print Header - QMap sorts keys automatically - QList headerKeys(header.keys()); + const QList headerKeys(header.keys()); QStringList row; - for ( const QString& headerField : qAsConst(headerKeys) ) + for ( const QString& headerField : headerKeys ) { row << headerField; } @@ -43,11 +43,11 @@ void CSVFormat::exportEnd() stream << row.join(delimiter) << "\n"; // Normalize and print exported records - for ( const QHash &record : qAsConst(exportedRecords) ) + for ( const QHash &record : static_cast>&>(exportedRecords) ) { row.clear(); - for ( const QString& headerField : qAsConst(headerKeys) ) + for ( const QString& headerField : headerKeys ) { row << record.value(headerField); } diff --git a/logformat/LogFormat.cpp b/logformat/LogFormat.cpp index 8f4c9c14..1938ef6b 100644 --- a/logformat/LogFormat.cpp +++ b/logformat/LogFormat.cpp @@ -239,6 +239,7 @@ void LogFormat::setDuplicateQSOCallback(duplicateQSOBehaviour (*func)(QSqlRecord #define RECORDIDX(a) ( (a) - 1 ) unsigned long LogFormat::runImport(QTextStream& importLogStream, + const StationProfile *defaultStationProfile, unsigned long *warnings, unsigned long *errors) { @@ -265,6 +266,7 @@ unsigned long LogFormat::runImport(QTextStream& importLogStream, return 0; } + QSqlDatabase::database().transaction(); QSqlTableModel model; @@ -272,7 +274,68 @@ unsigned long LogFormat::runImport(QTextStream& importLogStream, model.removeColumn(model.fieldIndex("id")); QSqlRecord record = model.record(); duplicateQSOBehaviour dupSetting = LogFormat::ASK_NEXT; -; + + auto setIfEmpty = [&](int column, const QString &value) + { + if ( record.value(RECORDIDX(column)).toString().isEmpty() && !value.isEmpty() ) + record.setValue(RECORDIDX(column), value); + }; + + auto setMyDefaultProfile = [&]() + { + setIfEmpty(LogbookModel::COLUMN_MY_DXCC, QString::number(defaultStationProfile->dxcc)); + setIfEmpty(LogbookModel::COLUMN_STATION_CALLSIGN, defaultStationProfile->callsign); + setIfEmpty(LogbookModel::COLUMN_MY_GRIDSQUARE, defaultStationProfile->locator); + setIfEmpty(LogbookModel::COLUMN_MY_NAME, defaultStationProfile->operatorName); + setIfEmpty(LogbookModel::COLUMN_MY_CITY_INTL, defaultStationProfile->qthName); + setIfEmpty(LogbookModel::COLUMN_MY_CITY, Data::removeAccents(defaultStationProfile->qthName)); + setIfEmpty(LogbookModel::COLUMN_MY_IOTA, defaultStationProfile->iota); + setIfEmpty(LogbookModel::COLUMN_MY_POTA_REF, defaultStationProfile->pota); + setIfEmpty(LogbookModel::COLUMN_MY_SOTA_REF, defaultStationProfile->sota); + setIfEmpty(LogbookModel::COLUMN_MY_SIG_INTL, defaultStationProfile->sig); + setIfEmpty(LogbookModel::COLUMN_MY_SIG, Data::removeAccents(defaultStationProfile->sig)); + setIfEmpty(LogbookModel::COLUMN_MY_SIG_INFO_INTL, defaultStationProfile->sigInfo); + setIfEmpty(LogbookModel::COLUMN_MY_SIG_INFO, Data::removeAccents(defaultStationProfile->sigInfo)); + setIfEmpty(LogbookModel::COLUMN_MY_VUCC_GRIDS, defaultStationProfile->vucc); + setIfEmpty(LogbookModel::COLUMN_MY_ITU_ZONE, QString::number(defaultStationProfile->ituz)); + setIfEmpty(LogbookModel::COLUMN_MY_CQ_ZONE, QString::number(defaultStationProfile->cqz)); + setIfEmpty(LogbookModel::COLUMN_MY_COUNTRY_INTL, defaultStationProfile->country); + setIfEmpty(LogbookModel::COLUMN_MY_COUNTRY, Data::removeAccents(defaultStationProfile->country)); + }; + + auto setMyEntity = [&](const DxccEntity &myEntity) + { + // force overwrite + record.setValue(RECORDIDX(LogbookModel::COLUMN_MY_DXCC), myEntity.dxcc); + record.setValue(RECORDIDX(LogbookModel::COLUMN_MY_COUNTRY), Data::removeAccents(myEntity.country)); + record.setValue(RECORDIDX(LogbookModel::COLUMN_MY_COUNTRY_INTL), myEntity.country); + + // other DXCC related values ​​are not closely related to DXCC value and could have been filled + // therefore check if it is present or not. + setIfEmpty(LogbookModel::COLUMN_MY_ITU_ZONE, QString::number(myEntity.ituz)); + setIfEmpty(LogbookModel::COLUMN_MY_CQ_ZONE, QString::number(myEntity.cqz)); + }; + + auto lookupAndSetMyEntityByCallsign = [&] (const QString& recordMyDXCC) + { + const DxccEntity &myEntity = Data::instance()->lookupDxcc(recordMyDXCC); + + if ( myEntity.dxcc == 0 ) // My DXCC not found + { + writeImportLog(importLogStream, + WARNING_SEVERITY, + errors, + warnings, + processedRec, + record, + tr("Cannot find My DXCC Entity Info")); + } + else + { + setMyEntity(myEntity); + } + }; + if ( !insertQuery.prepare( QSqlDatabase::database().driver()->sqlStatement(QSqlDriver::InsertStatement, "contacts", record, @@ -290,6 +353,10 @@ unsigned long LogFormat::runImport(QTextStream& importLogStream, processedRec++; + /* Compute the Band if missing + * Band is one of the mandatory fields + */ + if ( record.value(RECORDIDX(LogbookModel::COLUMN_BAND)).toString().isEmpty() && !record.value(RECORDIDX(LogbookModel::COLUMN_FREQUENCY)).toString().isEmpty() ) { @@ -311,17 +378,17 @@ unsigned long LogFormat::runImport(QTextStream& importLogStream, if ( !start_time.isValid() || call.toString().isEmpty() || band.toString().isEmpty() - || mode.toString().isEmpty() - || mycall.toString().isEmpty() ) + || mode.toString().isEmpty()) { writeImportLog(importLogStream, ERROR_SEVERITY, + errors, + warnings, processedRec, record, tr("A minimal set of fields not present (start_time, call, band, mode, station_callsign)")); qWarning() << "Import does not contain minimal set of fields (start_time, call, band, mode, station_callsign)"; qCDebug(runtime) << record; - (*errors)++; continue; } @@ -336,10 +403,11 @@ unsigned long LogFormat::runImport(QTextStream& importLogStream, { writeImportLog(importLogStream, WARNING_SEVERITY, + errors, + warnings, processedRec, record, tr("Outside the selected Date Range")); - (*warnings)++; continue; } } @@ -362,10 +430,11 @@ unsigned long LogFormat::runImport(QTextStream& importLogStream, { writeImportLog(importLogStream, WARNING_SEVERITY, + errors, + warnings, processedRec, record, tr("Duplicate")); - (*warnings)++; continue; } @@ -388,55 +457,173 @@ unsigned long LogFormat::runImport(QTextStream& importLogStream, case SKIP_ALL: writeImportLog(importLogStream, WARNING_SEVERITY, + errors, + warnings, processedRec, record, tr("Duplicate")); - (*warnings)++; continue; break; } } } - const DxccEntity &entity = Data::instance()->lookupDxcc(call.toString()); + /* Adding information which are important for QLog or QLog knows/compute them */ + /************************/ + /* Add DXCC Entity Info */ + /************************/ - if ( entity.dxcc == 0 ) + int recordDXCCId = record.value(RECORDIDX(LogbookModel::COLUMN_DXCC)).toInt(); // 0 = NAN or not present + // otherwise = DXCC ID + + if ( recordDXCCId != 0 || updateDxcc ) + { + const DxccEntity &entity = ( updateDxcc ) ? Data::instance()->lookupDxcc(call.toString()) + : Data::instance()->lookupDxccID(recordDXCCId); + + if ( entity.dxcc == 0 ) // DXCC not found + { + writeImportLog(importLogStream, + (updateDxcc) ? ERROR_SEVERITY : WARNING_SEVERITY, + errors, + warnings, + processedRec, + record, + tr("Cannot find DXCC Entity Info")); + if ( updateDxcc ) + continue; + } + else + { + // force overwrite + record.setValue(RECORDIDX(LogbookModel::COLUMN_DXCC), entity.dxcc); + record.setValue(RECORDIDX(LogbookModel::COLUMN_COUNTRY), Data::removeAccents(entity.country)); + record.setValue(RECORDIDX(LogbookModel::COLUMN_COUNTRY_INTL), entity.country); + + // other DXCC related values ​​are not closely related to DXCC value and could have been filled + // therefore check if it is present or not. + setIfEmpty(LogbookModel::COLUMN_CONTINENT, entity.cont); + setIfEmpty(LogbookModel::COLUMN_ITUZ, QString::number(entity.ituz)); + setIfEmpty(LogbookModel::COLUMN_CQZ, QString::number(entity.cqz)); + } + } + else { writeImportLog(importLogStream, - ERROR_SEVERITY, + WARNING_SEVERITY, + errors, + warnings, processedRec, record, - tr("Cannot find DXCC Entity Info")); - (*errors)++; - continue; + tr("DXCC Info is missing")); } - if ( record.value(RECORDIDX(LogbookModel::COLUMN_DXCC)).toString().isEmpty() - || updateDxcc ) - { - record.setValue(RECORDIDX(LogbookModel::COLUMN_DXCC), entity.dxcc); - record.setValue(RECORDIDX(LogbookModel::COLUMN_COUNTRY), Data::removeAccents(entity.country)); - record.setValue(RECORDIDX(LogbookModel::COLUMN_COUNTRY_INTL), entity.country); - } + /************************/ + /* Add My Station Info */ + /************************/ - if ( record.value(RECORDIDX(LogbookModel::COLUMN_CONTINENT)).toString().isEmpty() - || updateDxcc ) - { - record.setValue(RECORDIDX(LogbookModel::COLUMN_CONTINENT), entity.cont); - } + int recordMyDXCCId = record.value(RECORDIDX(LogbookModel::COLUMN_MY_DXCC)).toInt(); // 0 = NAN or not present + // otherwise = DXCC ID + const QString &myCallString = mycall.toString(); - if ( record.value(RECORDIDX(LogbookModel::COLUMN_ITUZ)).toString().isEmpty() - || updateDxcc ) + if ( defaultStationProfile ) { - record.setValue(RECORDIDX(LogbookModel::COLUMN_ITUZ), QString::number(entity.ituz)); - } + // default is enabled - if ( record.value(RECORDIDX(LogbookModel::COLUMN_CQZ)).toString().isEmpty() - || updateDxcc ) + // Case 1: Both recordMyDXCCId and myCallString are empty + if ( recordMyDXCCId == 0 && myCallString.isEmpty() ) + { + setMyDefaultProfile(); + } + // Case 2: recordMyDXCCId is empty, myCallString is not + else if ( recordMyDXCCId == 0 ) + { + if ( defaultStationProfile->callsign == myCallString ) + setMyDefaultProfile(); + else + lookupAndSetMyEntityByCallsign(myCallString); + } + // Case 3: myCallString is empty, recordMyDXCCId is not + else if ( myCallString.isEmpty() ) + { + if ( defaultStationProfile->dxcc == recordMyDXCCId ) + setMyDefaultProfile(); + else + { + // no Station Callsign = ERROR + writeImportLog(importLogStream, + ERROR_SEVERITY, + errors, + warnings, + processedRec, + record, + tr("no Station Callsign present")); + continue; + } + } + // Case 4: Both recordMyDXCCId and myCallString are not empty + else + { + if ( defaultStationProfile->callsign == myCallString ) + { + if ( defaultStationProfile->dxcc == recordMyDXCCId ) + setMyDefaultProfile(); + else + { + // no Station Callsign = ERROR + writeImportLog(importLogStream, + ERROR_SEVERITY, + errors, + warnings, + processedRec, + record, + tr("no Station Callsign present")); + continue; + } + } + else + lookupAndSetMyEntityByCallsign(myCallString); + } + } + else { - record.setValue(RECORDIDX(LogbookModel::COLUMN_CQZ), QString::number(entity.cqz)); + // default is disabled + if ( myCallString.isEmpty() ) + { + // no Station Callsign = ERROR + writeImportLog(importLogStream, + ERROR_SEVERITY, + errors, + warnings, + processedRec, + record, + tr("no Station Callsign present")); + continue; + } + else + { + const DxccEntity &myEntity = ( recordMyDXCCId != 0 ) ? Data::instance()->lookupDxccID(recordDXCCId) + : Data::instance()->lookupDxcc(myCallString); + + if ( myEntity.dxcc == 0 ) // My DXCC not found + { + writeImportLog(importLogStream, + WARNING_SEVERITY, + errors, + warnings, + processedRec, + record, + tr("Cannot find My DXCC Entity Info")); + } + else + setMyEntity(myEntity); + } } + /***********/ + /* Add PFX */ + /***********/ + if ( record.value(RECORDIDX(LogbookModel::COLUMN_PREFIX)).toString().isEmpty() ) { const QString &pfxRef = Callsign(call.toString()).getWPXPrefix(); @@ -447,6 +634,9 @@ unsigned long LogFormat::runImport(QTextStream& importLogStream, } } + /********************/ + /* Compute Distance */ + /********************/ const QString &gridsquare = record.value(RECORDIDX(LogbookModel::COLUMN_GRID)).toString(); const QString &my_gridsquare = record.value(RECORDIDX(LogbookModel::COLUMN_MY_GRIDSQUARE)).toString(); @@ -454,8 +644,8 @@ unsigned long LogFormat::runImport(QTextStream& importLogStream, && !my_gridsquare.isEmpty() && record.value(RECORDIDX(LogbookModel::COLUMN_DISTANCE)).toString().isEmpty() ) { - Gridsquare grid(gridsquare); - Gridsquare my_grid(my_gridsquare); + const Gridsquare grid(gridsquare); + const Gridsquare my_grid(my_gridsquare); double distance; if ( my_grid.distanceTo(grid, distance) ) @@ -464,7 +654,9 @@ unsigned long LogFormat::runImport(QTextStream& importLogStream, } } - + /*************************/ + /* Compute Alt from SOTA */ + /*************************/ if ( record.value(RECORDIDX(LogbookModel::COLUMN_ALTITUDE)).toString().isEmpty() && !sota.toString().isEmpty() ) { @@ -476,6 +668,9 @@ unsigned long LogFormat::runImport(QTextStream& importLogStream, } } + /*******************************/ + /* Compute My Alt from My SOTA */ + /*******************************/ if ( record.value(RECORDIDX(LogbookModel::COLUMN_MY_ALTITUDE)).toString().isEmpty() && !mysota.toString().isEmpty() ) { @@ -487,44 +682,9 @@ unsigned long LogFormat::runImport(QTextStream& importLogStream, } } - const DxccEntity &dxccEntity = Data::instance()->lookupDxcc(mycall.toString()); - - if ( dxccEntity.dxcc == 0 ) - { - writeImportLog(importLogStream, - ERROR_SEVERITY, - processedRec, - record, - tr("Cannot find own DXCC Entity Info")); - (*errors)++; - continue; - } - - if ( record.value(RECORDIDX(LogbookModel::COLUMN_MY_DXCC)).toString().isEmpty() ) - { - record.setValue(RECORDIDX(LogbookModel::COLUMN_MY_DXCC), dxccEntity.dxcc); - } - - if ( record.value(RECORDIDX(LogbookModel::COLUMN_MY_ITU_ZONE)).toString().isEmpty() ) - { - record.setValue(RECORDIDX(LogbookModel::COLUMN_MY_ITU_ZONE), dxccEntity.ituz); - } - - if ( record.value(RECORDIDX(LogbookModel::COLUMN_MY_CQ_ZONE)).toString().isEmpty() ) - { - record.setValue(RECORDIDX(LogbookModel::COLUMN_MY_CQ_ZONE), dxccEntity.cqz); - } - - if ( record.value(RECORDIDX(LogbookModel::COLUMN_MY_COUNTRY_INTL)).toString().isEmpty() ) - { - record.setValue(RECORDIDX(LogbookModel::COLUMN_MY_COUNTRY_INTL), dxccEntity.country); - } - - if ( record.value(RECORDIDX(LogbookModel::COLUMN_MY_COUNTRY)).toString().isEmpty() ) - { - record.setValue(RECORDIDX(LogbookModel::COLUMN_MY_COUNTRY), Data::removeAccents(dxccEntity.country)); - } - + /******************/ + /* PREPARE INSERT */ + /******************/ // Bind all values for ( int i = 0; i < record.count(); i++ ) { @@ -535,17 +695,20 @@ unsigned long LogFormat::runImport(QTextStream& importLogStream, { writeImportLog(importLogStream, ERROR_SEVERITY, + errors, + warnings, processedRec, record, tr("Cannot insert to database") + " - " + insertQuery.lastError().text()); qWarning() << "Cannot insert a record to Contact Table - " << insertQuery.lastError(); qCDebug(runtime) << record; - (*errors)++; } else { writeImportLog(importLogStream, INFO_SEVERITY, + errors, + warnings, processedRec, record, tr("Imported")); @@ -868,7 +1031,7 @@ long LogFormat::runExport(const QList &selectedQSOs) if ( exportedFields.first() != "*" ) { - for ( const QString& fieldName : qAsConst(exportedFields) ) + for ( const QString& fieldName : static_cast(exportedFields) ) { contactRecord.append(qso.field(fieldName)); } @@ -930,7 +1093,10 @@ void LogFormat::writeImportLog(QTextStream &errorLogStream, ImportLogSeverity se errorLogStream << importLogSeverityToString(severity) << msg << "\n"; } -void LogFormat::writeImportLog(QTextStream& errorLogStream, ImportLogSeverity severity, +void LogFormat::writeImportLog(QTextStream& errorLogStream, + ImportLogSeverity severity, + unsigned long *error, + unsigned long *warning, const unsigned long recordNo, const QSqlRecord &record, const QString &msg) @@ -944,5 +1110,10 @@ void LogFormat::writeImportLog(QTextStream& errorLogStream, ImportLogSeverity se record.value("callsign").toString(), record.value("mode").toString()) << "\n"; + switch (severity) + { + case WARNING_SEVERITY: (*warning)++; break; + case ERROR_SEVERITY: (*error)++; break; + case INFO_SEVERITY: break; + } } - diff --git a/logformat/LogFormat.h b/logformat/LogFormat.h index 8daf4e8d..37263511 100644 --- a/logformat/LogFormat.h +++ b/logformat/LogFormat.h @@ -6,6 +6,7 @@ #include #include "core/LogLocale.h" +#include "data/StationProfile.h" class QSqlRecord; @@ -52,6 +53,7 @@ class LogFormat : public QObject { static LogFormat* open(Type type, QTextStream& stream); unsigned long runImport(QTextStream& errorLogStream, + const StationProfile *defaultStationProfile, unsigned long *warnings, unsigned long *errors); void runQSLImport(QSLFrom fromService); @@ -105,6 +107,8 @@ class LogFormat : public QObject { const QString &msg); void writeImportLog(QTextStream& errorLogStream, ImportLogSeverity severity, + unsigned long *error, + unsigned long *warning, const unsigned long recordNo, const QSqlRecord &record, const QString &msg); diff --git a/models/AlertTableModel.cpp b/models/AlertTableModel.cpp index 40d51d4d..991b5df8 100644 --- a/models/AlertTableModel.cpp +++ b/models/AlertTableModel.cpp @@ -1,6 +1,5 @@ #include #include "AlertTableModel.h" -#include "core/debug.h" #include "data/Data.h" #include "rig/macros.h" @@ -14,7 +13,7 @@ int AlertTableModel::rowCount(const QModelIndex&) const int AlertTableModel::columnCount(const QModelIndex&) const { - return 7; + return 8; } QVariant AlertTableModel::data(const QModelIndex& index, int role) const @@ -32,6 +31,7 @@ QVariant AlertTableModel::data(const QModelIndex& index, int role) const case COLUMN_UPDATED: return selectedRecord.counter; case COLUMN_LAST_UPDATE: return selectedRecord.alert.dateTime.toString(locale.formatTimeLongWithoutTZ()); case COLUMN_LAST_COMMENT: return selectedRecord.alert.comment; + case COLUMN_MEMBER: return selectedRecord.alert.memberList2StringList().join(","); default: return QVariant(); } } @@ -66,6 +66,7 @@ QVariant AlertTableModel::headerData(int section, Qt::Orientation orientation, i case COLUMN_UPDATED: return tr("Updated"); case COLUMN_LAST_UPDATE: return tr("Last Update"); case COLUMN_LAST_COMMENT: return tr("Last Comment"); + case COLUMN_MEMBER: return tr("Member"); default: return QVariant(); } } diff --git a/models/AlertTableModel.h b/models/AlertTableModel.h index 9b677e66..bd1a505c 100644 --- a/models/AlertTableModel.h +++ b/models/AlertTableModel.h @@ -22,6 +22,7 @@ class AlertTableModel : public QAbstractTableModel COLUMN_UPDATED = 4, COLUMN_LAST_UPDATE = 5, COLUMN_LAST_COMMENT = 6, + COLUMN_MEMBER = 7, }; struct AlertTableRecord diff --git a/models/LogbookModel.h b/models/LogbookModel.h index 7762a662..3bc45352 100644 --- a/models/LogbookModel.h +++ b/models/LogbookModel.h @@ -15,7 +15,6 @@ class LogbookModel : public QSqlTableModel bool setData(const QModelIndex &index, const QVariant &value, int role) override; void updateExternalServicesUploadStatus( const QModelIndex &index, int role, bool &updateResult ); void updateUploadToModified( const QModelIndex &index, int role, int column, bool &updateResult ); - enum column_id { COLUMN_ID = 0, diff --git a/models/SearchFilterProxyModel.cpp b/models/SearchFilterProxyModel.cpp new file mode 100644 index 00000000..e7d46866 --- /dev/null +++ b/models/SearchFilterProxyModel.cpp @@ -0,0 +1,34 @@ +#include "SearchFilterProxyModel.h" + +SearchFilterProxyModel::SearchFilterProxyModel(QObject *parent) + : QSortFilterProxyModel{parent} +{} + +void SearchFilterProxyModel::setSearchString(const QString &searchString) +{ + this->searchString = searchString; + invalidateFilter(); +} + +void SearchFilterProxyModel::setSearchSkippedCols(const QVector &columns) +{ + searchSkippedCols = columns; + invalidateFilter(); +} + +bool SearchFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const +{ + // full-text search + for ( int col = 0; col < sourceModel()->columnCount(); ++col ) + { + if (searchSkippedCols.contains(col) ) + continue; + + QModelIndex index = sourceModel()->index(source_row, col, source_parent); + QString data = index.data(Qt::DisplayRole).toString(); + + if ( data.contains(searchString, Qt::CaseInsensitive) ) + return true; + } + return false; +} diff --git a/models/SearchFilterProxyModel.h b/models/SearchFilterProxyModel.h new file mode 100644 index 00000000..9cf93922 --- /dev/null +++ b/models/SearchFilterProxyModel.h @@ -0,0 +1,23 @@ +#ifndef QLOG_MODELS_SEARCHFILTERPROXYMODEL_H +#define QLOG_MODELS_SEARCHFILTERPROXYMODEL_H + +#include + +class SearchFilterProxyModel : public QSortFilterProxyModel +{ + Q_OBJECT + +public: + SearchFilterProxyModel(QObject* parent = nullptr); + void setSearchString(const QString& searchString); + void setSearchSkippedCols(const QVector &columns); + +protected: + bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override; + +private: + QString searchString; + QVector searchSkippedCols; +}; + +#endif // QLOG_MODELS_SEARCHFILTERPROXYMODEL_H diff --git a/models/ShortcutEditorModel.cpp b/models/ShortcutEditorModel.cpp index 69c66a58..51b69310 100644 --- a/models/ShortcutEditorModel.cpp +++ b/models/ShortcutEditorModel.cpp @@ -1,5 +1,4 @@ #include "ShortcutEditorModel.h" -#include "core/debug.h" ShortcutEditorModel::ShortcutEditorModel(const QList &actions, const QStringList &builtInStaticActions, diff --git a/models/ShortcutEditorModel.h b/models/ShortcutEditorModel.h index ed1d67c5..36457ac4 100644 --- a/models/ShortcutEditorModel.h +++ b/models/ShortcutEditorModel.h @@ -1,5 +1,5 @@ -#ifndef SHORTCUTEDITORMODEL_H -#define SHORTCUTEDITORMODEL_H +#ifndef QLOG_MODELS_SHORTCUTEDITORMODEL_H +#define QLOG_MODELS_SHORTCUTEDITORMODEL_H #include #include @@ -36,4 +36,4 @@ class ShortcutEditorModel : public QAbstractTableModel const QString&) const; }; -#endif // SHORTCUTEDITORMODEL_H +#endif // QLOG_MODELS_SHORTCUTEDITORMODEL_H diff --git a/models/WsjtxTableModel.cpp b/models/WsjtxTableModel.cpp index 4f23402e..62baff8a 100644 --- a/models/WsjtxTableModel.cpp +++ b/models/WsjtxTableModel.cpp @@ -1,8 +1,6 @@ #include #include "WsjtxTableModel.h" -#include "core/debug.h" -#include "data/StationProfile.h" -#include "core/Gridsquare.h" +#include "data/Data.h" bool operator==(const WsjtxEntry& a, const WsjtxEntry& b) { diff --git a/res/io.github.foldynl.QLog.metainfo.xml b/res/io.github.foldynl.QLog.metainfo.xml index a82ac9c3..8dff595c 100644 --- a/res/io.github.foldynl.QLog.metainfo.xml +++ b/res/io.github.foldynl.QLog.metainfo.xml @@ -47,6 +47,33 @@ https://github.com/foldynl/QLog https://github.com/foldynl/QLog/blob/master/CONTRIBUTING.md + + +

    +
  • [NEW] - DXC - Added Full-text search
  • +
  • [NEW] - Select S in RST Edit when focused (issue #454)
  • +
  • [NEW] - Alerts - Added Member Column
  • +
  • [CHANGED] - HamlibDrv Rig/Rot- Added multiplatform reliable sleep
  • +
  • [CHANGED] - Changed Backup policy
  • +
  • [CHANGED] - Logbook page size - improved performance
  • +
  • [CHANGED] - Logbook - CTRL-A (Select All) is disabled
  • +
  • [CHANGED] - Awards - Bands are displayed based on the Settings (issue #452)
  • +
  • [CHANGED] - WSJTX - More reliable detection of CQ stations (PR #471 @aa5sh)
  • +
  • [CHANGED] - WSJTX - SOTA/POTA/WWFF/SIG are being added to the logged QSO (PR #463 @aa5sh)
  • +
  • [CHANGED] - Stats - Add a confirmation dialog for displaying over 50k QSOs on the map
  • +
  • [CHANGED] - New Contact - Starting QSO Timer when Rig online and WSJTX Update Callsign Status is received
  • +
  • [CHANGED] - Added a postponed handling for Rig soft errors (issue #472)
  • +
  • Fixed WSJT-X does not emit band change if rig is disconnected (issue #447)
  • +
  • Fixed Wrong import of ADIF file of another log program (issue #455)
  • +
  • Fixed WSJTX log record is stored incorrectly if it contains non-ASCII chars(issue #458)
  • +
  • Fixed ADIF import does not import records with old DXCC Entities (issue #459)
  • +
  • Fixed ADIF import incorrectly uses Station Profile parameters (issue #461)
  • +
  • Fixed Logbook - QSO Table Column Width Does Not Stick (issue #464)
  • +
  • Fixed Alerts Window displays OOB Spots (issue #469)
  • +
  • Fixed Field values from past QSOs are used incorrectly in case of WSJTX QSOs (#issue 470)
  • +
+ +
    diff --git a/rig/Rig.cpp b/rig/Rig.cpp index f276b916..50f30800 100644 --- a/rig/Rig.cpp +++ b/rig/Rig.cpp @@ -49,14 +49,6 @@ Rig::Rig(QObject *parent) } -Rig* Rig::instance() -{ - FCT_IDENTIFICATION; - - static Rig instance; - return &instance; -} - qint32 Rig::getNormalBandwidth(const QString &mode, const QString &) { FCT_IDENTIFICATION; diff --git a/rig/Rig.h b/rig/Rig.h index 6a73bd64..87abd3e5 100644 --- a/rig/Rig.h +++ b/rig/Rig.h @@ -30,7 +30,12 @@ class Rig : public QObject TCI_DRIVER = 4 }; - static Rig* instance(); + static Rig* instance() + { + static Rig instance; + return &instance; + }; + static qint32 getNormalBandwidth(const QString &mode, const QString &subMode); diff --git a/rig/drivers/HamlibRigDrv.cpp b/rig/drivers/HamlibRigDrv.cpp index 1738ed98..99883e5a 100644 --- a/rig/drivers/HamlibRigDrv.cpp +++ b/rig/drivers/HamlibRigDrv.cpp @@ -1,11 +1,5 @@ #include -#ifdef Q_OS_WIN -#include -#else -#include -#endif - #include #include "HamlibRigDrv.h" #include "core/debug.h" @@ -16,6 +10,13 @@ #define HAMLIB_FILPATHLEN FILPATHLEN #endif +#ifndef RIG_IS_SOFT_ERRCODE +#define RIG_IS_SOFT_ERRCODE(errcode) (errcode == RIG_EINVAL || errcode == RIG_ENIMPL || errcode == RIG_ERJCTED \ + || errcode == RIG_ETRUNC || errcode == RIG_ENAVAIL || errcode == RIG_ENTARGET \ + || errcode == RIG_EVFO || errcode == RIG_EDOM) + +#endif + // macro introduced hamlib 4.6 #ifndef PTTPORT #define PTTPORT(r) (&r->state.pttport) @@ -134,6 +135,9 @@ HamlibRigDrv::HamlibRigDrv(const RigProfile &profile, } rig_set_debug(RIG_DEBUG_BUG); + + connect(&errorTimer, &QTimer::timeout, + this, &HamlibRigDrv::checkErrorCounter); } HamlibRigDrv::~HamlibRigDrv() @@ -219,16 +223,10 @@ bool HamlibRigDrv::open() int status = rig_open(rig); - if ( status != RIG_OK ) - { - lastErrorText = hamlibErrorString(status); - qCDebug(runtime) << "Rig Open Error" << lastErrorText; + if ( !isRigRespOK(status, tr("Rig Open Error"), false) ) return false; - } - else - { - qCDebug(runtime) << "Rig Open - OK"; - } + + qCDebug(runtime) << "Rig Open - OK"; opened = true; currRIT = MHz(rigProfile.ritOffset); @@ -314,14 +312,8 @@ void HamlibRigDrv::setFrequency(double newFreq) } int status = rig_set_freq(rig, RIG_VFO_CURR, newFreq); + isRigRespOK(status, tr("Set Frequency Error"), false); - if ( status != RIG_OK ) - { - lastErrorText = hamlibErrorString(status); - qCWarning(runtime) << "Set Freq error" << lastErrorText; - emit errorOccured(tr("Set Frequency Error"), - lastErrorText); - } commandSleep(); } @@ -362,13 +354,7 @@ void HamlibRigDrv::__setMode(rmode_t newModeID) && newModeID != currModeId ) { int status = rig_set_mode(rig, RIG_VFO_CURR, newModeID, RIG_PASSBAND_NOCHANGE); - - if ( status != RIG_OK ) - { - lastErrorText = hamlibErrorString(status); - qCWarning(runtime) << "Set KeySpeed error" << lastErrorText; - //emit errorOccured(lastErrorText); - } + isRigRespOK(status, tr("Set Mode Error"), false); commandSleep(); } } @@ -391,14 +377,7 @@ void HamlibRigDrv::setPTT(bool newPTTState) } int status = rig_set_ptt(rig, RIG_VFO_CURR, (newPTTState ? RIG_PTT_ON : RIG_PTT_OFF)); - - if ( status != RIG_OK ) - { - lastErrorText = hamlibErrorString(status); - qCWarning(runtime) << "Set PTT error" << lastErrorText; - emit errorOccured(tr("Set PTT Error"), - lastErrorText); - } + isRigRespOK(status, tr("Set PTT Error"), false); // wait a moment because Rigs are slow and they are not possible to set and get // mode so quickly @@ -463,13 +442,8 @@ void HamlibRigDrv::sendMorse(const QString &text) } int status = rig_send_morse(rig, RIG_VFO_CURR, text.toLocal8Bit().constData()); + isRigRespOK(status, tr("Cannot sent Morse"), false); - if ( status != RIG_OK ) - { - lastErrorText = hamlibErrorString(status); - qCWarning(runtime) << "Cannot sent Morse" << lastErrorText; - //emit errorOccured(lastErrorText); - } commandSleep(); } @@ -487,13 +461,7 @@ void HamlibRigDrv::stopMorse() #if (HAMLIBVERSION_MAJOR >= 4) int status = rig_stop_morse(rig, RIG_VFO_CURR); - - if ( status != RIG_OK ) - { - lastErrorText = hamlibErrorString(status); - qCWarning(runtime) << "Cannot Stop Morse" << lastErrorText; - //emit errorOccured(lastErrorText); - } + isRigRespOK(status, tr("Cannot stop Morse"), false); #endif commandSleep(); } @@ -512,6 +480,7 @@ void HamlibRigDrv::stopTimers() FCT_IDENTIFICATION; timer.stop(); + errorTimer.stop(); } void HamlibRigDrv::sendDXSpot(const DxSpot &) @@ -561,6 +530,21 @@ void HamlibRigDrv::checkRigStateChange() drvLock.unlock(); } +void HamlibRigDrv::checkErrorCounter() +{ + FCT_IDENTIFICATION; + + if ( postponedErrors.isEmpty() ) + return; + + qCDebug(runtime) << postponedErrors; + + // emit only one error + auto it = postponedErrors.constBegin(); + emit errorOccured(it.key(), it.value()); + postponedErrors.clear(); +} + void HamlibRigDrv::checkPTTChange() { FCT_IDENTIFICATION; @@ -580,7 +564,7 @@ void HamlibRigDrv::checkPTTChange() ptt_t pttHamlib; int status = rig_get_ptt(rig, RIG_VFO_CURR, &pttHamlib); - if ( status == RIG_OK ) + if ( isRigRespOK(status, tr("Get PTT Error"), false) ) { bool ptt = ( pttHamlib == RIG_PTT_OFF ) ? false : true; @@ -594,16 +578,9 @@ void HamlibRigDrv::checkPTTChange() emit pttChanged(currPTT); } } - else - { - lastErrorText = hamlibErrorString(status); - qCWarning(runtime) << "Get PTT error" << lastErrorText; - } } else - { qCDebug(runtime) << "Get PTT is disabled"; - } } bool HamlibRigDrv::checkFreqChange() @@ -622,7 +599,7 @@ bool HamlibRigDrv::checkFreqChange() freq_t vfo_freq; int status = rig_get_freq(rig, RIG_VFO_CURR, &vfo_freq); - if ( status == RIG_OK ) + if ( isRigRespOK(status, tr("Get Frequency Error")) ) { qCDebug(runtime) << "Rig Freq: "<< QSTRING_FREQ(Hz2MHz(vfo_freq)); qCDebug(runtime) << "Object Freq: "<< QSTRING_FREQ(Hz2MHz(currFreq)); @@ -637,18 +614,11 @@ bool HamlibRigDrv::checkFreqChange() } } else - { - lastErrorText = hamlibErrorString(status); - emit errorOccured(tr("Get Frequency Error"), - lastErrorText); - qCWarning(runtime) << "Get Freq error" << lastErrorText; return false; - } } else - { qCDebug(runtime) << "Get Freq is disabled"; - } + return true; } @@ -670,7 +640,7 @@ bool HamlibRigDrv::checkModeChange() int status = rig_get_mode(rig, RIG_VFO_CURR, &curr_modeId, &pbwidth); - if ( status == RIG_OK ) + if ( isRigRespOK(status, tr("Get Mode Error")) ) { qCDebug(runtime) << "Rig Mode: "<< curr_modeId << "Rig Filter: "<< pbwidth; qCDebug(runtime) << "Object Mode: "<< currModeId << "Object Filter:" << currPBWidth; @@ -694,18 +664,11 @@ bool HamlibRigDrv::checkModeChange() } } else - { - lastErrorText = hamlibErrorString(status); - emit errorOccured(tr("Get Mode Error"), - lastErrorText); - qCWarning(runtime) << "Get Mode error" << lastErrorText; return false; - } } else - { qCDebug(runtime) << "Get Mode is disabled"; - } + return true; } @@ -726,7 +689,7 @@ void HamlibRigDrv::checkVFOChange() int status = rig_get_vfo(rig, &curr_vfo); - if ( status == RIG_OK ) + if ( isRigRespOK(status, tr("Get VFO Error"), false) ) { qCDebug(runtime) << "Rig VFO: "<< curr_vfo; qCDebug(runtime) << "Object VFO: "<< currVFO; @@ -740,16 +703,9 @@ void HamlibRigDrv::checkVFOChange() emit vfoChanged(rawVFOText); } } - else - { - lastErrorText = hamlibErrorString(status); - qCWarning(runtime) << "Get VFO error" << lastErrorText; - } } else - { qCDebug(runtime) << "Get VFO is disabled"; - } } void HamlibRigDrv::checkPWRChange() @@ -771,11 +727,11 @@ void HamlibRigDrv::checkPWRChange() int status = rig_get_level(rig, RIG_VFO_CURR, RIG_LEVEL_RFPOWER, &rigPowerLevel); - if ( status == RIG_OK ) + if ( isRigRespOK(status, tr("Get PWR Error"), false) ) { status = rig_power2mW(rig, &rigPower, rigPowerLevel.f, currFreq, currModeId); - if ( status == RIG_OK ) + if ( isRigRespOK(status, tr("Get PWR (power2mw) Error"), false) ) { qCDebug(runtime) << "Rig PWR: "<< rigPower; qCDebug(runtime) << "Object PWR: "<< currPWR; @@ -788,22 +744,10 @@ void HamlibRigDrv::checkPWRChange() emit powerChanged(mW2W(currPWR)); } } - else - { - lastErrorText = hamlibErrorString(status); - qCWarning(runtime) << "Get PWR power2mw error" << lastErrorText; - } - } - else - { - lastErrorText = hamlibErrorString(status); - qCWarning(runtime) << "Get PWR error" << lastErrorText; - } + } } else - { qCDebug(runtime) << "Get PWR is disabled"; - } } void HamlibRigDrv::checkRITChange() @@ -825,18 +769,14 @@ void HamlibRigDrv::checkRITChange() int status = rig_get_func(rig, RIG_VFO_CURR, RIG_FUNC_RIT, &ritStatus); - if ( status == RIG_OK ) + if ( isRigRespOK(status, tr("Get RIT Function Error"), false) ) { if ( ritStatus ) { /* RIT is on */ status = rig_get_rit(rig, RIG_VFO_CURR, &rit); - if ( status != RIG_OK ) - { + if ( !isRigRespOK(status, tr("Get RIT Error"), false) ) rit = s_Hz(0); - lastErrorText = hamlibErrorString(status); - qCWarning(runtime) << "Get RIT error" << lastErrorText; - } } else { @@ -862,16 +802,9 @@ void HamlibRigDrv::checkRITChange() Hz2MHz(getXITFreq())); } } - else - { - lastErrorText = hamlibErrorString(status); - qCWarning(runtime) << "Get RIT Function error" << lastErrorText; - } } else - { qCDebug(runtime) << "Get RIT is disabled"; - } } void HamlibRigDrv::checkXITChange() @@ -893,18 +826,14 @@ void HamlibRigDrv::checkXITChange() int status = rig_get_func(rig, RIG_VFO_CURR, RIG_FUNC_XIT, &xitStatus); - if ( status == RIG_OK ) + if ( isRigRespOK(status, tr("Get XIT Function Error"), false) ) { if ( xitStatus ) { /* XIT is on */ status = rig_get_xit(rig, RIG_VFO_CURR, &xit); - if ( status != RIG_OK ) - { + if ( !isRigRespOK(status, tr("Get XIT Error"), false) ) xit = s_Hz(0); - lastErrorText = hamlibErrorString(status); - qCWarning(runtime) << "Get XIT error" << lastErrorText; - } } else { @@ -930,16 +859,9 @@ void HamlibRigDrv::checkXITChange() Hz2MHz(getXITFreq())); } } - else - { - lastErrorText = hamlibErrorString(status); - qCWarning(runtime) << "Get XIT Function error" << lastErrorText; - } } else - { qCDebug(runtime) << "Get XIT is disabled"; - } } void HamlibRigDrv::checkKeySpeedChange() @@ -959,7 +881,7 @@ void HamlibRigDrv::checkKeySpeedChange() int status = rig_get_level(rig, RIG_VFO_CURR, RIG_LEVEL_KEYSPD, &rigKeySpeed); - if ( status == RIG_OK ) + if ( isRigRespOK(status, tr("Get KeySpeed Error"), false) ) { qCDebug(runtime) << "RIG Key Speed: "<< rigKeySpeed.i; qCDebug(runtime) << "Object Key Speed: "<< keySpeed; @@ -970,16 +892,9 @@ void HamlibRigDrv::checkKeySpeedChange() emit keySpeedChanged(keySpeed); } } - else - { - lastErrorText = hamlibErrorString(status); - qCWarning(runtime) << "Get KeySpeed error" << lastErrorText; - } } else - { qCDebug(runtime) << "Get KeySpeed is disabled"; - } } double HamlibRigDrv::getRITFreq() @@ -1018,24 +933,58 @@ void HamlibRigDrv::__setKeySpeed(qint16 wpm) value_t hamlibWPM; hamlibWPM.i = wpm; int status = rig_set_level(rig, RIG_VFO_CURR, RIG_LEVEL_KEYSPD, hamlibWPM); - - if ( status != RIG_OK ) - { - lastErrorText = hamlibErrorString(status); - qCWarning(runtime) << "Set KeySpeed error" << lastErrorText; - //emit errorOccured(lastErrorText); - } + isRigRespOK(status, tr("Set KeySpeed Error"), false); commandSleep(); } void HamlibRigDrv::commandSleep() { -#ifdef Q_OS_WIN - Sleep(100); -#else - usleep(100000); -#endif + FCT_IDENTIFICATION; + + QThread::msleep(200); +} + +bool HamlibRigDrv::isRigRespOK(int errorStatus, + const QString errorName, + bool emitError) +{ + FCT_IDENTIFICATION; + + qCDebug(function_parameters) << errorStatus << errorName << emitError; + + if ( errorStatus == RIG_OK ) + { + if ( emitError ) + postponedErrors.remove(errorName); + return true; + } + + lastErrorText = hamlibErrorString(errorStatus); + + if ( emitError ) + { + qCDebug(runtime) << "Emit Error detected"; + + if ( !RIG_IS_SOFT_ERRCODE(-errorStatus) ) + { + // hard error, emit error now + qCDebug(runtime) << "Hard Error"; + emit errorOccured(errorName, lastErrorText); + } + else + { + // soft error + postponedErrors[errorName] = lastErrorText; + + if ( !errorTimer.isActive() ) + { + qCDebug(runtime) << "Starting Error Timer"; + errorTimer.start(15 * 1000); //15s + } + } + } + return false; } const QString HamlibRigDrv::getModeNormalizedText(const rmode_t mode, @@ -1127,17 +1076,22 @@ QString HamlibRigDrv::hamlibErrorString(int errorCode) qCDebug(function_parameters) << errorCode; - static QRegularExpression re("[\r\n]"); - - const QStringList &errorList = QString(rigerror(errorCode)).split(re); QString ret; + QString detail(rigerror(errorCode)); + +#if ( HAMLIBVERSION_MAJOR >= 4 && HAMLIBVERSION_MINOR >= 5 ) + // The rigerror has different behavior since 4.5. It contains the stack trace in the first part + // Need to use rigerror2 + ret = QString(rigerror2(errorCode)); +#else + static QRegularExpression re("[\r\n]"); + QStringList errorList = detail.split(re); if ( errorList.size() >= 1 ) - { ret = errorList.at(0); - } - - qCDebug(runtime) << ret; +#endif + qWarning() << "Detail" << detail; + qCWarning(runtime) << ret; return ret; } diff --git a/rig/drivers/HamlibRigDrv.h b/rig/drivers/HamlibRigDrv.h index 91fccf91..c99898c4 100644 --- a/rig/drivers/HamlibRigDrv.h +++ b/rig/drivers/HamlibRigDrv.h @@ -36,8 +36,10 @@ class HamlibRigDrv : public GenericRigDrv private slots: void checkRigStateChange(); + void checkErrorCounter(); private: + #if ( HAMLIBVERSION_MAJOR >= 4 && HAMLIBVERSION_MINOR >= 6 ) static int addRig(rig_caps *caps, void* data); #else @@ -61,6 +63,9 @@ private slots: void __setKeySpeed(qint16 wpm); void __setMode(rmode_t newModeID); void commandSleep(); + bool isRigRespOK(int errorStatus, + const QString errorName, + bool emitError = true); const QString getModeNormalizedText(const rmode_t mode, QString &submode) const; @@ -72,6 +77,7 @@ private slots: RIG* rig; QTimer timer; + QTimer errorTimer; bool forceSendState; bool currPTT; @@ -85,7 +91,7 @@ private slots: unsigned int keySpeed; bool morseOverCatSupported; QMutex drvLock; - + QHashpostponedErrors; }; #endif // RIG_DRIVERS_HAMLIBRIGDRV_H diff --git a/rig/drivers/TCIRigDrv.cpp b/rig/drivers/TCIRigDrv.cpp index 818232d5..f2645f4a 100644 --- a/rig/drivers/TCIRigDrv.cpp +++ b/rig/drivers/TCIRigDrv.cpp @@ -5,6 +5,7 @@ #include "rig/macros.h" #include "data/Data.h" #include "data/BandPlan.h" +#include "core/debug.h" MODULE_IDENTIFICATION("qlog.rig.driver.tcidrv"); diff --git a/rotator/RotCaps.h b/rotator/RotCaps.h index 27fc8753..b6a4ca20 100644 --- a/rotator/RotCaps.h +++ b/rotator/RotCaps.h @@ -1,5 +1,5 @@ -#ifndef ROTATOR_ROTCAPS_H -#define ROTATOR_ROTCAPS_H +#ifndef QLOG_ROTATOR_ROTCAPS_H +#define QLOG_ROTATOR_ROTCAPS_H class RotCaps @@ -14,4 +14,4 @@ class RotCaps int serialStopBits; }; -#endif // ROTATOR_ROTCAPS_H +#endif // QLOG_ROTATOR_ROTCAPS_H diff --git a/rotator/Rotator.cpp b/rotator/Rotator.cpp index ecde6e52..710a0662 100644 --- a/rotator/Rotator.cpp +++ b/rotator/Rotator.cpp @@ -42,13 +42,6 @@ Rotator::~Rotator() __closeRot(); } -Rotator* Rotator::instance() { - FCT_IDENTIFICATION; - - static Rotator instance; - return &instance; -} - double Rotator::getAzimuth() { FCT_IDENTIFICATION; diff --git a/rotator/Rotator.h b/rotator/Rotator.h index fe97ef92..74cb2753 100644 --- a/rotator/Rotator.h +++ b/rotator/Rotator.h @@ -3,7 +3,6 @@ #include #include "data/RotProfile.h" -#include "core/SerialPort.h" #include "rotator/drivers/GenericRotDrv.h" #include "RotCaps.h" @@ -20,7 +19,11 @@ class Rotator : public QObject PSTROTATOR_DRIVER = 2 }; - static Rotator* instance(); + static Rotator* instance() + { + static Rotator instance; + return &instance; + }; double getAzimuth(); double getElevation(); bool isRotConnected(); diff --git a/rotator/drivers/GenericRotDrv.h b/rotator/drivers/GenericRotDrv.h index 87f550a1..71b31c21 100644 --- a/rotator/drivers/GenericRotDrv.h +++ b/rotator/drivers/GenericRotDrv.h @@ -1,5 +1,5 @@ -#ifndef GENERICROTDRV_H -#define GENERICROTDRV_H +#ifndef QLOG_ROTATOR_DRIVERS_GENERICROTDRV_H +#define QLOG_ROTATOR_DRIVERS_GENERICROTDRV_H #include #include "data/RotProfile.h" @@ -36,4 +36,4 @@ class GenericRotDrv : public QObject double elevation; }; -#endif // GENERICROTDRV_H +#endif // QLOG_ROTATOR_DRIVERS_GENERICROTDRV_H diff --git a/rotator/drivers/HamlibRotDrv.cpp b/rotator/drivers/HamlibRotDrv.cpp index a8e42343..2b215cb3 100644 --- a/rotator/drivers/HamlibRotDrv.cpp +++ b/rotator/drivers/HamlibRotDrv.cpp @@ -19,6 +19,13 @@ #define HAMLIB_FILPATHLEN FILPATHLEN #endif +#ifndef RIG_IS_SOFT_ERRCODE +#define RIG_IS_SOFT_ERRCODE(errcode) (errcode == RIG_EINVAL || errcode == RIG_ENIMPL || errcode == RIG_ERJCTED \ + || errcode == RIG_ETRUNC || errcode == RIG_ENAVAIL || errcode == RIG_ENTARGET \ + || errcode == RIG_EVFO || errcode == RIG_EDOM) + +#endif + #define POOL_INTERVAL 500 MODULE_IDENTIFICATION("qlog.rotator.driver.hamlibdrv"); @@ -84,6 +91,10 @@ HamlibRotDrv::HamlibRotDrv(const RotProfile &profile, } rig_set_debug(RIG_DEBUG_BUG); + + connect(&errorTimer, &QTimer::timeout, + this, &HamlibRotDrv::checkErrorCounter); + } HamlibRotDrv::~HamlibRotDrv() @@ -147,16 +158,10 @@ bool HamlibRotDrv::open() int status = rot_open(rot); - if ( status != RIG_OK ) - { - lastErrorText = hamlibErrorString(status); - qCDebug(runtime) << "Rot Open Error" << lastErrorText; + if ( !isRotRespOK(status, tr("Rot Open Error"), false) ) return false; - } - else - { - qCDebug(runtime) << "Rot Open - OK"; - } + + qCDebug(runtime) << "Rot Open - OK"; opened = true; @@ -243,13 +248,7 @@ void HamlibRotDrv::setPosition(double in_azimuth, double in_elevation) static_cast(newAzimuth), static_cast(newElevation)); - if ( status != RIG_OK ) - { - lastErrorText = hamlibErrorString(status); - qCWarning(runtime) << "Set Az/El error" << lastErrorText; - emit errorOccured(tr("Set Possition Error"), - lastErrorText); - } + isRotRespOK(status, tr("Set Possition Error"), false); // wait a moment because Rotators are slow and they are not possible to set and get // mode so quickly (get mode is called in the main thread's update() function @@ -261,6 +260,7 @@ void HamlibRotDrv::stopTimers() FCT_IDENTIFICATION; timer.stop(); + errorTimer.stop(); } void HamlibRotDrv::checkRotStateChange() @@ -284,6 +284,21 @@ void HamlibRotDrv::checkRotStateChange() drvLock.unlock(); } +void HamlibRotDrv::checkErrorCounter() +{ + FCT_IDENTIFICATION; + + if ( postponedErrors.isEmpty() ) + return; + + qCDebug(runtime) << postponedErrors; + + // emit only one error + auto it = postponedErrors.constBegin(); + emit errorOccured(it.key(), it.value()); + postponedErrors.clear(); +} + void HamlibRotDrv::checkChanges() { FCT_IDENTIFICATION; @@ -307,7 +322,7 @@ void HamlibRotDrv::checkAzEl() elevation_t el; int status = rot_get_position(rot, &az, &el); - if ( status == RIG_OK ) + if ( isRotRespOK(status, tr("Get Possition Error")) ) { double newAzimuth = az; double newElevation = el; @@ -328,18 +343,49 @@ void HamlibRotDrv::checkAzEl() emit positioningChanged(azimuth, elevation); } } - else - { - lastErrorText = hamlibErrorString(status); - qCWarning(runtime) << "Get AZ/EL error" << lastErrorText; - emit errorOccured(tr("Get Possition Error"), - lastErrorText); - } } else - { qCDebug(runtime) << "Get POSITION is disabled"; +} + +bool HamlibRotDrv::isRotRespOK(int errorStatus, const QString errorName, bool emitError) +{ + FCT_IDENTIFICATION; + + qCDebug(function_parameters) << errorStatus << errorName << emitError; + + if ( errorStatus == RIG_OK ) // there are no special codes for ROT, use RIG codes + { + if ( emitError ) + postponedErrors.remove(errorName); + return true; + } + + lastErrorText = hamlibErrorString(errorStatus); + + if ( emitError ) + { + qCDebug(runtime) << "Emit Error detected"; + + if ( !RIG_IS_SOFT_ERRCODE(-errorStatus) ) + { + // hard error, emit error now + qCDebug(runtime) << "Hard Error"; + emit errorOccured(errorName, lastErrorText); + } + else + { + // soft error + postponedErrors[errorName] = lastErrorText; + + if ( !errorTimer.isActive() ) + { + qCDebug(runtime) << "Starting Error Timer"; + errorTimer.start(15 * 1000); //15s + } + } } + return false; } serial_handshake_e HamlibRotDrv::stringToHamlibFlowControl(const QString &in_flowcontrol) @@ -384,28 +430,31 @@ QString HamlibRotDrv::hamlibErrorString(int errorCode) qCDebug(function_parameters) << errorCode; - static QRegularExpression re("[\r\n]"); - - const QStringList &errorList = QString(rigerror(errorCode)).split(re); QString ret; + QString detail(rigerror(errorCode)); + +#if ( HAMLIBVERSION_MAJOR >= 4 && HAMLIBVERSION_MINOR >= 5 ) + // The rigerror has different behavior since 4.5. It contains the stack trace in the first part + // Need to use rigerror2 + ret = QString(rigerror2(errorCode)); +#else + static QRegularExpression re("[\r\n]"); + QStringList errorList = detail.split(re); if ( errorList.size() >= 1 ) - { ret = errorList.at(0); - } - - qCDebug(runtime) << ret; +#endif + qWarning() << "Detail" << detail; + qCWarning(runtime) << ret; return ret; } void HamlibRotDrv::commandSleep() { -#ifdef Q_OS_WIN - Sleep(100); -#else - usleep(100000); -#endif + FCT_IDENTIFICATION; + + QThread::msleep(100); } #undef MUTEXLOCKER diff --git a/rotator/drivers/HamlibRotDrv.h b/rotator/drivers/HamlibRotDrv.h index 0eb4e6c3..b274c9b9 100644 --- a/rotator/drivers/HamlibRotDrv.h +++ b/rotator/drivers/HamlibRotDrv.h @@ -1,5 +1,5 @@ -#ifndef ROTATOR_DRIVERS_HAMLIBROTDRV_H -#define ROTATOR_DRIVERS_HAMLIBROTDRV_H +#ifndef QLOG_ROTATOR_DRIVERS_HAMLIBROTDRV_H +#define QLOG_ROTATOR_DRIVERS_HAMLIBROTDRV_H #include #include @@ -24,12 +24,16 @@ class HamlibRotDrv : public GenericRotDrv private slots: void checkRotStateChange(); + void checkErrorCounter(); private: static int addRig(const struct rot_caps* caps, void* data); void checkChanges(); void checkAzEl(); + bool isRotRespOK(int errorStatus, + const QString errorName, + bool emitError = true); serial_handshake_e stringToHamlibFlowControl(const QString &in_flowcontrol); serial_parity_e stringToHamlibParity(const QString &in_parity); @@ -38,9 +42,11 @@ private slots: ROT* rot; QTimer timer; + QTimer errorTimer; QMutex drvLock; bool forceSendState; + QHashpostponedErrors; }; -#endif // ROTATOR_DRIVERS_HAMLIBROTDRV_H +#endif // QLOG_ROTATOR_DRIVERS_HAMLIBROTDRV_H diff --git a/rotator/drivers/PSTRotDrv.h b/rotator/drivers/PSTRotDrv.h index 1ed83533..55f43fea 100644 --- a/rotator/drivers/PSTRotDrv.h +++ b/rotator/drivers/PSTRotDrv.h @@ -1,5 +1,5 @@ -#ifndef ROTATOR_DRIVERS_PSTROTDRV_H -#define ROTATOR_DRIVERS_PSTROTDRV_H +#ifndef QLOG_ROTATOR_DRIVERS_PSTROTDRV_H +#define QLOG_ROTATOR_DRIVERS_PSTROTDRV_H #include #include @@ -41,4 +41,4 @@ private slots: QHostAddress rotatorAddress; }; -#endif // ROTATOR_DRIVERS_PSTROTDRV_H +#endif // QLOG_ROTATOR_DRIVERS_PSTROTDRV_H diff --git a/rpm_spec/qlog.spec b/rpm_spec/qlog.spec index fdd4fe1d..106e5e13 100644 --- a/rpm_spec/qlog.spec +++ b/rpm_spec/qlog.spec @@ -42,6 +42,29 @@ INSTALL_ROOT=%{buildroot} make -f Makefile install %{_metainfodir}/* %changelog +* Sat Oct 5 2024 Ladislav Foldyna - 0.39.0-1 +- [NEW] - DXC - Added Full-text search +- [NEW] - Select S in RST Edit when focused (issue #454) +- [NEW] - Alerts - Added Member Column +- [CHANGED] - HamlibDrv Rig/Rot- Added multiplatform reliable sleep +- [CHANGED] - Changed Backup policy +- [CHANGED] - Logbook page size - improved performance +- [CHANGED] - Logbook - CTRL-A (Select All) is disabled +- [CHANGED] - Awards - Bands are displayed based on the Settings (issue #452) +- [CHANGED] - WSJTX - More reliable detection of CQ stations (PR #471 @aa5sh) +- [CHANGED] - WSJTX - SOTA/POTA/WWFF/SIG are being added to the logged QSO (PR #463 @aa5sh) +- [CHANGED] - Stats - Add a confirmation dialog for displaying over 50k QSOs on the map +- [CHANGED] - New Contact - Starting QSO Timer when Rig online and WSJTX Update Callsign Status is received +- [CHANGED] - Added a postponed handling for Rig soft errors (issue #472) +- Fixed WSJT-X does not emit band change if rig is disconnected (issue #447) +- Fixed Wrong import of ADIF file of another log program (issue #455) +- Fixed WSJTX log record is stored incorrectly if it contains non-ASCII chars(issue #458) +- Fixed ADIF import does not import records with old DXCC Entities (issue #459) +- Fixed ADIF import incorrectly uses Station Profile parameters (issue #461) +- Fixed Logbook - QSO Table Column Width Does Not Stick (issue #464) +- Fixed Alerts Window displays OOB Spots (issue #469) +- Fixed Field values from past QSOs are used incorrectly in case of WSJTX QSOs (#issue 470) + * Thu Aug 29 2024 Ladislav Foldyna - 0.38.0-1 - [NEW] - Logbook - Added Send DX Spot to the QSO Context Menu - [NEW] - DX Filter - Added Dedup Time/Freq difference setting (@aa5sh) diff --git a/ui/AlertRuleDetail.cpp b/ui/AlertRuleDetail.cpp index 773f1577..13d20ecb 100644 --- a/ui/AlertRuleDetail.cpp +++ b/ui/AlertRuleDetail.cpp @@ -232,7 +232,7 @@ void AlertRuleDetail::save() if ( ui->memberGroupBox->isChecked() ) { - for ( QCheckBox* item: qAsConst(memberListCheckBoxes) ) + for ( QCheckBox* item: static_cast&>(memberListCheckBoxes) ) { if ( item->isChecked() ) { @@ -674,7 +674,7 @@ void AlertRuleDetail::generateMembershipCheckboxes(const AlertRule * rule) { int elementIndex = 0; - for ( QCheckBox* item: qAsConst(memberListCheckBoxes) ) + for ( QCheckBox* item: static_cast&>(memberListCheckBoxes) ) { ui->dxMemberGrid->addWidget(item, elementIndex / 6, elementIndex % 6); elementIndex++; diff --git a/ui/AlertRuleDetail.ui b/ui/AlertRuleDetail.ui index 69b90e26..ea0244d7 100644 --- a/ui/AlertRuleDetail.ui +++ b/ui/AlertRuleDetail.ui @@ -6,8 +6,8 @@ 0 0 - 357 - 620 + 511 + 680 @@ -317,31 +317,31 @@ - - + + - North America + South America - - + + - Africa + Antarctica - - + + - Antarctica + North America - - + + - South America + Oceania @@ -359,10 +359,10 @@ - - + + - Oceania + Africa @@ -424,70 +424,70 @@ - - + + - North America + Antarctica false - - + + - Africa + Asia false - - + + - Antarctica + Europe false - - + + - South America + Africa false - - + + - Asia + North America false - - + + - Europe + Oceania false - - + + - Oceania + South America false @@ -547,19 +547,20 @@ continent afcheckbox ascheckbox - nacheckbox - occheckbox ancheckbox eucheckbox + nacheckbox + occheckbox sacheckbox + memberGroupBox spotterCountryCombo continent_spotter afcheckbox_spotter ascheckbox_spotter - nacheckbox_spotter - occheckbox_spotter ancheckbox_spotter eucheckbox_spotter + nacheckbox_spotter + occheckbox_spotter sacheckbox_spotter diff --git a/ui/AlertWidget.cpp b/ui/AlertWidget.cpp index 0690a625..fd45d811 100644 --- a/ui/AlertWidget.cpp +++ b/ui/AlertWidget.cpp @@ -131,11 +131,11 @@ void AlertWidget::restoreTableHeaderState() { FCT_IDENTIFICATION; - const QVariant &state = settings.value("alert/state"); + const QByteArray &state = settings.value("alert/state").toByteArray(); - if (!state.isNull()) + if (!state.isEmpty()) { - ui->alertTableView->horizontalHeader()->restoreState(state.toByteArray()); + ui->alertTableView->horizontalHeader()->restoreState(state); } } diff --git a/ui/AwardsDialog.cpp b/ui/AwardsDialog.cpp index 29e02164..f8a7ed66 100644 --- a/ui/AwardsDialog.cpp +++ b/ui/AwardsDialog.cpp @@ -5,7 +5,6 @@ #include "models/SqlListModel.h" #include "core/debug.h" #include "data/Band.h" -#include "data/Data.h" #include "data/BandPlan.h" #include MODULE_IDENTIFICATION("qlog.ui.awardsdialog"); @@ -63,7 +62,7 @@ void AwardsDialog::refreshTable(int) { FCT_IDENTIFICATION; - const QList& dxccBands = BandPlan::bandsList(true, true); + const QList& dxccBands = BandPlan::bandsList(false, true); if ( dxccBands.size() == 0 ) return; diff --git a/ui/CWConsoleWidget.cpp b/ui/CWConsoleWidget.cpp index 0ecb3199..c61821b7 100644 --- a/ui/CWConsoleWidget.cpp +++ b/ui/CWConsoleWidget.cpp @@ -31,11 +31,6 @@ CWConsoleWidget::CWConsoleWidget(QWidget *parent) : refreshKeyProfileCombo(); refreshShortcutProfileCombo(); - connect(CWKeyer::instance(), &CWKeyer::cwKeyConnected, this, &CWConsoleWidget::cwKeyConnected); - connect(CWKeyer::instance(), &CWKeyer::cwKeyDisconnected, this, &CWConsoleWidget::cwKeyDisconnected); - connect(Rig::instance(), &Rig::rigConnected, this, &CWConsoleWidget::rigConnectHandler); - connect(Rig::instance(), &Rig::rigDisconnected, this, &CWConsoleWidget::rigDisconnectHandler); - connect(ui->modeSwitch, &SwitchButton::stateChanged, this, &CWConsoleWidget::sendWordSwitched); sendWord = getSendWordConfig(); diff --git a/ui/CWConsoleWidget.h b/ui/CWConsoleWidget.h index a206b3ef..40d0141e 100644 --- a/ui/CWConsoleWidget.h +++ b/ui/CWConsoleWidget.h @@ -30,18 +30,18 @@ public slots: void cwKeySpeedDecrease(); void cwShortcutProfileIncrease(); void cwShortcutProfileDecrease(); + void rigDisconnectHandler(); + void rigConnectHandler(); + void cwKeyConnected(QString); + void cwKeyDisconnected(); private slots: void cwKeyProfileComboChanged(QString); void cwShortcutProfileComboChanged(QString); void refreshKeyProfileCombo(); void refreshShortcutProfileCombo(); - void cwKeyConnected(QString); - void cwKeyDisconnected(); void cwKeySpeedChanged(int); void cwSendButtonPressed(bool insertNewLine = true); - void rigDisconnectHandler(); - void rigConnectHandler(); void cwKeyMacroF1(); void cwKeyMacroF2(); void cwKeyMacroF3(); diff --git a/ui/DxFilterDialog.cpp b/ui/DxFilterDialog.cpp index fc7f2fca..56bbbe62 100644 --- a/ui/DxFilterDialog.cpp +++ b/ui/DxFilterDialog.cpp @@ -203,7 +203,7 @@ void DxFilterDialog::accept() { memberList.append("DUMMYCLUB"); - for ( QCheckBox* item: qAsConst(memberListCheckBoxes) ) + for ( QCheckBox* item: static_cast&>(memberListCheckBoxes) ) { if ( item->isChecked() ) { @@ -244,7 +244,7 @@ void DxFilterDialog::generateMembershipCheckboxes() { int elementIndex = 0; - for ( QCheckBox* item: qAsConst(memberListCheckBoxes) ) + for ( QCheckBox* item: static_cast&>(memberListCheckBoxes) ) { ui->dxMemberGrid->addWidget(item, elementIndex / 3, elementIndex % 3); elementIndex++; diff --git a/ui/DxWidget.cpp b/ui/DxWidget.cpp index 2710ad90..6ca31eac 100644 --- a/ui/DxWidget.cpp +++ b/ui/DxWidget.cpp @@ -12,13 +12,13 @@ #include #include #endif +#include #include "DxWidget.h" #include "ui_DxWidget.h" #include "data/Data.h" #include "DxFilterDialog.h" #include "models/SqlListModel.h" -#include "ui/StyleItemDelegate.h" #include "core/debug.h" #include "data/StationProfile.h" #include "data/WCYSpot.h" @@ -122,7 +122,7 @@ bool DxTableModel::addEntry(DxSpot entry, bool deduplicate, bool shouldInsert = true; if ( deduplicate ) { - for (const DxSpot &record : qAsConst(dxData)) + for (const DxSpot &record : static_cast&>(dxData)) { if ( record.time.secsTo(entry.time) > dedup_interval ) break; @@ -403,18 +403,24 @@ DxWidget::DxWidget(QWidget *parent) : ui->setupUi(this); + setSearchClosed(); + ui->serverSelect->setStyleSheet(QStringLiteral("QComboBox {color: red}")); - dxTableModel = new DxTableModel(this); wcyTableModel = new WCYTableModel(this); wwvTableModel = new WWVTableModel(this); toAllTableModel = new ToAllTableModel(this); + dxTableProxyModel = new SearchFilterProxyModel(ui->dxTable); + dxTableModel = new DxTableModel(dxTableProxyModel); + dxTableProxyModel->setSourceModel(dxTableModel); + QAction *separator = new QAction(this); separator->setSeparator(true); - ui->dxTable->setModel(dxTableModel); + ui->dxTable->setModel(dxTableProxyModel); ui->dxTable->addAction(ui->actionFilter); + ui->dxTable->addAction(ui->actionSearch); ui->dxTable->addAction(ui->actionDisplayedColumns); ui->dxTable->addAction(ui->actionClear); ui->dxTable->addAction(separator); @@ -475,6 +481,7 @@ DxWidget::DxWidget(QWidget *parent) : ui->actionConnectOnStartup->setChecked(getAutoconnectServer()); ui->actionKeepSpots->setChecked(getKeepQSOs()); + dxTableProxyModel->setSearchSkippedCols(dxcListHiddenCols()); } void DxWidget::toggleConnect() @@ -787,31 +794,32 @@ void DxWidget::restoreWidgetSetting() FCT_IDENTIFICATION; QSettings settings; - QVariant state = settings.value("dxc/dxtablestate"); + QByteArray state = settings.value("dxc/dxtablestate").toByteArray(); - if (!state.isNull()) + if (!state.isEmpty()) { - ui->dxTable->horizontalHeader()->restoreState(state.toByteArray()); + ui->dxTable->horizontalHeader()->restoreState(state); } - state = settings.value("dxc/wcytablestate"); + state = settings.value("dxc/wcytablestate").toByteArray(); - if (!state.isNull()) + if (!state.isEmpty()) { - ui->wcyTable->horizontalHeader()->restoreState(state.toByteArray()); + ui->wcyTable->horizontalHeader()->restoreState(state); } - state = settings.value("dxc/wwvtablestate"); + state = settings.value("dxc/wwvtablestate").toByteArray(); - if (!state.isNull()) + if (!state.isEmpty()) { - ui->wwvTable->horizontalHeader()->restoreState(state.toByteArray()); + ui->wwvTable->horizontalHeader()->restoreState(state); } - state = settings.value("dxc/toalltablestate"); - if (!state.isNull()) + state = settings.value("dxc/toalltablestate").toByteArray(); + + if (!state.isEmpty()) { - ui->toAllTable->horizontalHeader()->restoreState(state.toByteArray()); + ui->toAllTable->horizontalHeader()->restoreState(state); } int fontsize = settings.value("dxc/consolefontsize", -1).toInt(); @@ -1181,7 +1189,7 @@ void DxWidget::connected() ui->commandEdit->setEnabled(true); ui->connectButton->setEnabled(true); ui->connectButton->setText(tr("Disconnect")); - ui->commandEdit->setPlaceholderText(""); + ui->commandEdit->setPlaceholderText(tr("DX Cluster Command")); ui->serverSelect->setStyleSheet("QComboBox {color: green}"); connectionState = CONNECTED; saveDXCServers(); @@ -1198,9 +1206,11 @@ void DxWidget::entryDoubleClicked(QModelIndex index) { FCT_IDENTIFICATION; - emit tuneDx(dxTableModel->getCallsign(index), - dxTableModel->getFrequency(index), - dxTableModel->getBandPlanode(index)); + const QModelIndex &source_index = dxTableProxyModel->mapToSource(index); + + emit tuneDx(dxTableModel->getCallsign(source_index), + dxTableModel->getFrequency(source_index), + dxTableModel->getBandPlanode(source_index)); } void DxWidget::actionFilter() @@ -1300,6 +1310,37 @@ void DxWidget::prepareQSOSpot(QSqlRecord qso) } } +void DxWidget::setSearch(const QString &text) +{ + FCT_IDENTIFICATION; + + dxTableProxyModel->setSearchString(text); +} + +void DxWidget::setSearchStatus(bool visible) +{ + FCT_IDENTIFICATION; + + ui->searchEdit->setVisible(visible); + ui->searchEdit->setFocus(); + ui->searchCloseButton->setVisible(visible); + + if (!visible) + ui->searchEdit->clear(); +} + +void DxWidget::setSearchVisible() +{ + FCT_IDENTIFICATION; + setSearchStatus(!ui->searchEdit->isVisible()); +} + +void DxWidget::setSearchClosed() +{ + FCT_IDENTIFICATION; + setSearchStatus(false); +} + void DxWidget::actionCommandSpotQSO() { FCT_IDENTIFICATION; @@ -1433,6 +1474,8 @@ void DxWidget::displayedColumns() ColumnSettingSimpleDialog dialog(view); dialog.exec(); saveWidgetSetting(); + if ( view == ui->dxTable ) + dxTableProxyModel->setSearchSkippedCols(dxcListHiddenCols()); } } @@ -1502,7 +1545,7 @@ void DxWidget::processDxSpot(const QString &spotter, DxSpot spot; - spot.time = (dateTime.isNull()) ? QDateTime::currentDateTime().toTimeSpec(Qt::UTC) + spot.time = (!dateTime.isValid()) ? QDateTime::currentDateTime().toTimeSpec(Qt::UTC) : dateTime; spot.callsign = call; spot.freq = freq.toDouble() / 1000; @@ -1541,6 +1584,20 @@ void DxWidget::processDxSpot(const QString &spotter, } } +QVector DxWidget::dxcListHiddenCols() const +{ + QVector ret; + ret.reserve(dxTableModel->columnCount()); + + for ( int i = 0; i < dxTableModel->columnCount(); ++i ) + { + if (ui->dxTable->isColumnHidden(i)) + ret.append(i); + } + + return ret; +} + BandPlan::BandPlanMode DxWidget::modeGroupFromComment(const QString &comment) const { FCT_IDENTIFICATION; diff --git a/ui/DxWidget.h b/ui/DxWidget.h index 8208ecdf..93f9926d 100644 --- a/ui/DxWidget.h +++ b/ui/DxWidget.h @@ -7,14 +7,13 @@ #include #include -#include "data/Data.h" #include "data/DxSpot.h" #include "data/WCYSpot.h" #include "data/WWVSpot.h" #include "data/ToAllSpot.h" -#include "ui/SwitchButton.h" #include "core/LogLocale.h" #include "core/DxServerString.h" +#include "models/SearchFilterProxyModel.h" // in sec #define DEDUPLICATION_TIME 3 @@ -114,7 +113,6 @@ class DeleteHighlightedDXServerWhenDelPressedEventFilter : public QObject bool eventFilter(QObject *obj, QEvent *event); }; - class DxWidget : public QWidget { Q_OBJECT @@ -136,6 +134,10 @@ public slots: void setLastQSO(QSqlRecord); void reloadSetting(); void prepareQSOSpot(QSqlRecord); + void setSearch(const QString &); + void setSearchStatus(bool); + void setSearchVisible(); + void setSearchClosed(); private slots: void actionCommandSpotQSO(); @@ -174,6 +176,7 @@ private slots: WCYTableModel* wcyTableModel; WWVTableModel* wwvTableModel; ToAllTableModel* toAllTableModel; + SearchFilterProxyModel* dxTableProxyModel; QTcpSocket* socket; Ui::DxWidget *ui; QRegularExpression moderegexp; @@ -224,6 +227,7 @@ private slots: const QString &comment, const QDateTime &dateTime = QDateTime()); + QVector dxcListHiddenCols() const; BandPlan::BandPlanMode modeGroupFromComment(const QString &comment) const; }; diff --git a/ui/DxWidget.ui b/ui/DxWidget.ui index 1486199b..abdc7ec6 100644 --- a/ui/DxWidget.ui +++ b/ui/DxWidget.ui @@ -225,6 +225,46 @@ + + + + 0 + + + + + Qt::ClickFocus + + + Full-text search + + + Search + + + true + + + + + + + Close Search + + + + + + + :/icons/cancel-24px.svg:/icons/cancel-24px.svg + + + true + + + + + @@ -587,6 +627,23 @@ Clear all data + + + Search... + + + DXC - Search + + + Ctrl+D + + + Qt::ApplicationShortcut + + + true + + @@ -880,6 +937,54 @@ + + actionSearch + triggered() + DxWidget + setSearchVisible() + + + -1 + -1 + + + 170 + 255 + + + + + searchCloseButton + clicked() + DxWidget + setSearchClosed() + + + 325 + 462 + + + 170 + 255 + + + + + searchEdit + textChanged(QString) + DxWidget + setSearch(QString) + + + 170 + 463 + + + 170 + 255 + + + send() @@ -903,5 +1008,8 @@ actionForgetPassword() actionKeepSpots() actionClear() + setSearch(QString) + setSearchVisible() + setSearchClosed() diff --git a/ui/DxccTableWidget.cpp b/ui/DxccTableWidget.cpp index db8b0fbb..15633887 100644 --- a/ui/DxccTableWidget.cpp +++ b/ui/DxccTableWidget.cpp @@ -9,7 +9,6 @@ #include "DxccTableWidget.h" #include "core/debug.h" #include "data/StationProfile.h" -#include "data/Data.h" #include "data/BandPlan.h" MODULE_IDENTIFICATION("qlog.ui.dxcctablewidget"); diff --git a/ui/EditLine.cpp b/ui/EditLine.cpp index ec555d1a..075141fc 100644 --- a/ui/EditLine.cpp +++ b/ui/EditLine.cpp @@ -60,3 +60,22 @@ void NewContactEditLine::spaceForbidden(bool inSpaceForbidden) { spaceForbiddenFlag = inSpaceForbidden; } + +NewContactRSTEditLine::NewContactRSTEditLine(QWidget *parent) : + NewContactEditLine(parent), + focusInSelectionBackwardOffset(1) +{ +} + +void NewContactRSTEditLine::setSelectionBackwardOffset(int offset) +{ + focusInSelectionBackwardOffset = offset; +} + +void NewContactRSTEditLine::focusInEvent(QFocusEvent *event) +{ + NewContactEditLine::focusInEvent(event); + + if ( event->reason() != Qt::PopupFocusReason && !text().isEmpty() && text().length() >= focusInSelectionBackwardOffset ) + setSelection(text().length() - focusInSelectionBackwardOffset, 1); +} diff --git a/ui/EditLine.h b/ui/EditLine.h index 4c432a32..eb9e3f78 100644 --- a/ui/EditLine.h +++ b/ui/EditLine.h @@ -24,4 +24,17 @@ class NewContactEditLine : public QLineEdit bool spaceForbiddenFlag; }; +class NewContactRSTEditLine : public NewContactEditLine +{ + Q_OBJECT + +public: + explicit NewContactRSTEditLine(QWidget *parent = nullptr); + void setSelectionBackwardOffset(int offset); + +protected: + void focusInEvent(QFocusEvent* event) override; + int focusInSelectionBackwardOffset; +}; + #endif // QLOG_UI_EDITLINE_H diff --git a/ui/FreqQSpinBox.cpp b/ui/FreqQSpinBox.cpp index 6a84bf2e..949eaa8a 100644 --- a/ui/FreqQSpinBox.cpp +++ b/ui/FreqQSpinBox.cpp @@ -50,7 +50,7 @@ void FreqQSpinBox::increaseByBand() if ( enabledBands.size() == 0 ) return; - for ( const Band &band : qAsConst(enabledBands) ) + for ( const Band &band : static_cast&>(enabledBands) ) { if ( band.start > value() ) { @@ -68,7 +68,7 @@ void FreqQSpinBox::decreaseByBand() double result = enabledBands.at(0).start; - for ( const Band &band : qAsConst(enabledBands) ) + for ( const Band &band : static_cast&>(enabledBands) ) { if ( band.start < value() ) result = band.start; diff --git a/ui/FreqQSpinBox.h b/ui/FreqQSpinBox.h index 220bcdd0..53828ef7 100644 --- a/ui/FreqQSpinBox.h +++ b/ui/FreqQSpinBox.h @@ -1,5 +1,5 @@ -#ifndef FREQQSPINBOX_H -#define FREQQSPINBOX_H +#ifndef QLOG_UI_FREQQSPINBOX_H +#define QLOG_UI_FREQQSPINBOX_H #include #include @@ -23,4 +23,4 @@ public slots: QList enabledBands; }; -#endif // FREQQSPINBOX_H +#endif // QLOG_UI_FREQQSPINBOX_H diff --git a/ui/HRDLogDialog.cpp b/ui/HRDLogDialog.cpp index ac84de94..eadcc2c8 100644 --- a/ui/HRDLogDialog.cpp +++ b/ui/HRDLogDialog.cpp @@ -7,7 +7,6 @@ #include "HRDLogDialog.h" #include "ui_HRDLogDialog.h" #include "models/SqlListModel.h" -#include "logformat/AdiFormat.h" #include "core/debug.h" #include "ui/ShowUploadDialog.h" #include "core/HRDLog.h" diff --git a/ui/ImportDialog.cpp b/ui/ImportDialog.cpp index 1716fffc..52272376 100644 --- a/ui/ImportDialog.cpp +++ b/ui/ImportDialog.cpp @@ -5,9 +5,7 @@ #include "logformat/LogFormat.h" #include "core/debug.h" #include "data/StationProfile.h" -#include "core/Gridsquare.h" #include "data/RigProfile.h" -#include "data/Data.h" MODULE_IDENTIFICATION("qlog.ui.importdialog"); @@ -232,7 +230,8 @@ void ImportDialog::saveImportDetails(const QString &importDetail, const QString } } -void ImportDialog::runImport() { +void ImportDialog::runImport() +{ FCT_IDENTIFICATION; if ( ui->fileEdit->text().isEmpty() ) @@ -260,70 +259,6 @@ void ImportDialog::runImport() { defaults["comment_intl"] = ui->commentEdit->text(); } - if ( ui->profileCheckBox->isChecked() - && selectedStationProfile != StationProfile() ) - { - if ( !selectedStationProfile.callsign.isEmpty() ) - { - defaults["station_callsign"] = selectedStationProfile.callsign.toUpper(); - } - - if ( !selectedStationProfile.locator.isEmpty() ) - { - defaults["my_gridsquare"] = selectedStationProfile.locator.toUpper(); - } - - if ( !selectedStationProfile.operatorName.isEmpty() ) - { - defaults["my_name_intl"] = selectedStationProfile.operatorName; - } - - if ( !selectedStationProfile.qthName.isEmpty() ) - { - defaults["my_city_intl"] = selectedStationProfile.qthName; - } - - if ( !selectedStationProfile.iota.isEmpty() ) - { - defaults["my_iota"] = Data::removeAccents(selectedStationProfile.iota.toUpper()); - } - - if ( !selectedStationProfile.sota.isEmpty() ) - { - defaults["my_sota_ref"] = Data::removeAccents(selectedStationProfile.sota.toUpper()); - } - - if ( !selectedStationProfile.sig.isEmpty() ) - { - defaults["my_sig_intl"] = Data::removeAccents(selectedStationProfile.sig); - } - - if ( !selectedStationProfile.sigInfo.isEmpty() ) - { - defaults["my_sig_info_intl"] = selectedStationProfile.sigInfo; - } - - if ( !selectedStationProfile.vucc.isEmpty() ) - { - defaults["my_vucc_grids"] = selectedStationProfile.vucc.toUpper(); - } - - if ( !selectedStationProfile.vucc.isEmpty() ) - { - defaults["my_wwff_ref"] = Data::removeAccents(selectedStationProfile.vucc.toUpper()); - } - - if ( !selectedStationProfile.pota.isEmpty() ) - { - defaults["my_pota_ref"] = Data::removeAccents(selectedStationProfile.pota.toUpper()); - } - - defaults["my_dxcc"] = QString::number(selectedStationProfile.dxcc); - defaults["my_itu_zone"] = QString::number(selectedStationProfile.ituz); - defaults["my_cq_zone"] = QString::number(selectedStationProfile.cqz); - defaults["my_country_intl"] = selectedStationProfile.country; - } - LogFormat* format = LogFormat::open(ui->typeSelect->currentText(), in); if (!format) { @@ -362,7 +297,10 @@ void ImportDialog::runImport() { unsigned long errors = 0L; unsigned long warnings = 0L; - int count = format->runImport(out, &warnings, &errors); + int count = format->runImport(out, + ( ui->profileCheckBox->isChecked() && selectedStationProfile != StationProfile() ) ?&selectedStationProfile: nullptr, + &warnings, + &errors); QString report = QObject::tr("Imported: %n contact(s)", "", count) + "
    " + QObject::tr("Warning(s): %n", "", warnings) + "
    " + diff --git a/ui/KSTHighlightRuleDetail.cpp b/ui/KSTHighlightRuleDetail.cpp index 69fbde7b..e2465d61 100644 --- a/ui/KSTHighlightRuleDetail.cpp +++ b/ui/KSTHighlightRuleDetail.cpp @@ -152,8 +152,8 @@ void KSTHighlightRuleDetail::save() rule.enabled = ui->enabledCheckbox->isChecked(); rule.interConditionOperand = static_cast(ui->matchCombo->currentIndex()); - QList conditionLayouts = ui->conditionsLayout->findChildren(); - for (auto &conditionLine: qAsConst(conditionLayouts) ) + const QList &conditionLayouts = ui->conditionsLayout->findChildren(); + for (auto &conditionLine: conditionLayouts ) { chatHighlightRule::Condition condition; for ( int i = 0; i < 3; i++ ) @@ -217,7 +217,7 @@ void KSTHighlightRuleDetail::loadRule(const QString &ruleName) ui->enabledCheckbox->setChecked(rule.enabled); ui->matchCombo->setCurrentIndex(rule.interConditionOperand); - for ( const chatHighlightRule::Condition &condition : qAsConst(rule.conditions)) + for ( const chatHighlightRule::Condition &condition : static_cast&>(rule.conditions)) { addCondition(condition.source, condition.operatorID, diff --git a/ui/LogbookWidget.cpp b/ui/LogbookWidget.cpp index 1372088b..66cd60b2 100644 --- a/ui/LogbookWidget.cpp +++ b/ui/LogbookWidget.cpp @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include "logformat/AdiFormat.h" #include "models/LogbookModel.h" @@ -21,7 +23,6 @@ #include "ui/ExportDialog.h" #include "core/Eqsl.h" #include "ui/PaperQSLDialog.h" -#include "core/NetworkNotification.h" #include "ui/QSODetailDialog.h" #include "core/MembershipQE.h" #include "core/GenericCallbook.h" @@ -41,6 +42,7 @@ LogbookWidget::LogbookWidget(QWidget *parent) : model = new LogbookModel(this); connect(model, &LogbookModel::beforeUpdate, this, &LogbookWidget::handleBeforeUpdate); connect(model, &LogbookModel::beforeDelete, this, &LogbookWidget::handleBeforeDelete); + connect(ui->contactTable, &QTableQSOView::dataCommitted, this, [this](){emit logbookUpdated();}); ui->contactTable->setModel(model); @@ -60,12 +62,9 @@ LogbookWidget::LogbookWidget(QWidget *parent) : ui->contactTable->addAction(separator1); ui->contactTable->addAction(ui->actionDeleteContact); - //ui->contactTable->sortByColumn(1, Qt::DescendingOrder); - ui->contactTable->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu); connect(ui->contactTable->horizontalHeader(), &QHeaderView::customContextMenuRequested, this, &LogbookWidget::showTableHeaderContextMenu); - connect(ui->contactTable, &QTableQSOView::dataCommitted, this, &LogbookWidget::updateTable); ui->contactTable->setItemDelegateForColumn(LogbookModel::COLUMN_TIME_ON, new TimestampFormatDelegate(ui->contactTable)); ui->contactTable->setItemDelegateForColumn(LogbookModel::COLUMN_TIME_OFF, new TimestampFormatDelegate(ui->contactTable)); @@ -140,9 +139,9 @@ LogbookWidget::LogbookWidget(QWidget *parent) : ui->contactTable->setItemDelegateForColumn(LogbookModel::COLUMN_UKSMG, new UnitFormatDelegate("", 0, 1, ui->contactTable)); QSettings settings; - QVariant logbookState = settings.value("logbook/state"); - if (!logbookState.isNull()) { - ui->contactTable->horizontalHeader()->restoreState(logbookState.toByteArray()); + const QByteArray &logbookState = settings.value("logbook/state").toByteArray(); + if (!logbookState.isEmpty()) { + ui->contactTable->horizontalHeader()->restoreState(logbookState); } else { /* Hide all */ @@ -164,6 +163,7 @@ LogbookWidget::LogbookWidget(QWidget *parent) : ui->contactTable->horizontalHeader()->setSectionsMovable(true); ui->contactTable->setStyle(new ProxyStyle(ui->contactTable->style())); + ui->contactTable->installEventFilter(this); ui->bandFilter->blockSignals(true); ui->bandFilter->setModel(new SqlListModel("SELECT name FROM bands ORDER BY start_freq", tr("Band"), this)); @@ -178,9 +178,8 @@ LogbookWidget::LogbookWidget(QWidget *parent) : "FROM dxcc_entities WHERE id IN (SELECT DISTINCT dxcc FROM contacts) " "ORDER BY 2 COLLATE LOCALEAWARE ASC;", tr("Country"), this); while (countryModel->canFetchMore()) - { countryModel->fetchMore(); - } + ui->countryFilter->setModel(countryModel); ui->countryFilter->setModelColumn(1); ui->countryFilter->blockSignals(false); @@ -188,11 +187,11 @@ LogbookWidget::LogbookWidget(QWidget *parent) : refreshClubFilter(); ui->userFilter->blockSignals(true); - userFilterModel = new SqlListModel("SELECT filter_name FROM qso_filters ORDER BY filter_name", tr("User Filter"), this); + userFilterModel = new SqlListModel("SELECT filter_name " + "FROM qso_filters " + "ORDER BY filter_name", tr("User Filter"), this); while (userFilterModel->canFetchMore()) - { userFilterModel->fetchMore(); - } ui->userFilter->setModel(userFilterModel); ui->userFilter->blockSignals(false); @@ -226,22 +225,14 @@ void LogbookWidget::filterCountryBand(const QString &countryName, ui->clubFilter->blockSignals(true); if ( ! countryName.isEmpty() ) - { ui->countryFilter->setCurrentText(countryName); - } else - { ui->countryFilter->setCurrentIndex(0); - } if ( !band.isEmpty() ) - { ui->bandFilter->setCurrentText(band); - } else - { ui->bandFilter->setCurrentIndex(0); - } //user wants to see only selected band and country ui->userFilter->setCurrentIndex(0); //suppress user-defined filter @@ -257,7 +248,7 @@ void LogbookWidget::filterCountryBand(const QString &countryName, ui->countryFilter->blockSignals(false); ui->bandFilter->blockSignals(false); - updateTable(); + filterTable(); } void LogbookWidget::lookupSelectedCallsign() @@ -286,7 +277,7 @@ void LogbookWidget::callsignFilterChanged() { FCT_IDENTIFICATION; - updateTable(); + filterTable(); } void LogbookWidget::bandFilterChanged() @@ -295,7 +286,7 @@ void LogbookWidget::bandFilterChanged() colorsFilterWidget(ui->bandFilter); saveBandFilter(); - updateTable(); + filterTable();; } void LogbookWidget::saveBandFilter() @@ -314,13 +305,9 @@ void LogbookWidget::restoreBandFilter() ui->bandFilter->blockSignals(true); const QString &value = settings.value("logbook/filters/band").toString(); if ( !value.isEmpty() ) - { ui->bandFilter->setCurrentText(value); - } else - { ui->bandFilter->setCurrentIndex(0); - } colorsFilterWidget(ui->bandFilter); ui->bandFilter->blockSignals(false); @@ -332,7 +319,7 @@ void LogbookWidget::modeFilterChanged() colorsFilterWidget(ui->modeFilter); saveModeFilter(); - updateTable(); + filterTable(); } void LogbookWidget::saveModeFilter() @@ -351,13 +338,10 @@ void LogbookWidget::restoreModeFilter() ui->modeFilter->blockSignals(true); const QString &value = settings.value("logbook/filters/mode").toString(); if ( !value.isEmpty() ) - { ui->modeFilter->setCurrentText(value); - } else - { ui->modeFilter->setCurrentIndex(0); - } + colorsFilterWidget(ui->modeFilter); ui->modeFilter->blockSignals(false); } @@ -368,7 +352,7 @@ void LogbookWidget::countryFilterChanged() colorsFilterWidget(ui->countryFilter); saveCountryFilter(); - updateTable(); + filterTable(); } void LogbookWidget::saveCountryFilter() @@ -387,13 +371,9 @@ void LogbookWidget::restoreCountryFilter() ui->countryFilter->blockSignals(true); const QString &value = settings.value("logbook/filters/country").toString(); if ( !value.isEmpty() ) - { ui->countryFilter->setCurrentText(value); - } else - { ui->countryFilter->setCurrentIndex(0); - } colorsFilterWidget(ui->countryFilter); ui->countryFilter->blockSignals(false); @@ -405,7 +385,7 @@ void LogbookWidget::userFilterChanged() colorsFilterWidget(ui->userFilter); saveUserFilter(); - updateTable(); + filterTable(); } void LogbookWidget::saveUserFilter() @@ -424,13 +404,10 @@ void LogbookWidget::restoreUserFilter() ui->userFilter->blockSignals(true); const QString &value = settings.value("logbook/filters/user").toString(); if ( !value.isEmpty() ) - { ui->userFilter->setCurrentText(value); - } else - { ui->userFilter->setCurrentIndex(0); - } + colorsFilterWidget(ui->userFilter); ui->userFilter->blockSignals(false); } @@ -441,7 +418,7 @@ void LogbookWidget::clubFilterChanged() colorsFilterWidget(ui->clubFilter); saveClubFilter(); - updateTable(); + filterTable(); } void LogbookWidget::refreshClubFilter() @@ -454,6 +431,23 @@ void LogbookWidget::refreshClubFilter() ui->clubFilter->addItems(QStringList(tr("Club")) << MembershipQE::instance()->getEnabledClubLists()); ui->clubFilter->setCurrentText(member); ui->clubFilter->blockSignals(false); + colorsFilterWidget(ui->clubFilter); +} + +void LogbookWidget::refreshUserFilter() +{ + FCT_IDENTIFICATION; + + /* Refresh dynamic User Filter selection combobox */ + /* block the signals !!! */ + ui->userFilter->blockSignals(true); + const QString &userFilterString = ui->userFilter->currentText(); + userFilterModel->refresh(); + ui->userFilter->setCurrentText(userFilterString); + ui->userFilter->blockSignals(false); + colorsFilterWidget(ui->userFilter); + + filterTable(); } void LogbookWidget::saveClubFilter() @@ -462,19 +456,16 @@ void LogbookWidget::saveClubFilter() settings.setValue("logbook/filters/member", ui->clubFilter->currentText()); } -void LogbookWidget::restoreclubFilter() +void LogbookWidget::restoreClubFilter() { QSettings settings; ui->clubFilter->blockSignals(true); const QString &value = settings.value("logbook/filters/member").toString(); if ( !value.isEmpty() ) - { ui->clubFilter->setCurrentText(value); - } else - { ui->clubFilter->setCurrentIndex(0); - } + colorsFilterWidget(ui->clubFilter); ui->clubFilter->blockSignals(false); } @@ -486,10 +477,10 @@ void LogbookWidget::restoreFilters() restoreModeFilter(); restoreBandFilter(); restoreCountryFilter(); - restoreclubFilter(); + restoreClubFilter(); restoreUserFilter(); externalFilter = QString(); - updateTable(); + filterTable(); } void LogbookWidget::uploadClublog() @@ -523,6 +514,13 @@ void LogbookWidget::deleteContact() QModelIndexList deletedRowIndexes = ui->contactTable->selectionModel()->selectedRows(); + // Since deletedRowIndexes contains indexes for columns that might be invisible, + // and scrollToIndex needs an index with a visible column, + // we obtain the column index from the first record in the table." + + int firstVisibleColumnIndex = ui->contactTable->indexAt(QPoint(0, 0)).column(); + QModelIndex previousIndex = model->index(deletedRowIndexes.first().row()-1, firstVisibleColumnIndex); + // Clublog does not accept batch DELETE operation // ask if an operator wants to continue if ( ClubLog::isUploadImmediatelyEnabled() @@ -535,13 +533,9 @@ void LogbookWidget::deleteContact() "that the DELETE operation will not be sent to Clublog?"), QMessageBox::Yes|QMessageBox::No); if ( reply != QMessageBox::Yes ) - { return; - } else - { blockClublogSignals = true; - } } std::sort(deletedRowIndexes.begin(), @@ -573,7 +567,7 @@ void LogbookWidget::deleteContact() int cnt = 0; - for ( const QModelIndex &index : qAsConst(deletedRowIndexes) ) + for ( const QModelIndex &index : static_cast(deletedRowIndexes) ) { cnt++; model->removeRow(index.row()); @@ -593,6 +587,7 @@ void LogbookWidget::deleteContact() ui->contactTable->setUpdatesEnabled(true); ui->contactTable->horizontalHeader()->restoreState(state); updateTable(); + scrollToIndex(previousIndex); blockClublogSignals = false; } @@ -642,118 +637,56 @@ void LogbookWidget::displayedColumns() saveTableHeaderState(); } -void LogbookWidget::updateTable() +void LogbookWidget::reselectModel() { FCT_IDENTIFICATION; - QStringList filterString; + model->select(); - const QString &callsignFilterValue = ui->callsignFilter->text(); + // under normal conditions, only 256 records are loaded. + // This will increase the value of the loaded records. + while ( model->canFetchMore() && model->rowCount() < 5000 ) + model->fetchMore(); - if ( !callsignFilterValue.isEmpty() ) + // it is not possible to use mode->rowCount here because model contains only + // the first 5000 records (or more) and rowCount has a value 5000 here. Therefore, it is needed + // to run a QSL stateme with Count. Run it only in case when QTableview does not contain all + // records from model + int qsoCount = 0; + if ( model->canFetchMore() ) { - filterString.append(QString("callsign LIKE '%%1%'").arg(callsignFilterValue.toUpper())); - } + QString countRecordsStmt(QLatin1String("SELECT COUNT(1) FROM contacts")); - const QString &bandFilterValue = ui->bandFilter->currentText(); + if ( !model->filter().isEmpty() ) + countRecordsStmt.append(QString(" WHERE %1").arg(model->filter())); - if ( ui->bandFilter->currentIndex() != 0 && !bandFilterValue.isEmpty()) - { - filterString.append(QString("band = '%1'").arg(bandFilterValue)); + QSqlQuery query(countRecordsStmt); + + qsoCount = query.first() ? query.value(0).toInt() : 0; } + else + qsoCount = model->rowCount(); - const QString &modeFilterValue = ui->modeFilter->currentText(); + ui->filteredQSOsLabel->setText(tr("Count: %n", "", qsoCount)); +} - if ( ui->modeFilter->currentIndex() != 0 && !modeFilterValue.isEmpty() ) - { - filterString.append(QString("mode = '%1'").arg(modeFilterValue)); - } +void LogbookWidget::updateTable() +{ + FCT_IDENTIFICATION; + + reselectModel(); - /* Refresh dynamic Country selection combobox */ - /* It is important to block its signals */ + // it is called when QSO is inserted/updated/deleted + // therefore it is needed to refresh country select box + + /* Refresh country selection combobox */ + /* block the signals !!! */ ui->countryFilter->blockSignals(true); const QString &country = ui->countryFilter->currentText(); countryModel->refresh(); ui->countryFilter->setCurrentText(country); ui->countryFilter->blockSignals(false); - - int row = ui->countryFilter->currentIndex(); - const QModelIndex &idx = ui->countryFilter->model()->index(row,0); - QVariant data = ui->countryFilter->model()->data(idx); - - if ( ui->countryFilter->currentIndex() != 0 ) - { - filterString.append(QString("dxcc = '%1'").arg(data.toInt())); - } - - if ( ui->clubFilter->currentIndex() != 0 ) - { - filterString.append(QString("id in (SELECT contactid FROM contact_clubs_view WHERE clubid = '%1')").arg(ui->clubFilter->currentText())); - } - - /* Refresh dynamic User Filter selection combobox */ - /* block the signals !!! */ - ui->userFilter->blockSignals(true); - const QString &userFilterString = ui->userFilter->currentText(); - userFilterModel->refresh(); - ui->userFilter->setCurrentText(userFilterString); - ui->userFilter->blockSignals(false); - - if ( ui->userFilter->currentIndex() != 0 ) - { - QSqlQuery userFilterQuery; - if ( ! userFilterQuery.prepare("SELECT " - "'(' || GROUP_CONCAT( ' ' || c.name || ' ' || CASE WHEN r.value IS NULL AND o.sql_operator IN ('=', 'like') THEN 'IS' " - " WHEN r.value IS NULL and r.operator_id NOT IN ('=', 'like') THEN 'IS NOT' " - " WHEN o.sql_operator = ('starts with') THEN 'like' " - " ELSE o.sql_operator END || " - "' (' || quote(CASE o.sql_operator WHEN 'like' THEN '%' || r.value || '%' " - " WHEN 'not like' THEN '%' || r.value || '%' " - " WHEN 'starts with' THEN r.value || '%' " - " ELSE r.value END) || ') ', m.sql_operator) || ')' " - "FROM qso_filters f, qso_filter_rules r, " - "qso_filter_operators o, qso_filter_matching_types m, " - "PRAGMA_TABLE_INFO('contacts') c " - "WHERE f.filter_name = :filterName " - " AND f.filter_name = r.filter_name " - " AND o.operator_id = r.operator_id " - " AND m.matching_id = f.matching_type " - " AND c.cid = r.table_field_index") ) - { - qWarning() << "Cannot prepare select statement"; - return; - } - - userFilterQuery.bindValue(":filterName", ui->userFilter->currentText()); - - qCDebug(runtime) << "User filter SQL: " << userFilterQuery.lastQuery(); - - if ( userFilterQuery.exec() ) - { - userFilterQuery.next(); - filterString.append(QString("( ") + userFilterQuery.value(0).toString() + ")"); - } - else - { - qCDebug(runtime) << "User filter error - " << userFilterQuery.lastError().text(); - } - } - - if ( !externalFilter.isEmpty() ) - { - filterString.append(QString("( ") + externalFilter + ")"); - } - - qCDebug(runtime) << "SQL filter summary: " << filterString.join(" AND "); - model->setFilter(filterString.join(" AND ")); - qCDebug(runtime) << model->query().lastQuery(); - - model->select(); - while (model->canFetchMore()) - model->fetchMore(); - - ui->contactTable->resizeColumnsToContents(); - ui->filteredQSOsLabel->setText(tr("Count: %n", "", model->rowCount())); + colorsFilterWidget(ui->countryFilter); emit logbookUpdated(); } @@ -854,6 +787,7 @@ void LogbookWidget::doubleClickColumn(QModelIndex modelIndex) }); dialog.exec(); updateTable(); + scrollToIndex(modelIndex); } } @@ -901,6 +835,43 @@ void LogbookWidget::sendDXCSpot() emit sendDXSpotContactReq(model->record(selectedIndexes.at(0).row())); } +void LogbookWidget::scrollToIndex(const QModelIndex &index, bool selectItem) +{ + FCT_IDENTIFICATION; + + if ( index == QModelIndex() ) + return; + + // is index visible ? + if ( ui->contactTable->visualRect(index).isEmpty() ) + { + while ( model->canFetchMore() && ui->contactTable->visualRect(index).isEmpty() ) + model->fetchMore(); + + if ( model->canFetchMore() ) + model->fetchMore(); // one more fetch + } + + ui->contactTable->scrollTo(index, QAbstractItemView::PositionAtCenter); + if ( selectItem ) + ui->contactTable->selectRow(index.row()); +} + +bool LogbookWidget::eventFilter(QObject *obj, QEvent *event) +{ + //FCT_IDENTIFICATION; + + if ( event->type() == QEvent::KeyPress && obj == ui->contactTable ) + { + QKeyEvent *keyEvent = static_cast(event); + // Block SelectAll + if ( QKeySequence(keyEvent->modifiers() | keyEvent->key()) == QKeySequence::SelectAll ) + return true; + } + + return QObject::eventFilter(obj, event); +} + void LogbookWidget::colorsFilterWidget(QComboBox *widget) { FCT_IDENTIFICATION; @@ -909,7 +880,86 @@ void LogbookWidget::colorsFilterWidget(QComboBox *widget) : ""); } -LogbookWidget::~LogbookWidget() { +void LogbookWidget::filterTable() +{ + FCT_IDENTIFICATION; + + QStringList filterString; + + const QString &callsignFilterValue = ui->callsignFilter->text(); + + if ( !callsignFilterValue.isEmpty() ) + filterString.append(QString("callsign LIKE '%%1%'").arg(callsignFilterValue.toUpper())); + + const QString &bandFilterValue = ui->bandFilter->currentText(); + + if ( ui->bandFilter->currentIndex() != 0 && !bandFilterValue.isEmpty()) + filterString.append(QString("band = '%1'").arg(bandFilterValue)); + + const QString &modeFilterValue = ui->modeFilter->currentText(); + + if ( ui->modeFilter->currentIndex() != 0 && !modeFilterValue.isEmpty() ) + filterString.append(QString("mode = '%1'").arg(modeFilterValue)); + + int row = ui->countryFilter->currentIndex(); + const QModelIndex &idx = ui->countryFilter->model()->index(row,0); + const QVariant &data = ui->countryFilter->model()->data(idx); + + if ( ui->countryFilter->currentIndex() != 0 ) + filterString.append(QString("dxcc = '%1'").arg(data.toInt())); + + if ( ui->clubFilter->currentIndex() != 0 ) + filterString.append(QString("id in (SELECT contactid FROM contact_clubs_view WHERE clubid = '%1')").arg(ui->clubFilter->currentText())); + + if ( ui->userFilter->currentIndex() != 0 ) + { + QSqlQuery userFilterQuery; + if ( ! userFilterQuery.prepare("SELECT " + "'(' || GROUP_CONCAT( ' ' || c.name || ' ' || CASE WHEN r.value IS NULL AND o.sql_operator IN ('=', 'like') THEN 'IS' " + " WHEN r.value IS NULL and r.operator_id NOT IN ('=', 'like') THEN 'IS NOT' " + " WHEN o.sql_operator = ('starts with') THEN 'like' " + " ELSE o.sql_operator END || " + "' (' || quote(CASE o.sql_operator WHEN 'like' THEN '%' || r.value || '%' " + " WHEN 'not like' THEN '%' || r.value || '%' " + " WHEN 'starts with' THEN r.value || '%' " + " ELSE r.value END) || ') ', m.sql_operator) || ')' " + "FROM qso_filters f, qso_filter_rules r, " + "qso_filter_operators o, qso_filter_matching_types m, " + "PRAGMA_TABLE_INFO('contacts') c " + "WHERE f.filter_name = :filterName " + " AND f.filter_name = r.filter_name " + " AND o.operator_id = r.operator_id " + " AND m.matching_id = f.matching_type " + " AND c.cid = r.table_field_index") ) + { + qWarning() << "Cannot prepare select statement"; + return; + } + + userFilterQuery.bindValue(":filterName", ui->userFilter->currentText()); + + qCDebug(runtime) << "User filter SQL: " << userFilterQuery.lastQuery(); + + if ( userFilterQuery.exec() ) + { + userFilterQuery.next(); + filterString.append(QString("( ") + userFilterQuery.value(0).toString() + ")"); + } + else + qCDebug(runtime) << "User filter error - " << userFilterQuery.lastError().text(); + } + + if ( !externalFilter.isEmpty() ) + filterString.append(QString("( ") + externalFilter + ")"); + + model->setFilter(filterString.join(" AND ")); + qCDebug(runtime) << model->query().lastQuery(); + + reselectModel(); +} + +LogbookWidget::~LogbookWidget() +{ FCT_IDENTIFICATION; saveTableHeaderState(); diff --git a/ui/LogbookWidget.h b/ui/LogbookWidget.h index 0fc61556..75bf26fd 100644 --- a/ui/LogbookWidget.h +++ b/ui/LogbookWidget.h @@ -42,21 +42,12 @@ public slots: void lookupSelectedCallsign(); void callsignFilterChanged(); void bandFilterChanged(); - void saveBandFilter(); - void restoreBandFilter(); void modeFilterChanged(); - void saveModeFilter(); - void restoreModeFilter(); void countryFilterChanged(); - void saveCountryFilter(); - void restoreCountryFilter(); void userFilterChanged(); - void saveUserFilter(); - void restoreUserFilter(); void clubFilterChanged(); void refreshClubFilter(); - void saveClubFilter(); - void restoreclubFilter(); + void refreshUserFilter(); void restoreFilters(); void updateTable(); void uploadClublog(); @@ -81,8 +72,22 @@ public slots: SqlListModel* userFilterModel; QString externalFilter; bool blockClublogSignals; + bool eventFilter(QObject *obj, QEvent *event); void colorsFilterWidget(QComboBox *widget); + void filterTable(); + void saveBandFilter(); + void restoreBandFilter(); + void saveModeFilter(); + void restoreModeFilter(); + void saveCountryFilter(); + void restoreCountryFilter(); + void saveUserFilter(); + void restoreUserFilter(); + void saveClubFilter(); + void restoreClubFilter(); + void reselectModel(); + void scrollToIndex(const QModelIndex& index, bool select = true); }; /* https://forum.qt.io/topic/90403/show-tooltip-immediatly/7/ */ diff --git a/ui/MainLayoutEditor.cpp b/ui/MainLayoutEditor.cpp index 31922ba6..442bc5cf 100644 --- a/ui/MainLayoutEditor.cpp +++ b/ui/MainLayoutEditor.cpp @@ -369,7 +369,7 @@ QList MainLayoutEditor::getFieldIndexes(StringListModel *model) const QStringList &list = model->stringList(); QList ret; - for ( const QString &fieldName : qAsConst(list) ) + for ( const QString &fieldName : list ) { int index = dynamicWidgets->getIndex4FieldLabelName(fieldName); if ( index >= 0 ) @@ -383,35 +383,35 @@ void MainLayoutEditor::fillWidgets(const MainLayoutProfile &profile) { FCT_IDENTIFICATION; - for ( int fieldIndex : qAsConst(profile.rowA) ) + for ( int fieldIndex : static_cast&>(profile.rowA) ) { QString fieldName = dynamicWidgets->getFieldLabelName4Index(fieldIndex); qsoRowAFieldsModel->append(fieldName); availableFieldsModel->deleteItem(fieldName); } - for ( int fieldIndex : qAsConst(profile.rowB) ) + for ( int fieldIndex : static_cast&>(profile.rowB) ) { QString fieldName = dynamicWidgets->getFieldLabelName4Index(fieldIndex); qsoRowBFieldsModel->append(fieldName); availableFieldsModel->deleteItem(fieldName); } - for ( int fieldIndex : qAsConst(profile.detailColA) ) + for ( int fieldIndex : static_cast&>(profile.detailColA) ) { QString fieldName = dynamicWidgets->getFieldLabelName4Index(fieldIndex); detailColAFieldsModel->append(fieldName); availableFieldsModel->deleteItem(fieldName); } - for ( int fieldIndex : qAsConst(profile.detailColB) ) + for ( int fieldIndex : static_cast&>(profile.detailColB) ) { QString fieldName = dynamicWidgets->getFieldLabelName4Index(fieldIndex); detailColBFieldsModel->append(fieldName); availableFieldsModel->deleteItem(fieldName); } - for ( int fieldIndex : qAsConst(profile.detailColC) ) + for ( int fieldIndex : static_cast&>(profile.detailColC) ) { QString fieldName = dynamicWidgets->getFieldLabelName4Index(fieldIndex); detailColCFieldsModel->append(fieldName); diff --git a/ui/MainLayoutEditor.h b/ui/MainLayoutEditor.h index aec73f8f..d307d339 100644 --- a/ui/MainLayoutEditor.h +++ b/ui/MainLayoutEditor.h @@ -4,8 +4,6 @@ #include #include #include -#include "models/LogbookModel.h" -#include "core/debug.h" #include "ui/NewContactWidget.h" #include "data/MainLayoutProfile.h" @@ -34,13 +32,13 @@ class StringListModel : public QStringListModel void deleteItem(const QString &value) { - QModelIndexList itemIndexList = match(index(0,0), + const QModelIndexList &itemIndexList = match(index(0,0), Qt::DisplayRole, value, 1, Qt::MatchExactly); - for (const QModelIndex & itemIndex: qAsConst(itemIndexList)) + for ( const QModelIndex & itemIndex: itemIndexList ) { deleteItem(itemIndex); } diff --git a/ui/MainWindow.cpp b/ui/MainWindow.cpp index acdb2f72..f93af21d 100644 --- a/ui/MainWindow.cpp +++ b/ui/MainWindow.cpp @@ -13,7 +13,6 @@ #include "rotator/Rotator.h" #include "cwkey/CWKeyer.h" #include "core/Wsjtx.h" -#include "data/Data.h" #include "core/debug.h" #include "ui/NewContactWidget.h" #include "ui/QSOFilterDialog.h" @@ -24,8 +23,6 @@ #include "core/Lotw.h" #include "core/Eqsl.h" #include "core/QRZ.h" -#include "core/CredentialStore.h" -#include "AlertSettingDialog.h" #include "core/PropConditions.h" #include "data/MainLayoutProfile.h" #include "ui/EditLayoutDialog.h" @@ -140,16 +137,37 @@ MainWindow::MainWindow(QWidget* parent) : connect(Rig::instance(), &Rig::rigCWKeyCloseRequest, this, &MainWindow::cwKeyerDisconnectProfile); connect(Rig::instance(), &Rig::frequencyChanged, ui->onlineMapWidget, &OnlineMapWidget::setIBPBand); connect(Rig::instance(), &Rig::frequencyChanged, ui->bandmapWidget , &BandmapWidget::updateTunedFrequency); + connect(Rig::instance(), &Rig::frequencyChanged, ui->newContactWidget, &NewContactWidget::changeFrequency); + connect(Rig::instance(), &Rig::frequencyChanged, ui->rigWidget, &RigWidget::updateFrequency); connect(Rig::instance(), &Rig::modeChanged, ui->bandmapWidget, &BandmapWidget::updateMode); + connect(Rig::instance(), &Rig::modeChanged, ui->newContactWidget, &NewContactWidget::changeModefromRig); + connect(Rig::instance(), &Rig::modeChanged, ui->rigWidget, &RigWidget::updateMode); + connect(Rig::instance(), &Rig::powerChanged, ui->newContactWidget, &NewContactWidget::changePower); + connect(Rig::instance(), &Rig::powerChanged, ui->rigWidget, &RigWidget::updatePWR); + connect(Rig::instance(), &Rig::rigConnected, ui->newContactWidget, &NewContactWidget::rigConnected); + connect(Rig::instance(), &Rig::rigConnected, ui->rigWidget, &RigWidget::rigConnected); + connect(Rig::instance(), &Rig::rigConnected, ui->cwconsoleWidget, &CWConsoleWidget::rigConnectHandler); + connect(Rig::instance(), &Rig::rigDisconnected, ui->cwconsoleWidget, &CWConsoleWidget::rigDisconnectHandler); + connect(Rig::instance(), &Rig::rigDisconnected, ui->newContactWidget, &NewContactWidget::rigDisconnected); + connect(Rig::instance(), &Rig::rigDisconnected, ui->rigWidget, &RigWidget::rigDisconnected); + connect(Rig::instance(), &Rig::vfoChanged, ui->rigWidget, &RigWidget::updateVFO); + connect(Rig::instance(), &Rig::xitChanged, ui->rigWidget, &RigWidget::updateXIT); + connect(Rig::instance(), &Rig::ritChanged, ui->rigWidget, &RigWidget::updateRIT); + connect(Rig::instance(), &Rig::pttChanged, ui->rigWidget, &RigWidget::updatePTT); connect(Rotator::instance(), &Rotator::rotErrorPresent, this, &MainWindow::rotErrorHandler); connect(Rotator::instance(), &Rotator::positionChanged, ui->onlineMapWidget, &OnlineMapWidget::antPositionChanged); connect(Rotator::instance(), &Rotator::rotConnected, ui->onlineMapWidget, &OnlineMapWidget::rotConnected); connect(Rotator::instance(), &Rotator::rotDisconnected, ui->onlineMapWidget, &OnlineMapWidget::rotDisconnected); + connect(Rotator::instance(), &Rotator::positionChanged, ui->rotatorWidget, &RotatorWidget::positionChanged); + connect(Rotator::instance(), &Rotator::rotConnected, ui->rotatorWidget, &RotatorWidget::rotConnected); + connect(Rotator::instance(), &Rotator::rotDisconnected, ui->rotatorWidget, &RotatorWidget::rotDisconnected); connect(CWKeyer::instance(), &CWKeyer::cwKeyerError, this, &MainWindow::cwKeyerErrorHandler); connect(CWKeyer::instance(), &CWKeyer::cwKeyWPMChanged, ui->cwconsoleWidget, &CWConsoleWidget::setWPM); connect(CWKeyer::instance(), &CWKeyer::cwKeyEchoText, ui->cwconsoleWidget, &CWConsoleWidget::appendCWEchoText); + connect(CWKeyer::instance(), &CWKeyer::cwKeyConnected, ui->cwconsoleWidget, &CWConsoleWidget::cwKeyConnected); + connect(CWKeyer::instance(), &CWKeyer::cwKeyDisconnected, ui->cwconsoleWidget, &CWConsoleWidget::cwKeyDisconnected); Fldigi* fldigi = new Fldigi(this); connect(fldigi, &Fldigi::addContact, ui->newContactWidget, &NewContactWidget::saveExternalContact); @@ -164,6 +182,8 @@ MainWindow::MainWindow(QWidget* parent) : connect(ui->wsjtxWidget, &WsjtxWidget::spotsCleared, ui->onlineMapWidget, &OnlineMapWidget::clearWSJTXSpots); connect(ui->wsjtxWidget, &WsjtxWidget::reply, wsjtx, &Wsjtx::startReply); connect(ui->wsjtxWidget, &WsjtxWidget::frequencyChanged, ui->newContactWidget, &NewContactWidget::changeFrequency); + connect(ui->wsjtxWidget, &WsjtxWidget::frequencyChanged, ui->onlineMapWidget, &OnlineMapWidget::setIBPBand); + connect(ui->wsjtxWidget, &WsjtxWidget::frequencyChanged, ui->bandmapWidget , &BandmapWidget::updateTunedFrequency); connect(ui->wsjtxWidget, &WsjtxWidget::modeChanged, ui->newContactWidget, &NewContactWidget::changeModefromRig); connect(this, &MainWindow::settingsChanged, wsjtx, &Wsjtx::reloadSetting); @@ -178,7 +198,7 @@ MainWindow::MainWindow(QWidget* parent) : connect(this, &MainWindow::altBackslash, Rig::instance(), &Rig::setPTT); connect(this, &MainWindow::manualMode, ui->newContactWidget, &NewContactWidget::setManualMode); - connect(ui->logbookWidget, &LogbookWidget::logbookUpdated, stats, &StatisticsWidget::refreshGraph); + connect(ui->logbookWidget, &LogbookWidget::logbookUpdated, stats, &StatisticsWidget::refreshWidget); connect(ui->logbookWidget, &LogbookWidget::contactUpdated, &networknotification, &NetworkNotification::QSOUpdated); connect(ui->logbookWidget, &LogbookWidget::clublogContactUpdated, clublogRT, &ClubLog::updateQSOImmediately); connect(ui->logbookWidget, &LogbookWidget::contactDeleted, &networknotification, &NetworkNotification::QSODeleted); @@ -221,7 +241,7 @@ MainWindow::MainWindow(QWidget* parent) : connect(ui->bandmapWidget, &BandmapWidget::tuneDx, ui->newContactWidget, &NewContactWidget::tuneDx); connect(ui->bandmapWidget, &BandmapWidget::nearestSpotFound, ui->newContactWidget, &NewContactWidget::nearestSpot); - connect(ui->wsjtxWidget, &WsjtxWidget::showDxDetails, ui->newContactWidget, &NewContactWidget::showDx); + connect(ui->wsjtxWidget, &WsjtxWidget::callsignSelected, ui->newContactWidget, &NewContactWidget::prepareWSJTXQSO); connect(ui->rigWidget, &RigWidget::rigProfileChanged, ui->newContactWidget, &NewContactWidget::refreshRigProfileCombo); @@ -1194,7 +1214,7 @@ void MainWindow::QSOFilterSetting() QSOFilterDialog dialog(this); dialog.exec(); - ui->logbookWidget->updateTable(); + ui->logbookWidget->refreshUserFilter(); } void MainWindow::alertRuleSetting() diff --git a/ui/MainWindow.h b/ui/MainWindow.h index 7a84fc67..e05668ce 100644 --- a/ui/MainWindow.h +++ b/ui/MainWindow.h @@ -7,7 +7,6 @@ #include "core/NetworkNotification.h" #include "core/AlertEvaluator.h" #include "core/PropConditions.h" -#include "core/MembershipQE.h" #include "core/ClubLog.h" namespace Ui { diff --git a/ui/MainWindow.ui b/ui/MainWindow.ui index b0d614ff..54343bb8 100644 --- a/ui/MainWindow.ui +++ b/ui/MainWindow.ui @@ -52,7 +52,7 @@ 0 0 913 - 22 + 23 diff --git a/ui/NewContactWidget.cpp b/ui/NewContactWidget.cpp index 64693bdd..45f2c212 100644 --- a/ui/NewContactWidget.cpp +++ b/ui/NewContactWidget.cpp @@ -16,8 +16,6 @@ #include "core/debug.h" #include "core/Gridsquare.h" #include "data/StationProfile.h" -#include "core/HamQTH.h" -#include "core/QRZ.h" #include "data/RigProfile.h" #include "data/AntProfile.h" #include "data/CWKeyProfile.h" @@ -186,23 +184,8 @@ NewContactWidget::NewContactWidget(QWidget *parent) : /**************/ /* CONNECTs */ /**************/ - connect(rig, &Rig::frequencyChanged, - this, &NewContactWidget::changeFrequency); - - connect(rig, &Rig::modeChanged, - this, &NewContactWidget::changeModefromRig); - - connect(rig, &Rig::powerChanged, - this, &NewContactWidget::changePower); - - connect(rig, &Rig::rigConnected, - this, &NewContactWidget::rigConnected); - - connect(rig, &Rig::rigDisconnected, - this, &NewContactWidget::rigDisconnected); - connect(&callbookManager, &CallbookManager::callsignResult, - this, &NewContactWidget::callsignResult); + this, &NewContactWidget::setCallbookFields); connect(&callbookManager, &CallbookManager::loginFailed, this, [this](const QString &callbookString) { @@ -212,7 +195,7 @@ NewContactWidget::NewContactWidget(QWidget *parent) : connect(contactTimer, &QTimer::timeout, this, &NewContactWidget::updateTimeOff); - connect(MembershipQE::instance(), &MembershipQE::clubStatusResult, this, &NewContactWidget::clubQueryResult); + connect(MembershipQE::instance(), &MembershipQE::clubStatusResult, this, &NewContactWidget::setMembershipList); /******************************/ /* CONNECTs DYNAMIC WIDGETS */ @@ -270,57 +253,42 @@ NewContactWidget::NewContactWidget(QWidget *parent) : // SQL query returns two QSOs. The first one is the last QSO with Base Callsign // and the second one is the last QSO for the Callsign from a portable QTH. - isprevQSOQueryPrepared = prevQSOQuery.prepare(QLatin1String("SELECT callsign, " - " name_intl, " - " qth_intl, " - " gridsquare, " - " notes_intl, " - " email, " - " web , " - " darc_dok " - "FROM ( " - " SELECT " - " callsign, " - " name_intl, " - " qth_intl, " - " gridsquare, " - " notes_intl, " - " email, " - " web , " - " darc_dok " - " FROM contacts " - " WHERE callsign = :exactCallsign " - " ORDER BY start_time DESC " - " LIMIT 1 " - " ) " - "UNION ALL " - "SELECT callsign, " - " name_intl, " - " qth_intl, " - " gridsquare, " - " notes_intl, " - " email, " - " web , " - " darc_dok " - "FROM ( " - " SELECT " - " callsign, " - " name_intl, " - " qth_intl, " - " gridsquare, " - " notes_intl, " - " email, " - " web , " - " darc_dok " - " FROM contacts c, contacts_autovalue a " - " WHERE c.id = a.contactid " - " AND a.base_callsign = :partialCallsign " - " ORDER BY start_time DESC " - " LIMIT 1 " - " )")); - - if ( !isprevQSOQueryPrepared) - qWarning() << "Cannot prepare prevQSOquery statement"; + isPrevQSOExactMatchQuery = prevQSOExactMatchQuery.prepare(QLatin1String("SELECT " + " callsign, " + " name_intl, " + " qth_intl, " + " gridsquare, " + " notes_intl, " + " email, " + " web , " + " darc_dok " + "FROM contacts " + "WHERE callsign = :exactCallsign " + " AND gridsquare LIKE :grid " + "ORDER BY start_time DESC " + "LIMIT 1 ")); + + if ( !isPrevQSOExactMatchQuery) + qWarning() << "Cannot prepare prevQSOExactMatchQuery statement"; + + isPrevQSOBaseCallMatchQuery = prevQSOBaseCallMatchQuery.prepare(QLatin1String("SELECT " + " callsign, " + " name_intl, " + " qth_intl, " + " gridsquare, " + " notes_intl, " + " email, " + " web , " + " darc_dok " + "FROM contacts c " + " INNER JOIN contacts_autovalue a ON c.id = a.contactid " + "WHERE a.base_callsign = :partialCallsign " + "ORDER BY start_time DESC " + "LIMIT 1")); + + if ( !isPrevQSOBaseCallMatchQuery) + qWarning() << "Cannot prepare prevQSOBaseCallMatchQuery statement"; + } void NewContactWidget::setComboBaseData(QComboBox *combo, const QString &data) @@ -408,14 +376,14 @@ void NewContactWidget::readGlobalSettings() refreshAntProfileCombo(); // recalculate all stats - queryDxcc(ui->callsignEdit->text().toUpper()); + setDxccInfo(ui->callsignEdit->text().toUpper()); ui->freqRXEdit->loadBands(); ui->freqTXEdit->loadBands(); } /* function is called when an operator change Callsign Edit */ -void NewContactWidget::callsignChanged() +void NewContactWidget::handleCallsignFromUser() { FCT_IDENTIFICATION; @@ -456,16 +424,16 @@ void NewContactWidget::callsignChanged() } else { - queryDxcc(callsign); + setDxccInfo(callsign); if ( callsign.length() >= 3 ) - fillFieldsFromLastQSO(callsign); + useFieldsFromPrevQSO(callsign); } } /* function is called when Callsign Edit is finished - example pressed enter */ /* if callsign is entered then QLog call callbook query */ -void NewContactWidget::editCallsignFinished() +void NewContactWidget::finalizeCallsignEdit() { FCT_IDENTIFICATION; @@ -477,8 +445,7 @@ void NewContactWidget::editCallsignFinished() } } - -void NewContactWidget::setCurrentDxcc(const DxccEntity &curr) +void NewContactWidget::setDxccInfo(const DxccEntity &curr) { FCT_IDENTIFICATION; @@ -492,53 +459,41 @@ void NewContactWidget::setCurrentDxcc(const DxccEntity &curr) updateCoordinates(dxccEntity.latlon[0], dxccEntity.latlon[1], COORD_DXCC); ui->dxccTableWidget->setDxcc(dxccEntity.dxcc, BandPlan::freq2Band(ui->freqTXEdit->value())); uiDynamic->contEdit->setCurrentText(dxccEntity.cont); - + ui->flagView->setPixmap((!dxccEntity.flag.isEmpty() ) ? QPixmap(QString(":/flags/64/%1.png").arg(dxccEntity.flag)) + : QPixmap() ); updateDxccStatus(); - - if ( !dxccEntity.flag.isEmpty() ) - { - QPixmap flag(QString(":/flags/64/%1.png").arg(dxccEntity.flag)); - ui->flagView->setPixmap(flag); - } - else - ui->flagView->setPixmap(QPixmap()); } else { - ui->flagView->setPixmap(QPixmap()); - ui->dxccTableWidget->clear(); - ui->dxccStatus->clear(); - ui->distanceInfo->clear(); - dxDistance = qQNaN(); - ui->bearingInfo->clear(); - partnerTimeZone = QTimeZone(); - ui->partnerLocTimeInfo->clear(); ui->dxccInfo->setText(" "); uiDynamic->cqzEdit->clear(); uiDynamic->ituEdit->clear(); + clearCoordinates(); + ui->dxccTableWidget->clear(); uiDynamic->contEdit->setCurrentText(""); + ui->flagView->setPixmap(QPixmap()); + ui->dxccStatus->clear(); emit newTarget(qQNaN(), qQNaN()); } } -/* Obtain DXCC info from local database */ -void NewContactWidget::queryDxcc(const QString &callsign) +void NewContactWidget::setDxccInfo(const QString &callsign) { FCT_IDENTIFICATION; qCDebug(function_parameters) << callsign; - setCurrentDxcc(Data::instance()->lookupDxcc(callsign)); + setDxccInfo(Data::instance()->lookupDxcc(callsign)); } -void NewContactWidget::fillFieldsFromLastQSO(const QString &callsign) +void NewContactWidget::useFieldsFromPrevQSO(const QString &callsign, const QString &grid) { FCT_IDENTIFICATION; qCDebug(function_parameters) << callsign; - if ( !isprevQSOQueryPrepared ) + if ( !isPrevQSOExactMatchQuery || !isPrevQSOBaseCallMatchQuery) return; const Callsign enteredCallsign(callsign); @@ -551,50 +506,68 @@ void NewContactWidget::fillFieldsFromLastQSO(const QString &callsign) const QString &baseCallsign = enteredCallsign.getBase(); // search the base_callsign - prevQSOQuery.bindValue(":exactCallsign",baseCallsign ); - prevQSOQuery.bindValue(":partialCallsign", baseCallsign); + prevQSOExactMatchQuery.bindValue(":exactCallsign", baseCallsign); + prevQSOExactMatchQuery.bindValue(":grid", grid + "%"); - if ( !prevQSOQuery.exec() ) + if ( !prevQSOExactMatchQuery.exec() ) { - qWarning() << "Cannot execute statement" << prevQSOQuery.lastError(); + qWarning() << "Cannot execute statement" << prevQSOExactMatchQuery.lastError(); emit filterCallsign(QString()); return; } - if ( prevQSOQuery.next() ) + if ( prevQSOExactMatchQuery.next() ) { - // SQL query returns two QSOs. The first one is the last QSO with Base Callsign - // and the second one is the last QSO for callsign, which was made from a portable QTH. - // The recognition is possible because the record where Callsign == Based Callsign - // is a QSO with the given Callsign from the base QTH. - // Otherwise, it's a QSO with a given Callsign from a portable QTH. - if ( prevQSOQuery.value("callsign").toString() == baseCallsign - && enteredCallsign.getHostPrefix().isEmpty() + // callsign match the base callsign - full info available + if ( enteredCallsign.getHostPrefix().isEmpty() && enteredCallsign.getSuffix().isEmpty() ) { // entered callsign is base callsign - no portable QTH. Get all fields from // previous QSO - uiDynamic->qthEdit->setText(prevQSOQuery.value("qth_intl").toString()); - uiDynamic->gridEdit->setText(prevQSOQuery.value("gridsquare").toString()); - uiDynamic->dokEdit->setText(prevQSOQuery.value("darc_dok").toString()); + uiDynamic->qthEdit->setText(prevQSOExactMatchQuery.value("qth_intl").toString()); + uiDynamic->gridEdit->setText(prevQSOExactMatchQuery.value("gridsquare").toString()); + uiDynamic->dokEdit->setText(prevQSOExactMatchQuery.value("darc_dok").toString()); } - uiDynamic->nameEdit->setText(prevQSOQuery.value("name_intl").toString()); - ui->noteEdit->insertPlainText(prevQSOQuery.value("notes_intl").toString()); - uiDynamic->emailEdit->setText(prevQSOQuery.value("email").toString()); - uiDynamic->urlEdit->setText(prevQSOQuery.value("web").toString()); + uiDynamic->nameEdit->setText(prevQSOExactMatchQuery.value("name_intl").toString()); + ui->noteEdit->insertPlainText(prevQSOExactMatchQuery.value("notes_intl").toString()); + uiDynamic->emailEdit->setText(prevQSOExactMatchQuery.value("email").toString()); + uiDynamic->urlEdit->setText(prevQSOExactMatchQuery.value("web").toString()); emit filterCallsign(baseCallsign); } else { - //callsign not found - qCDebug(runtime) << "Callsign not match in the Logbook"; - emit filterCallsign(QString()); + //exact match not found + prevQSOBaseCallMatchQuery.bindValue(":partialCallsign", baseCallsign); + + if ( !prevQSOBaseCallMatchQuery.exec() ) + { + qWarning() << "Cannot execute statement2" << prevQSOBaseCallMatchQuery.lastError(); + emit filterCallsign(QString()); + return; + } + + if ( prevQSOBaseCallMatchQuery.next() ) + { + // partial informaion available + uiDynamic->nameEdit->setText(prevQSOBaseCallMatchQuery.value("name_intl").toString()); + ui->noteEdit->insertPlainText(prevQSOBaseCallMatchQuery.value("notes_intl").toString()); + uiDynamic->emailEdit->setText(prevQSOBaseCallMatchQuery.value("email").toString()); + uiDynamic->urlEdit->setText(prevQSOBaseCallMatchQuery.value("web").toString()); + + emit filterCallsign(baseCallsign); + } + else + { + //callsign not found + qCDebug(runtime) << "Callsign not match in the Logbook"; + emit filterCallsign(QString()); + } } } /* function handles a response from Callbook classes */ -void NewContactWidget::callsignResult(const QMap& data) +void NewContactWidget::setCallbookFields(const QMap& data) { FCT_IDENTIFICATION; @@ -682,7 +655,7 @@ void NewContactWidget::callsignResult(const QMap& data) { qCDebug(runtime) << "Received different DXCC Info" << data.value("dxcc") << dxccEntity.dxcc; - setCurrentDxcc(Data::instance()->lookupDxccID(callbookDXCC)); + setDxccInfo(Data::instance()->lookupDxccID(callbookDXCC)); } } @@ -698,27 +671,23 @@ void NewContactWidget::callsignResult(const QMap& data) lastCallbookQueryData = QMap(data); } -void NewContactWidget::clubQueryResult(const QString &in_callsign, QMap data) +void NewContactWidget::setMembershipList(const QString &in_callsign, + QMap data) { FCT_IDENTIFICATION; if ( in_callsign != callsign ) - { - // do not need this result return; - } QString memberText; - QMapIterator clubs(data); - QPalette palette; - //"Hello World" while ( clubs.hasNext() ) { clubs.next(); - QColor color = Data::statusToColor(static_cast(clubs.value()), palette.color(QPalette::Text)); + const QColor &color = Data::statusToColor(static_cast(clubs.value()), palette.color(QPalette::Text)); + //"Hello World" memberText.append(QString("%2   ").arg(Data::colorToHTMLColor(color), clubs.key())); } ui->memberListLabel->setText(memberText); @@ -832,13 +801,15 @@ void NewContactWidget::__modeChanged() QStringListModel* model = dynamic_cast(ui->submodeEdit->model()); model->setStringList(submodeList); - if (!submodeList.isEmpty()) { + if (!submodeList.isEmpty()) + { submodeList.prepend(""); model->setStringList(submodeList); ui->submodeEdit->setVisible(true); ui->submodeEdit->setCurrentIndex(1); } - else { + else + { QStringList list; model->setStringList(list); ui->submodeEdit->setVisible(false); @@ -964,7 +935,7 @@ void NewContactWidget::gridChanged() if (!newGrid.isValid()) { coordPrec = COORD_NONE; - queryDxcc(ui->callsignEdit->text().toUpper()); + setDxccInfo(ui->callsignEdit->text().toUpper()); return; } @@ -1050,7 +1021,6 @@ void NewContactWidget::addAddlFields(QSqlRecord &record, const StationProfile &p { FCT_IDENTIFICATION; - if ( record.value("pfx").toString().isEmpty() ) { const QString &pfxRef = Callsign(record.value("callsign").toString()).getWPXPrefix(); @@ -1712,13 +1682,17 @@ void NewContactWidget::saveExternalContact(QSqlRecord record) QSqlField idField = model.record().field(model.fieldIndex("id")); model.removeColumn(model.fieldIndex("id")); - const DxccEntity &dxcc = Data::instance()->lookupDxcc(savedCallsign); + // if DXCC field is present then it must be used as DXCC Entity + int recordDXCCId = record.value("dxcc").toInt(); // 0 = NAN or not present + // otherwise = DXCC ID + const DxccEntity &dxcc = ( recordDXCCId ) ? Data::instance()->lookupDxccID(recordDXCCId) + : Data::instance()->lookupDxcc(savedCallsign); if ( dxcc.dxcc != 0 ) { - if ( record.value("country_intl").toString().isEmpty() - && record.value("country").toString().isEmpty() ) - record.setValue("country_intl", dxcc.country); + // force overwrite + record.setValue("dxcc", dxcc.dxcc); + record.setValue("country_intl", dxcc.country); if ( record.value("cqz").toString().isEmpty() ) record.setValue("cqz", dxcc.cqz); @@ -1728,15 +1702,14 @@ void NewContactWidget::saveExternalContact(QSqlRecord record) if ( record.value("cont").toString().isEmpty() ) record.setValue("cont", dxcc.cont); - - if ( record.value("dxcc").toString().isEmpty() ) - record.setValue("dxcc", dxcc.dxcc); } // add information from callbook if it is a known callsign // based on the poll #420, QLog adds more information from callbook if ( savedCallsign == ui->callsignEdit->text() ) { + stopContactTimer(); + updateTime(); // information independent of QTH if ( record.value("name_intl").toString().isEmpty() && record.value("name").toString().isEmpty() @@ -1784,6 +1757,26 @@ void NewContactWidget::saveExternalContact(QSqlRecord record) && !uiDynamic->stateEdit->text().isEmpty() ) record.setValue("state", uiDynamic->stateEdit->text()); + if ( record.value("pota_ref").toString().isEmpty() + && !uiDynamic->potaEdit->text().isEmpty()) + record.setValue("pota_ref", uiDynamic->potaEdit->text()); + + if ( record.value("sota_ref").toString().isEmpty() + && !uiDynamic->sotaEdit->text().isEmpty()) + record.setValue("sota_ref", uiDynamic->sotaEdit->text()); + + if ( record.value("sig_intl").toString().isEmpty() + && !uiDynamic->sigEdit->text().isEmpty()) + record.setValue("sig_intl", uiDynamic->sigEdit->text()); + + if ( record.value("sig_info_intl").toString().isEmpty() + && !uiDynamic->sigInfoEdit->text().isEmpty()) + record.setValue("sig_info_intl", uiDynamic->sigInfoEdit->text()); + + if ( record.value("wwff_ref").toString().isEmpty() + && !uiDynamic->wwffEdit->text().isEmpty()) + record.setValue("wwff_ref", uiDynamic->wwffEdit->text()); + // fix ITUz and CQz from callbook, if necessary if ( record.value("ituz").toString() != uiDynamic->ituEdit->text() ) record.setValue("ituz", uiDynamic->ituEdit->text()); @@ -1967,7 +1960,17 @@ void NewContactWidget::updateCoordinates(double lat, double lon, CoordPrecision emit newTarget(lat, lon); } +} +void NewContactWidget::clearCoordinates() +{ + FCT_IDENTIFICATION; + + ui->distanceInfo->clear(); + dxDistance = qQNaN(); + ui->bearingInfo->clear(); + partnerTimeZone = QTimeZone(); + ui->partnerLocTimeInfo->clear(); } void NewContactWidget::updateDxccStatus() @@ -2361,8 +2364,8 @@ void NewContactWidget::setupCustomUi() FCT_IDENTIFICATION; // Clear Custom Lines - QList customUiRows = ui->customLayout->findChildren(); - for ( auto &rowLayout : qAsConst(customUiRows) ) + const QList &customUiRows = ui->customLayout->findChildren(); + for ( auto &rowLayout : customUiRows ) { qCDebug(runtime) << "Removing objects from " << rowLayout->objectName(); @@ -2382,7 +2385,7 @@ void NewContactWidget::setupCustomUi() QList detailColumns; detailColumns << ui->detailColA << ui->detailColB << ui->detailColC; - for ( QFormLayout * layout : qAsConst(detailColumns) ) + for ( QFormLayout * layout : static_cast&>(detailColumns) ) { qCDebug(runtime) << "Removing" << layout->rowCount() <<"object(s) from" << layout->objectName(); @@ -2611,11 +2614,12 @@ void NewContactWidget::fillCallsignGrid(const QString &callsign, const QString & uiDynamic->gridEdit->setText(grid); } -void NewContactWidget::showDx(const QString &callsign, const QString &grid) +void NewContactWidget::prepareWSJTXQSO(const QString &receivedCallsign, + const QString &grid) { FCT_IDENTIFICATION; - qCDebug(function_parameters)<freqRXEdit->value(); // Important !!! - to prevent QSY Contact Reset when the frequency is set + // QSY Wipe disabling - It is possible to have a RIG connected and run WSJTX. + // To prevent the QSY Wipe when WSJTX's Fake Split Mode is enabled, QLog starts the QSO Timer. + if ( rigOnline ) + startContactTimer(); + + callsign = receivedCallsign; + ui->callsignEdit->setText(receivedCallsign); uiDynamic->gridEdit->setText(grid); + setDxccInfo(receivedCallsign); + + // at the moment WSJTX sends several statuses about changing one callsign. + // In order to avoid multiple searches, we will search only when we have a grid - it was usually the last + // status message + // the current status message sequence is + // 1) prev Callsign empty grid + // 2) new Callsign empty grid + // 3) new Calllsign, new gris + if ( !grid.isEmpty() ) + { + useFieldsFromPrevQSO(callsign, grid); + finalizeCallsignEdit(); + } } -void NewContactWidget::setDefaultReport() { +void NewContactWidget::setDefaultReport() +{ FCT_IDENTIFICATION; - if (defaultReport.isEmpty()) { + if (defaultReport.isEmpty()) defaultReport = ""; - } ui->rstRcvdEdit->setText(defaultReport); + ui->rstRcvdEdit->setSelectionBackwardOffset(defaultReport.size() >= 3 ? 2 : 1 ); ui->rstSentEdit->setText(defaultReport); + ui->rstSentEdit->setSelectionBackwardOffset(defaultReport.size() >= 3 ? 2 : 1 ); } void NewContactWidget::webLookup() @@ -2874,7 +2904,7 @@ void NewContactWidget::stationProfileComboChanged(const QString &profileName) emit stationProfileChanged(); // recalculate all stats - queryDxcc(ui->callsignEdit->text().toUpper()); + setDxccInfo(ui->callsignEdit->text().toUpper()); } void NewContactWidget::rigProfileComboChanged(const QString &profileName) @@ -3220,8 +3250,8 @@ void NewContactWidget::changeCallsignManually(const QString &callsign, double fr QSOFreq = freq; // Important !!! - to prevent QSY Contact Reset when the frequency is set ui->callsignEdit->setText(callsign); ui->callsignEdit->end(false); - callsignChanged(); - editCallsignFinished(); + handleCallsignFromUser(); + finalizeCallsignEdit(); stopContactTimer(); } @@ -3397,6 +3427,9 @@ QWidget *NewContactDynamicWidgets::getEditor(int index) { FCT_IDENTIFICATION; + if ( !widgetMapping.contains(index) ) + return nullptr; + widgetMapping.value(index).editor->setHidden(false); widgetMapping.value(index).editor->setFocusPolicy(Qt::ClickFocus); return widgetMapping.value(index).editor; @@ -3409,7 +3442,7 @@ QStringList NewContactDynamicWidgets::getAllFieldLabelNames() const QStringList ret; const QList &dynWidget = widgetMapping.values(); - for (const DynamicWidget &widget : qAsConst(dynWidget)) + for (const DynamicWidget &widget : dynWidget) { ret << widget.fieldLabelName; } @@ -3434,6 +3467,9 @@ QString NewContactDynamicWidgets::getFieldLabelName4Index(int i) const { FCT_IDENTIFICATION; + if ( !widgetMapping.contains(i) ) + return QString(); + return widgetMapping.value(i).fieldLabelName; } diff --git a/ui/NewContactWidget.h b/ui/NewContactWidget.h index aa62337a..16ef21f3 100644 --- a/ui/NewContactWidget.h +++ b/ui/NewContactWidget.h @@ -11,8 +11,6 @@ #include #include -#include "data/Data.h" -#include "core/Gridsquare.h" #include "data/DxSpot.h" #include "rig/Rig.h" #include "core/CallbookManager.h" @@ -23,6 +21,9 @@ #include "ui/EditLine.h" #include "data/BandPlan.h" #include "core/MultiselectCompleter.h" +#include "data/POTAEntity.h" +#include "data/SOTAEntity.h" +#include "data/WWFFEntity.h" namespace Ui { class NewContactWidget; @@ -192,7 +193,7 @@ public slots: double frequency, const BandPlan::BandPlanMode mode); void fillCallsignGrid(const QString &callsign, const QString& grid); - void showDx(const QString &callsign, const QString &grid); + void prepareWSJTXQSO(const QString &callsign, const QString &grid); void resetContact(); void saveContact(); @@ -215,7 +216,7 @@ public slots: void setupCustomUi(); private slots: - void callsignChanged(); + void handleCallsignFromUser(); void frequencyTXChanged(); void frequencyRXChanged(); void changeMode(); @@ -225,9 +226,9 @@ private slots: void updateTimeOff(); void startContactTimer(); void stopContactTimer(); - void editCallsignFinished(); - void callsignResult(const QMap& data); - void clubQueryResult(const QString&, QMap); + void finalizeCallsignEdit(); + void setCallbookFields(const QMap& data); + void setMembershipList(const QString&, QMap); void propModeChanged(const QString&); void sotaChanged(const QString&); void sotaEditFinished(); @@ -247,9 +248,10 @@ private slots: void refreshSIGCompleter(); private: - void fillFieldsFromLastQSO(const QString &callsign); - void setCurrentDxcc(const DxccEntity &curr); - void queryDxcc(const QString &callsign); + void useFieldsFromPrevQSO(const QString &callsign, + const QString &grid = QString()); + void setDxccInfo(const DxccEntity &curr); + void setDxccInfo(const QString &callsign); void clearCallbookQueryFields(); void clearMemberQueryFields(); void readWidgetSettings(); @@ -259,6 +261,7 @@ private slots: void updateTXBand(double freq); void updateRXBand(double freq); void updateCoordinates(double lat, double lon, CoordPrecision prec); + void clearCoordinates(); void updateDxccStatus(); void updatePartnerLocTime(); void setDefaultReport(); @@ -319,8 +322,10 @@ private slots: QSettings settings; Band bandTX; Band bandRX; - QSqlQuery prevQSOQuery; - bool isprevQSOQueryPrepared; + QSqlQuery prevQSOExactMatchQuery; + QSqlQuery prevQSOBaseCallMatchQuery; + bool isPrevQSOExactMatchQuery; + bool isPrevQSOBaseCallMatchQuery; }; #endif // QLOG_UI_NEWCONTACTWIDGET_H diff --git a/ui/NewContactWidget.ui b/ui/NewContactWidget.ui index 565dc8a2..554cede2 100644 --- a/ui/NewContactWidget.ui +++ b/ui/NewContactWidget.ui @@ -7,7 +7,7 @@ 0 0 971 - 371 + 378 @@ -69,7 +69,7 @@ 0 - + 0 @@ -284,7 +284,6 @@ - 75 true @@ -297,7 +296,6 @@ - 75 true @@ -345,7 +343,6 @@ 20 - 75 true @@ -355,7 +352,7 @@ - + 0 @@ -795,7 +792,6 @@ 13 - 75 true @@ -865,7 +861,6 @@ 9 - 50 false @@ -894,7 +889,6 @@ 9 - 50 false @@ -1669,6 +1663,11 @@ QDoubleSpinBox
    ui/FreqQSpinBox.h
    + + NewContactRSTEditLine + QLineEdit +
    ui/EditLine.h
    +
    callsignEdit @@ -1684,7 +1683,7 @@ callsignEdit textChanged(QString) NewContactWidget - callsignChanged() + handleCallsignFromUser() 177 @@ -1732,7 +1731,7 @@ callsignEdit returnPressed() NewContactWidget - callsignChanged() + handleCallsignFromUser() 115 @@ -1764,7 +1763,7 @@ callsignEdit editingFinished() NewContactWidget - editCallsignFinished() + finalizeCallsignEdit() 67 @@ -1972,7 +1971,7 @@ saveContact() resetContact() - callsignChanged() + handleCallsignFromUser() gridChanged() stopContactTimer() frequencyTXChanged() @@ -1983,7 +1982,7 @@ updateTimeStop() subModeChanged() propModeChanged(QString) - editCallsignFinished() + finalizeCallsignEdit() freqTXOffsetChanged(double) stationProfileComboChanged(QString) sotaChanged(QString) diff --git a/ui/OnlineMapWidget.cpp b/ui/OnlineMapWidget.cpp index 86cc245d..2a7597dc 100644 --- a/ui/OnlineMapWidget.cpp +++ b/ui/OnlineMapWidget.cpp @@ -19,6 +19,7 @@ #include "rotator/Rotator.h" #include "rig/Rig.h" #include "data/BandPlan.h" +#include "rig/macros.h" MODULE_IDENTIFICATION("qlog.ui.onlinemapwidget"); diff --git a/ui/OnlineMapWidget.h b/ui/OnlineMapWidget.h index e1dde292..cd7594bc 100644 --- a/ui/OnlineMapWidget.h +++ b/ui/OnlineMapWidget.h @@ -11,7 +11,6 @@ #include "ui/NewContactWidget.h" #include "core/KSTChat.h" #include "data/WsjtxEntry.h" -#include "core/Wsjtx.h" namespace Ui { class OnlineMapWidget; diff --git a/ui/PaperQSLDialog.cpp b/ui/PaperQSLDialog.cpp index 3c52c970..4a9ff9f2 100644 --- a/ui/PaperQSLDialog.cpp +++ b/ui/PaperQSLDialog.cpp @@ -90,9 +90,9 @@ void PaperQSLDialog::showAvailableFiles() { FCT_IDENTIFICATION; - QStringList files = qsl->getAvailableQSLNames(dialogQSORecord, QSLObject::QSLFILE); + const QStringList &files = qsl->getAvailableQSLNames(dialogQSORecord, QSLObject::QSLFILE); - for ( auto &file : qAsConst(files) ) + for ( auto &file : files ) { addFileToDialog(file); } diff --git a/ui/ProfileImageWidget.h b/ui/ProfileImageWidget.h index b750dfdb..2fe458d9 100644 --- a/ui/ProfileImageWidget.h +++ b/ui/ProfileImageWidget.h @@ -1,5 +1,5 @@ -#ifndef PROFILEIMAGEWIDGET_H -#define PROFILEIMAGEWIDGET_H +#ifndef QLOG_UI_PROFILEIMAGEWIDGET_H +#define QLOG_UI_PROFILEIMAGEWIDGET_H #include #include @@ -56,4 +56,4 @@ private slots: QMimeType mimeType; }; -#endif // PROFILEIMAGEWIDGET_H +#endif // QLOG_UI_PROFILEIMAGEWIDGET_H diff --git a/ui/QSODetailDialog.cpp b/ui/QSODetailDialog.cpp index 67657039..1a21a54b 100644 --- a/ui/QSODetailDialog.cpp +++ b/ui/QSODetailDialog.cpp @@ -265,7 +265,7 @@ QSODetailDialog::QSODetailDialog(const QSqlRecord &qso, /* Country */ SqlListModel* countryModel = new SqlListModel("SELECT id, translate_to_locale(name), name " "FROM dxcc_entities " - "ORDER BY 2 COLLATE LOCALEAWARE ASC;", "", this); + "ORDER BY 2 COLLATE LOCALEAWARE ASC;", " ", this); while ( countryModel->canFetchMore() ) countryModel->fetchMore(); @@ -845,9 +845,9 @@ bool QSODetailDialog::doValidation() bool allValid = true; - QList list = findChildren(); + const QList &list = findChildren(); - for ( QLabel *label : qAsConst(list) ) + for ( QLabel *label : list ) { if ( label ) label->setToolTip(QString()); } @@ -1685,11 +1685,7 @@ void QSOEditMapperDelegate::setEditorData(QWidget *editor, QModelIndexList countryIndex = combo->model()->match(combo->model()->index(0,0), Qt::DisplayRole, index.data(), 1, Qt::MatchExactly); - if ( countryIndex.size() >= 1 ) - { - combo->setCurrentIndex(countryIndex.at(0).row()); - } - + combo->setCurrentIndex(( countryIndex.size() >= 1 ) ? countryIndex.at(0).row() : -1); } return; } @@ -1824,10 +1820,14 @@ void QSOEditMapperDelegate::setModelData(QWidget *editor, if ( combo ) { int row = combo->currentIndex(); - const QModelIndex &idxDXCC = combo->model()->index(row,0); - const QModelIndex &idxCountryEN = combo->model()->index(row,2); - QVariant dataDXCC = combo->model()->data(idxDXCC); - QVariant dataCountryEN = combo->model()->data(idxCountryEN); + QVariant dataDXCC; + QVariant dataCountryEN; + + if ( row > 0 ) // the first line is an empty line + { + dataDXCC = combo->model()->data(combo->model()->index(row,0)); + dataCountryEN = combo->model()->data(combo->model()->index(row,2)); + } model->setData(index, dataDXCC); model->setData(model->index(index.row(), diff --git a/ui/QSODetailDialog.h b/ui/QSODetailDialog.h index 2b63ae7a..216e6003 100644 --- a/ui/QSODetailDialog.h +++ b/ui/QSODetailDialog.h @@ -1,5 +1,5 @@ -#ifndef QSODETAILDIALOG_H -#define QSODETAILDIALOG_H +#ifndef QLOG_UI_QSODETAILDIALOG_H +#define QLOG_UI_QSODETAILDIALOG_H #include #include diff --git a/ui/QSOFilterDetail.cpp b/ui/QSOFilterDetail.cpp index ebff4465..93b52436 100644 --- a/ui/QSOFilterDetail.cpp +++ b/ui/QSOFilterDetail.cpp @@ -511,9 +511,9 @@ void QSOFilterDetail::save() { if ( deleteFilterStmt.exec() ) { - QList conditionLayouts = ui->conditionsLayout->findChildren(); + const QList &conditionLayouts = ui->conditionsLayout->findChildren(); - for (auto &condition: qAsConst(conditionLayouts) ) + for (auto &condition: conditionLayouts ) { int fieldNameIdx = 0; int conditionIdx = 0; diff --git a/ui/QSOFilterDialog.cpp b/ui/QSOFilterDialog.cpp index 74e6b766..4734eb37 100644 --- a/ui/QSOFilterDialog.cpp +++ b/ui/QSOFilterDialog.cpp @@ -2,7 +2,6 @@ #include #include #include -#include "models/SqlListModel.h" #include "QSOFilterDialog.h" #include "ui_QSOFilterDialog.h" #include "core/debug.h" diff --git a/ui/QrzDialog.cpp b/ui/QrzDialog.cpp index 5f240718..7d13283f 100644 --- a/ui/QrzDialog.cpp +++ b/ui/QrzDialog.cpp @@ -11,7 +11,6 @@ #include "core/QRZ.h" #include "models/SqlListModel.h" #include "ui/ShowUploadDialog.h" -#include "logformat/AdiFormat.h" #include "data/StationProfile.h" MODULE_IDENTIFICATION("qlog.ui.qrzdialog"); diff --git a/ui/RigWidget.cpp b/ui/RigWidget.cpp index aede933b..a5c6db59 100644 --- a/ui/RigWidget.cpp +++ b/ui/RigWidget.cpp @@ -8,7 +8,6 @@ #include "ui_RigWidget.h" #include "rig/macros.h" #include "core/debug.h" -#include "models/SqlListModel.h" #include "data/Data.h" #include "core/HRDLog.h" #include "data/BandPlan.h" @@ -48,17 +47,6 @@ RigWidget::RigWidget(QWidget *parent) : refreshBandCombo(); refreshModeCombo(); - Rig* rig = Rig::instance(); - connect(rig, &Rig::frequencyChanged, this, &RigWidget::updateFrequency); - connect(rig, &Rig::modeChanged, this, &RigWidget::updateMode); - connect(rig, &Rig::vfoChanged, this, &RigWidget::updateVFO); - connect(rig, &Rig::powerChanged, this, &RigWidget::updatePWR); - connect(rig, &Rig::rigConnected, this, &RigWidget::rigConnected); - connect(rig, &Rig::rigDisconnected, this, &RigWidget::rigDisconnected); - connect(rig, &Rig::xitChanged, this, &RigWidget::updateXIT); - connect(rig, &Rig::ritChanged, this, &RigWidget::updateRIT); - connect(rig, &Rig::pttChanged, this, &RigWidget::updatePTT); - QTimer *onAirTimer = new QTimer(this); connect(onAirTimer, &QTimer::timeout, this, &RigWidget::sendOnAirState); onAirTimer->start(ONAIR_INTERVAL * 1000); @@ -209,7 +197,7 @@ void RigWidget::bandComboChanged(const QString &newBand) double newFreq = record.value("start_freq").toDouble(); - if ( ! record.value("last_seen_freq").isNull() ) + if ( ! record.value("last_seen_freq").toString().isEmpty() ) { newFreq = record.value("last_seen_freq").toDouble(); } diff --git a/ui/RotatorWidget.cpp b/ui/RotatorWidget.cpp index 0a18e792..fa7e78d3 100644 --- a/ui/RotatorWidget.cpp +++ b/ui/RotatorWidget.cpp @@ -40,10 +40,6 @@ RotatorWidget::RotatorWidget(QWidget *parent) : ui->userButtonsProfileCombo->setModel(userButtonModel); refreshRotUserButtonProfileCombo(); - connect(Rotator::instance(), &Rotator::positionChanged, this, &RotatorWidget::positionChanged); - connect(Rotator::instance(), &Rotator::rotConnected, this, &RotatorWidget::rotConnected); - connect(Rotator::instance(), &Rotator::rotDisconnected, this, &RotatorWidget::rotDisconnected); - QMenu *qsoBearingMenu = new QMenu(this); qsoBearingMenu->addAction(ui->actionQSO_SP); qsoBearingMenu->addAction(ui->actionQSO_LP); diff --git a/ui/SettingsDialog.cpp b/ui/SettingsDialog.cpp index 1bfaadb8..884a9cdd 100644 --- a/ui/SettingsDialog.cpp +++ b/ui/SettingsDialog.cpp @@ -18,14 +18,12 @@ #include "../core/HRDLog.h" #include "../ui/StyleItemDelegate.h" #include "core/debug.h" -#include "core/CredentialStore.h" #include "data/StationProfile.h" #include "data/RigProfile.h" #include "data/AntProfile.h" #include "data/Data.h" #include "core/Gridsquare.h" #include "core/Wsjtx.h" -#include "core/QSLStorage.h" #include "core/NetworkNotification.h" #include "rig/Rig.h" #include "rig/RigCaps.h" @@ -33,7 +31,6 @@ #include "rotator/RotCaps.h" #include "core/LogParam.h" #include "core/Callsign.h" -#include "cwkey/CWKeyer.h" #include "core/MembershipQE.h" #include "models/SqlListModel.h" #include "core/GenericCallbook.h" @@ -41,6 +38,7 @@ #include "core/HostsPortString.h" #include "models/ShortcutEditorModel.h" #include "ui/StyleItemDelegate.h" +#include "core/SerialPort.h" #define STACKED_WIDGET_SERIAL_SETTING 0 #define STACKED_WIDGET_NETWORK_SETTING 1 @@ -1239,10 +1237,10 @@ void SettingsDialog::delCWKeyProfile() { QStringList dependentRigs; QString removedCWProfile = ui->cwProfilesListView->model()->data(index).toString(); - QStringList availableRigProfileNames = rigProfManager->profileNameList(); + const QStringList &availableRigProfileNames = rigProfManager->profileNameList(); /* needed to verify whether removed Key is not used in Rig Profile as an assigned Key*/ - for ( const QString &rigProfileName : qAsConst(availableRigProfileNames) ) + for ( const QString &rigProfileName : availableRigProfileNames ) { qCDebug(runtime) << "Checking Rig Profile" << rigProfileName; RigProfile testedRig = rigProfManager->getProfile(rigProfileName); @@ -2408,7 +2406,7 @@ void SettingsDialog::writeSettings() { QStringList enabledLists; - for ( QCheckBox* item: qAsConst(memberListCheckBoxes) ) + for ( QCheckBox* item: static_cast&>(memberListCheckBoxes) ) { if ( item->isChecked() ) { @@ -2648,7 +2646,7 @@ void SettingsDialog::generateMembershipCheckboxes() { int elementIndex = 0; - for ( QCheckBox* item: qAsConst(memberListCheckBoxes) ) + for ( QCheckBox* item: static_cast&>(memberListCheckBoxes) ) { ui->clubListGrig->addWidget(item, elementIndex / 6, elementIndex % 6); elementIndex++; diff --git a/ui/SettingsDialog.h b/ui/SettingsDialog.h index 1a5e2b97..8c5dce4e 100644 --- a/ui/SettingsDialog.h +++ b/ui/SettingsDialog.h @@ -18,9 +18,9 @@ #include "data/CWShortcutProfile.h" #include "data/RotUsrButtonsProfile.h" #include "core/LogLocale.h" -#include "rig/Rig.h" #include "ui/MainWindow.h" #include "core/MultiselectCompleter.h" +#include "rig/RigCaps.h" namespace Ui { class SettingsDialog; diff --git a/ui/StatisticsWidget.cpp b/ui/StatisticsWidget.cpp index bc332aad..0d2f6bb0 100644 --- a/ui/StatisticsWidget.cpp +++ b/ui/StatisticsWidget.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include "StatisticsWidget.h" #include "ui_StatisticsWidget.h" #include "core/debug.h" @@ -27,146 +28,66 @@ void StatisticsWidget::mainStatChanged(int idx) qCDebug(function_parameters) << idx; - ui->statTypeSecCombo->blockSignals(true); - - ui->statTypeSecCombo->clear(); - - switch ( idx ) - { - /* QSOs per */ - case 0: - { - ui->statTypeSecCombo->addItem(tr("Year")); - ui->statTypeSecCombo->addItem(tr("Month")); - ui->statTypeSecCombo->addItem(tr("Day in Week")); - ui->statTypeSecCombo->addItem(tr("Hour")); - ui->statTypeSecCombo->addItem(tr("Mode")); - ui->statTypeSecCombo->addItem(tr("Band")); - ui->statTypeSecCombo->addItem(tr("Continent")); - ui->statTypeSecCombo->addItem(tr("Propagation Mode")); - } - break; - - /* Percents */ - case 1: - { - ui->statTypeSecCombo->addItem(tr("Confirmed / Not Confirmed")); - } - break; - - /* TOP 10 */ - case 2: - { - ui->statTypeSecCombo->addItem(tr("Countries")); - ui->statTypeSecCombo->addItem(tr("Big Gridsquares")); - } - break; - - /* Histogram */ - case 3: - { - QString unit; - Gridsquare::distance2localeUnitDistance(0, unit); - ui->statTypeSecCombo->addItem(tr("Distance") + QString(" [%1]").arg(unit)); - } - break; + setSubTypesCombo(idx); + refreshGraph(); +} - /* Show on Map */ - case 4: - { - ui->statTypeSecCombo->addItem(tr("QSOs")); - ui->statTypeSecCombo->addItem(tr("Confirmed/Worked Grids")); - ui->statTypeSecCombo->addItem(tr("ODX")); - } - break; - } - if ( idx == 4 ) - { - ui->lotwCheckBox->setEnabled(true); - ui->eqslCheckBox->setEnabled(true); - ui->paperCheckBox->setEnabled(true); - } - else - { - ui->lotwCheckBox->setEnabled(false); - ui->eqslCheckBox->setEnabled(false); - ui->paperCheckBox->setEnabled(false); - } +void StatisticsWidget::refreshWidget() +{ + FCT_IDENTIFICATION; - ui->statTypeSecCombo->blockSignals(false); + if ( !isVisible() ) + return; - refreshGraph(); + refreshCombos(); + refreshGraph(); } void StatisticsWidget::refreshGraph() { FCT_IDENTIFICATION; + if ( !isVisible() ) + return; + QStringList genericFilter; genericFilter << " 1 = 1 "; //just initialization - use only in case of empty Options - refreshCallCombo(); - refreshRigCombo(); - refreshAntCombo(); - refreshBandCombo(); - refreshGridCombo(); - if ( ui->myCallCombo->currentIndex() != 0 ) - { genericFilter << " (station_callsign = '" + ui->myCallCombo->currentText() + "') "; - } if ( ui->myGridCombo->currentIndex() != 0 ) { if ( ui->myGridCombo->currentText().isEmpty() ) - { genericFilter << " (my_gridsquare is NULL) "; - } else - { genericFilter << " (my_gridsquare = '" + ui->myGridCombo->currentText() + "') "; - } } if ( ui->myRigCombo->currentIndex() != 0 ) { if ( ui->myRigCombo->currentText().isEmpty() ) - { genericFilter << " (my_rig is NULL) "; - } else - { genericFilter << " (my_rig = '" + ui->myRigCombo->currentText() + "') "; - } } if ( ui->myAntennaCombo->currentIndex() != 0 ) { if ( ui->myAntennaCombo->currentText().isEmpty() ) - { genericFilter << " (my_antenna is NULL) "; - } else - { genericFilter << " (my_antenna = '" + ui->myAntennaCombo->currentText() + "') "; - } } - if ( ui->bandCombo->currentIndex() != 0 ) - { - if ( ! ui->bandCombo->currentText().isEmpty() ) - { - genericFilter << " (band = '" + ui->bandCombo->currentText() + "') "; - } - } + if ( ui->bandCombo->currentIndex() != 0 && ! ui->bandCombo->currentText().isEmpty() ) + genericFilter << " (band = '" + ui->bandCombo->currentText() + "') "; if ( ui->useDateRangeCheckBox->isChecked() ) - { genericFilter << " (date(start_time) BETWEEN date('" + ui->startDateEdit->date().toString("yyyy-MM-dd") + " 00:00:00') AND date('" + ui->endDateEdit->date().toString("yyyy-MM-dd") + " 23:59:59') ) "; - } qCDebug(runtime) << "main " << ui->statTypeMainCombo->currentIndex() << " secondary " << ui->statTypeSecCombo->currentIndex(); @@ -373,25 +294,18 @@ void StatisticsWidget::refreshGraph() QStringList confirmed("1=2 "); if ( ui->eqslCheckBox->isChecked() ) - { confirmed << " eqsl_qsl_rcvd = 'Y' "; - } if ( ui->lotwCheckBox->isChecked() ) - { confirmed << " lotw_qsl_rcvd = 'Y' "; - } if ( ui->paperCheckBox->isChecked() ) - { confirmed << " qsl_rcvd = 'Y' "; - } QString innerCase = " CASE WHEN (" + confirmed.join("or") + ") THEN 1 ELSE 0 END "; - - QString stmtMyLocations = "SELECT DISTINCT my_gridsquare FROM contacts WHERE " + genericFilter.join(" AND "); QSqlQuery myLocations(stmtMyLocations); + qCDebug(runtime) << stmtMyLocations; drawMyLocationsOnMap(myLocations); @@ -477,22 +391,14 @@ void StatisticsWidget::changeTheme(int theme) QString themeJavaScript; if ( theme == 1 ) /* dark mode */ - { themeJavaScript = "map.getPanes().tilePane.style.webkitFilter=\"brightness(0.6) invert(1) contrast(3) hue-rotate(200deg) saturate(0.3) brightness(0.9)\";"; - } else - { themeJavaScript = "map.getPanes().tilePane.style.webkitFilter=\"\";"; - } if ( !isMainPageLoaded ) - { postponedScripts.append(themeJavaScript); - } else - { main_page->runJavaScript(themeJavaScript); - } } StatisticsWidget::StatisticsWidget(QWidget *parent) : @@ -507,21 +413,10 @@ StatisticsWidget::StatisticsWidget(QWidget *parent) : ui->setupUi(this); ui->myCallCombo->setModel(new QStringListModel(this)); - refreshCallCombo(); - ui->myGridCombo->setModel(new QStringListModel(this)); - refreshGridCombo(); - ui->myRigCombo->setModel(new QStringListModel(this)); - refreshRigCombo(); - ui->myRigCombo->setCurrentIndex(0); - ui->myAntennaCombo->setModel(new QStringListModel(this)); - refreshAntCombo(); - ui->myAntennaCombo->setCurrentIndex(0); - ui->bandCombo->setModel(new QStringListModel(this)); - refreshBandCombo(); ui->startDateEdit->setDisplayFormat(locale.formatDateShortWithYYYY()); ui->startDateEdit->setDate(QDate::currentDate().addDays(DEFAULT_STAT_RANGE)); @@ -533,12 +428,10 @@ StatisticsWidget::StatisticsWidget(QWidget *parent) : main_page->setWebChannel(&channel); ui->mapView->setPage(main_page); + connect(ui->mapView, &QWebEngineView::loadFinished, this, &StatisticsWidget::mapLoaded); main_page->load(QUrl(QStringLiteral("qrc:/res/map/onlinemap.html"))); ui->mapView->setFocusPolicy(Qt::ClickFocus); - connect(ui->mapView, &QWebEngineView::loadFinished, this, &StatisticsWidget::mapLoaded); channel.registerObject("layerControlHandler", &layerControlHandler); - - mainStatChanged(0); } StatisticsWidget::~StatisticsWidget() @@ -548,6 +441,30 @@ StatisticsWidget::~StatisticsWidget() delete ui; } +bool StatisticsWidget::event(QEvent *event) +{ + if (event->type() == QEvent::Show) + { + // We will not use refreshWidget here, even though at first glance it appears + // to do the same thing. The difference is that we want class constructor to be as fast as possible. + // Therefore, in the constructor, we do not populate the combo boxes. As a result, they are empty + // when first displayed and need to be loaded and then combos for Rig, Ant, etc., can be set. + refreshCombos(); + ui->statTypeMainCombo->blockSignals(true); + ui->statTypeMainCombo->setCurrentIndex(0); + ui->statTypeMainCombo->blockSignals(false); + setSubTypesCombo(ui->statTypeMainCombo->currentIndex()); + ui->myRigCombo->blockSignals(true); + ui->myRigCombo->setCurrentIndex(0); + ui->myRigCombo->blockSignals(false); + ui->myAntennaCombo->blockSignals(true); + ui->myAntennaCombo->setCurrentIndex(0); + ui->myAntennaCombo->blockSignals(false); + refreshGraph(); + } + return QWidget::event(event); // Propagate the event further +} + void StatisticsWidget::drawBarGraphs(const QString &title, QSqlQuery &query) { FCT_IDENTIFICATION; @@ -561,9 +478,7 @@ void StatisticsWidget::drawBarGraphs(const QString &title, QSqlQuery &query) QValueAxis *axisY = new QValueAxis(); if ( chart != nullptr ) - { chart->deleteLater(); - } chart = new QChart(); @@ -604,10 +519,7 @@ void StatisticsWidget::drawPieGraph(const QString &title, QPieSeries *series) QChart *chart = ui->graphView->chart(); if ( chart != nullptr ) - { chart->deleteLater(); - } - chart = new QChart(); @@ -624,15 +536,15 @@ void StatisticsWidget::drawMyLocationsOnMap(QSqlQuery &query) { FCT_IDENTIFICATION; - - if ( query.lastQuery().isEmpty() ) return; + if ( query.lastQuery().isEmpty() ) + return; QList locations; while ( query.next() ) { - QString loc = query.value(0).toString(); - Gridsquare stationGrid(loc); + const QString &loc = query.value(0).toString(); + const Gridsquare stationGrid(loc); if ( stationGrid.isValid() ) { @@ -650,30 +562,29 @@ void StatisticsWidget::drawMyLocationsOnMap(QSqlQuery &query) qCDebug(runtime) << javaScript; if ( !isMainPageLoaded ) - { postponedScripts.append(javaScript); - } else - { main_page->runJavaScript(javaScript); - } } void StatisticsWidget::drawPointsOnMap(QSqlQuery &query) { FCT_IDENTIFICATION; - - if ( query.lastQuery().isEmpty() ) return; + if ( query.lastQuery().isEmpty() ) + return; QList stations; + qulonglong count = 0; + while ( query.next() ) { - Gridsquare stationGrid(query.value(1).toString()); + const Gridsquare stationGrid(query.value(1).toString()); if ( stationGrid.isValid() ) { + count++; double lat = stationGrid.getLatitude(); double lon = stationGrid.getLongitude(); stations.append(QString("[\"%1\", %2, %3, %4]").arg(query.value(0).toString()) @@ -683,6 +594,16 @@ void StatisticsWidget::drawPointsOnMap(QSqlQuery &query) } } + if ( count > 50000 ) + { + QMessageBox::StandardButton reply; + reply = QMessageBox::question(this, tr("Statistics"), tr("Over 50000 QSOs. Display them?"), + QMessageBox::Yes|QMessageBox::No); + + if ( reply != QMessageBox::Yes ) + stations.clear(); + } + QString javaScript = QString("grids_confirmed = [];" "grids_worked = [];" "drawPoints([%1]);" @@ -691,13 +612,9 @@ void StatisticsWidget::drawPointsOnMap(QSqlQuery &query) qCDebug(runtime) << javaScript; if ( !isMainPageLoaded ) - { postponedScripts.append(javaScript); - } else - { main_page->runJavaScript(javaScript); - } } void StatisticsWidget::drawFilledGridsOnMap(QSqlQuery &query) @@ -713,13 +630,9 @@ void StatisticsWidget::drawFilledGridsOnMap(QSqlQuery &query) while ( query.next() ) { if ( query.value(2).toInt() > 0 && ! confirmedGrids.contains(query.value(1).toString()) ) - { confirmedGrids << QString("\"" + query.value(1).toString() + "\""); - } else - { workedGrids << QString("\"" + query.value(1).toString() + "\""); - } } QString javaScript = QString("grids_confirmed = [ %1 ]; " @@ -731,62 +644,99 @@ void StatisticsWidget::drawFilledGridsOnMap(QSqlQuery &query) qCDebug(runtime) << javaScript; if ( !isMainPageLoaded ) - { postponedScripts.append(javaScript); - } else - { main_page->runJavaScript(javaScript); - } } -void StatisticsWidget::refreshCallCombo() +void StatisticsWidget::refreshCombos() { FCT_IDENTIFICATION; - refreshCombo(ui->myCallCombo, "SELECT DISTINCT UPPER(station_callsign) FROM contacts ORDER BY station_callsign"); + refreshCombo(ui->myCallCombo, QLatin1String("SELECT DISTINCT UPPER(station_callsign) FROM contacts ORDER BY station_callsign")); + refreshCombo(ui->myRigCombo, QLatin1String("SELECT DISTINCT my_rig FROM contacts ORDER BY my_rig")); + refreshCombo(ui->myAntennaCombo, QLatin1String("SELECT DISTINCT my_antenna FROM contacts ORDER BY my_antenna")); + refreshCombo(ui->bandCombo, QLatin1String("SELECT DISTINCT band FROM contacts c, bands b WHERE c.band = b.name ORDER BY b.start_freq;")); + refreshCombo(ui->myGridCombo, QLatin1String("SELECT DISTINCT UPPER(my_gridsquare) FROM contacts ORDER BY my_gridsquare")); } -void StatisticsWidget::refreshRigCombo() +void StatisticsWidget::setSubTypesCombo(int mainTypeIdx) { FCT_IDENTIFICATION; - refreshCombo(ui->myRigCombo, "SELECT DISTINCT my_rig FROM contacts ORDER BY my_rig"); -} + ui->statTypeSecCombo->blockSignals(true); -void StatisticsWidget::refreshAntCombo() -{ - FCT_IDENTIFICATION; + ui->statTypeSecCombo->clear(); - refreshCombo(ui->myAntennaCombo, "SELECT DISTINCT my_antenna FROM contacts ORDER BY my_antenna"); -} + ui->lotwCheckBox->setEnabled(false); + ui->eqslCheckBox->setEnabled(false); + ui->paperCheckBox->setEnabled(false); -void StatisticsWidget::refreshBandCombo() -{ - FCT_IDENTIFICATION; + switch ( mainTypeIdx ) + { + /* QSOs per */ + case 0: + { + ui->statTypeSecCombo->addItem(tr("Year")); + ui->statTypeSecCombo->addItem(tr("Month")); + ui->statTypeSecCombo->addItem(tr("Day in Week")); + ui->statTypeSecCombo->addItem(tr("Hour")); + ui->statTypeSecCombo->addItem(tr("Mode")); + ui->statTypeSecCombo->addItem(tr("Band")); + ui->statTypeSecCombo->addItem(tr("Continent")); + ui->statTypeSecCombo->addItem(tr("Propagation Mode")); + } + break; - refreshCombo(ui->bandCombo, "SELECT DISTINCT band FROM contacts c, bands b WHERE c.band = b.name ORDER BY b.start_freq;"); -} + /* Percents */ + case 1: + { + ui->statTypeSecCombo->addItem(tr("Confirmed / Not Confirmed")); + } + break; -void StatisticsWidget::refreshGridCombo() -{ - FCT_IDENTIFICATION; + /* TOP 10 */ + case 2: + { + ui->statTypeSecCombo->addItem(tr("Countries")); + ui->statTypeSecCombo->addItem(tr("Big Gridsquares")); + } + break; + + /* Histogram */ + case 3: + { + QString unit; + Gridsquare::distance2localeUnitDistance(0, unit); + ui->statTypeSecCombo->addItem(tr("Distance") + QString(" [%1]").arg(unit)); + } + break; + + /* Show on Map */ + case 4: + { + ui->statTypeSecCombo->addItem(tr("QSOs")); + ui->statTypeSecCombo->addItem(tr("Confirmed/Worked Grids")); + ui->statTypeSecCombo->addItem(tr("ODX")); + ui->lotwCheckBox->setEnabled(true); + ui->eqslCheckBox->setEnabled(true); + ui->paperCheckBox->setEnabled(true); + } + break; + } - refreshCombo(ui->myGridCombo, "SELECT DISTINCT UPPER(my_gridsquare) FROM contacts ORDER BY my_gridsquare"); + ui->statTypeSecCombo->blockSignals(false); } -void StatisticsWidget::refreshCombo(QComboBox * combo, QString sqlQeury) +void StatisticsWidget::refreshCombo(QComboBox * combo, + const QString &sqlQeury) { FCT_IDENTIFICATION; QString currSelection = combo->currentText(); combo->blockSignals(true); - //combo->clear(); - combo->setModel(new SqlListModel(sqlQeury,tr("All"), this)); - combo->setCurrentText(currSelection); combo->blockSignals(false); - } diff --git a/ui/StatisticsWidget.h b/ui/StatisticsWidget.h index a7237876..99b591be 100644 --- a/ui/StatisticsWidget.h +++ b/ui/StatisticsWidget.h @@ -25,28 +25,31 @@ class StatisticsWidget : public QWidget public slots: void mainStatChanged(int); - void refreshGraph(); void dateRangeCheckBoxChanged(int); void mapLoaded(bool); void changeTheme(int); + void refreshWidget(); +private slots: + void refreshGraph(); public: explicit StatisticsWidget(QWidget *parent = nullptr); ~StatisticsWidget(); +protected: + bool event(QEvent *event) override; + private: + void drawBarGraphs(const QString &title, QSqlQuery &query); void drawPieGraph(const QString &title, QPieSeries* series); void drawMyLocationsOnMap(QSqlQuery &); void drawPointsOnMap(QSqlQuery&); void drawFilledGridsOnMap(QSqlQuery&); - void refreshCallCombo(); - void refreshRigCombo(); - void refreshAntCombo(); - void refreshBandCombo(); - void refreshGridCombo(); - void refreshCombo(QComboBox * combo, QString sqlQeury); + void refreshCombos(); + void setSubTypesCombo(int mainTypeIdx); + void refreshCombo(QComboBox * combo, const QString &sqlQeury); private: Ui::StatisticsWidget *ui; diff --git a/ui/WsjtxFilterDialog.cpp b/ui/WsjtxFilterDialog.cpp index 4bb80555..9760638d 100644 --- a/ui/WsjtxFilterDialog.cpp +++ b/ui/WsjtxFilterDialog.cpp @@ -114,7 +114,7 @@ void WsjtxFilterDialog::accept() { memberList.append("DUMMYCLUB"); - for ( QCheckBox* item: qAsConst(memberListCheckBoxes) ) + for ( QCheckBox* item: static_cast&>(memberListCheckBoxes) ) { if ( item->isChecked() ) { @@ -155,7 +155,7 @@ void WsjtxFilterDialog::generateMembershipCheckboxes() { int elementIndex = 0; - for ( QCheckBox* item: qAsConst(memberListCheckBoxes) ) + for ( QCheckBox* item: static_cast&>(memberListCheckBoxes) ) { ui->dxMemberGrid->addWidget(item, elementIndex / 3, elementIndex % 3); elementIndex++; diff --git a/ui/WsjtxWidget.cpp b/ui/WsjtxWidget.cpp index e956c50b..3e98dc76 100644 --- a/ui/WsjtxWidget.cpp +++ b/ui/WsjtxWidget.cpp @@ -21,7 +21,7 @@ MODULE_IDENTIFICATION("qlog.ui.wsjtxswidget"); WsjtxWidget::WsjtxWidget(QWidget *parent) : QWidget(parent), ui(new Ui::WsjtxWidget), - cqRE("^CQ (DX |TEST |[A-Z]{0,2} )?([A-Z0-9\\/]+) ?([A-Z]{2}[0-9]{2})?.*") + cqRE("(^(?:(?P(?:CQ|DE|QRZ)(?:\\s?DX|\\s(?:[A-Z]{1,4}|\\d{3}))|[A-Z0-9\\/]+|\\.{3})\\s)(?:(?P[A-Z0-9\\/]+)(?:\\s(?P[-+A-Z0-9]+)(?:\\s(?P(?:OOO|(?!RR73)[A-R]{2}[0-9]{2})))?)?)?)") { FCT_IDENTIFICATION; @@ -64,8 +64,8 @@ void WsjtxWidget::decodeReceived(WsjtxDecode decode) WsjtxEntry entry; entry.decode = decode; - entry.callsign = match.captured(2); - entry.grid = match.captured(3); + entry.callsign = match.captured(3); + entry.grid = match.captured(4); entry.dxcc = Data::instance()->lookupDxcc(entry.callsign); entry.status = Data::instance()->dxccStatus(entry.dxcc.dxcc, currBand, BandPlan::MODE_GROUP_STRING_DIGITAL); entry.receivedTime = QDateTime::currentDateTimeUtc(); @@ -176,7 +176,7 @@ void WsjtxWidget::statusReceived(WsjtxStatus newStatus) if ( this->status.dx_call != newStatus.dx_call || this->status.dx_grid != newStatus.dx_grid ) { - emit showDxDetails(newStatus.dx_call, newStatus.dx_grid); + emit callsignSelected(newStatus.dx_call, newStatus.dx_grid); } if ( this->status.mode != newStatus.mode ) @@ -209,7 +209,7 @@ void WsjtxWidget::tableViewDoubleClicked(QModelIndex index) const QModelIndex &source_index = proxyModel->mapToSource(index); const WsjtxEntry &entry = wsjtxTableModel->getEntry(source_index); - emit showDxDetails(entry.callsign, entry.grid); + //emit callsignSelected(entry.callsign, entry.grid); // it is not needed to send this - Qlog receives the change via WSJTX emit reply(entry.decode); } @@ -221,7 +221,7 @@ void WsjtxWidget::callsignClicked(QString callsign) if ( entry.callsign.isEmpty() ) return; - emit showDxDetails(callsign, entry.grid); + emit callsignSelected(callsign, entry.grid); emit reply(entry.decode); } @@ -335,11 +335,11 @@ void WsjtxWidget::restoreTableHeaderState() FCT_IDENTIFICATION; QSettings settings; - QVariant state = settings.value("wsjtx/state"); + const QByteArray &state = settings.value("wsjtx/state").toByteArray(); - if (!state.isNull()) + if (!state.isEmpty()) { - ui->tableView->horizontalHeader()->restoreState(state.toByteArray()); + ui->tableView->horizontalHeader()->restoreState(state); } } diff --git a/ui/WsjtxWidget.h b/ui/WsjtxWidget.h index 4b4e7257..c8029908 100644 --- a/ui/WsjtxWidget.h +++ b/ui/WsjtxWidget.h @@ -32,7 +32,7 @@ private slots: void actionFilter(); signals: - void showDxDetails(QString callsign, QString grid); + void callsignSelected(QString callsign, QString grid); void reply(WsjtxDecode); void CQSpot(WsjtxEntry); void filteredCQSpot(WsjtxEntry);