not1mm 23.3.25__py3-none-any.whl → 23.3.27__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- not1mm/__main__.py +17 -125
- not1mm/lib/database.py +24 -0
- not1mm/lib/version.py +1 -1
- not1mm/plugins/cq_wpx_cw.py +389 -0
- not1mm/plugins/cq_wpx_ssb.py +138 -4
- {not1mm-23.3.25.dist-info → not1mm-23.3.27.dist-info}/METADATA +11 -1
- {not1mm-23.3.25.dist-info → not1mm-23.3.27.dist-info}/RECORD +11 -10
- {not1mm-23.3.25.dist-info → not1mm-23.3.27.dist-info}/LICENSE +0 -0
- {not1mm-23.3.25.dist-info → not1mm-23.3.27.dist-info}/WHEEL +0 -0
- {not1mm-23.3.25.dist-info → not1mm-23.3.27.dist-info}/entry_points.txt +0 -0
- {not1mm-23.3.25.dist-info → not1mm-23.3.27.dist-info}/top_level.txt +0 -0
not1mm/__main__.py
CHANGED
@@ -663,7 +663,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
663
663
|
|
664
664
|
def select_contest(self):
|
665
665
|
"""Load contest"""
|
666
|
-
self.contest = doimp("
|
666
|
+
self.contest = doimp("cq_wpx_cw")
|
667
667
|
logger.debug("Loaded Contest Name = %s", self.contest.name)
|
668
668
|
self.contest.init_contest(self)
|
669
669
|
|
@@ -984,10 +984,12 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
984
984
|
"""Called when text in the callsign field has changed"""
|
985
985
|
text = self.callsign.text()
|
986
986
|
text = text.upper()
|
987
|
-
|
987
|
+
position = self.callsign.cursorPosition()
|
988
|
+
stripped_text = text.strip().replace(" ", "")
|
988
989
|
self.callsign.setText(stripped_text)
|
990
|
+
self.callsign.setCursorPosition(position)
|
989
991
|
|
990
|
-
if
|
992
|
+
if " " in text:
|
991
993
|
if stripped_text == "CW":
|
992
994
|
self.setmode("CW")
|
993
995
|
self.radio_state["mode"] = "CW"
|
@@ -1113,9 +1115,18 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
1113
1115
|
"""Checks if a callsign is a dupe on current band/mode."""
|
1114
1116
|
band = float(get_logged_band(str(self.radio_state.get("vfoa", 0.0))))
|
1115
1117
|
mode = self.radio_state.get("mode", "")
|
1116
|
-
debugline =
|
1118
|
+
debugline = (
|
1119
|
+
f"Call: {call} Band: {band} Mode: {mode} Dupetype: {self.contest.dupe_type}"
|
1120
|
+
)
|
1117
1121
|
logger.debug("%s", debugline)
|
1118
|
-
|
1122
|
+
if self.contest.dupe_type == 1:
|
1123
|
+
result = self.database.check_dupe(call)
|
1124
|
+
if self.contest.dupe_type == 2:
|
1125
|
+
result = self.database.check_dupe_on_band(call, band)
|
1126
|
+
if self.contest.dupe_type == 3:
|
1127
|
+
result = self.database.check_dupe_on_band_mode(call, band, mode)
|
1128
|
+
if self.contest.dupe_type == 4:
|
1129
|
+
result = {"isdupe": False}
|
1119
1130
|
debugline = f"{result}"
|
1120
1131
|
logger.debug("%s", debugline)
|
1121
1132
|
return result.get("isdupe", False)
|
@@ -1242,126 +1253,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
1242
1253
|
"""Generates Cabrillo file. Maybe."""
|
1243
1254
|
# https://www.cqwpx.com/cabrillo.htm
|
1244
1255
|
logger.debug("******Cabrillo*****")
|
1245
|
-
|
1246
|
-
str(Path.home())
|
1247
|
-
+ "/"
|
1248
|
-
+ f"{self.pref.get('callsign').upper()}_{self.contest.cabrillo_name}.log"
|
1249
|
-
)
|
1250
|
-
logger.debug("%s", filename)
|
1251
|
-
log = self.database.fetch_all_contacts_asc()
|
1252
|
-
try:
|
1253
|
-
with open(filename, "w", encoding="ascii") as file_descriptor:
|
1254
|
-
print("START-OF-LOG: 3.0", end="\r\n", file=file_descriptor)
|
1255
|
-
print(
|
1256
|
-
f"CREATED-BY: Not1MM v{__version__}",
|
1257
|
-
end="\r\n",
|
1258
|
-
file=file_descriptor,
|
1259
|
-
)
|
1260
|
-
print(
|
1261
|
-
f"CONTEST: {self.contest.cabrillo_name}",
|
1262
|
-
end="\r\n",
|
1263
|
-
file=file_descriptor,
|
1264
|
-
)
|
1265
|
-
print(
|
1266
|
-
f"CALLSIGN: {self.pref.get('callsign','')}",
|
1267
|
-
end="\r\n",
|
1268
|
-
file=file_descriptor,
|
1269
|
-
)
|
1270
|
-
print(
|
1271
|
-
f"LOCATION: {self.pref.get('section', '')}",
|
1272
|
-
end="\r\n",
|
1273
|
-
file=file_descriptor,
|
1274
|
-
)
|
1275
|
-
# print(
|
1276
|
-
# f"ARRL-SECTION: {self.pref.get('section', '')}",
|
1277
|
-
# end="\r\n",
|
1278
|
-
# file=file_descriptor,
|
1279
|
-
# )
|
1280
|
-
# CATEGORY-OPERATOR: SINGLE-OP
|
1281
|
-
# CATEGORY-ASSISTED: NON-ASSISTED
|
1282
|
-
# CATEGORY-BAND: ALL
|
1283
|
-
# CATEGORY-MODE: SSB
|
1284
|
-
# CATEGORY-TRANSMITTER: ONE
|
1285
|
-
# CATEGORY-OVERLAY: CLASSIC
|
1286
|
-
# GRID-LOCATOR: DM13at
|
1287
|
-
print(
|
1288
|
-
f"CATEGORY: {None}",
|
1289
|
-
end="\r\n",
|
1290
|
-
file=file_descriptor,
|
1291
|
-
)
|
1292
|
-
print("CATEGORY-POWER: ", end="\r\n", file=file_descriptor)
|
1293
|
-
|
1294
|
-
print(
|
1295
|
-
f"CLAIMED-SCORE: {self.contest.calc_score(self)}",
|
1296
|
-
end="\r\n",
|
1297
|
-
file=file_descriptor,
|
1298
|
-
)
|
1299
|
-
print(
|
1300
|
-
"OPERATORS: ",
|
1301
|
-
end="\r\n",
|
1302
|
-
file=file_descriptor,
|
1303
|
-
)
|
1304
|
-
print(
|
1305
|
-
f"NAME: {self.pref.get('name', '')}",
|
1306
|
-
end="\r\n",
|
1307
|
-
file=file_descriptor,
|
1308
|
-
)
|
1309
|
-
print(
|
1310
|
-
f"ADDRESS: {self.pref.get('address1', '')}",
|
1311
|
-
end="\r\n",
|
1312
|
-
file=file_descriptor,
|
1313
|
-
)
|
1314
|
-
print(
|
1315
|
-
f"ADDRESS-CITY: {self.pref.get('city', '')}",
|
1316
|
-
end="\r\n",
|
1317
|
-
file=file_descriptor,
|
1318
|
-
)
|
1319
|
-
print(
|
1320
|
-
f"ADDRESS-STATE-PROVINCE: {self.pref.get('state', '')}",
|
1321
|
-
end="\r\n",
|
1322
|
-
file=file_descriptor,
|
1323
|
-
)
|
1324
|
-
print(
|
1325
|
-
f"ADDRESS-POSTALCODE: {self.pref.get('zip', '')}",
|
1326
|
-
end="\r\n",
|
1327
|
-
file=file_descriptor,
|
1328
|
-
)
|
1329
|
-
print(
|
1330
|
-
f"ADDRESS-COUNTRY: {self.pref.get('country', '')}",
|
1331
|
-
end="\r\n",
|
1332
|
-
file=file_descriptor,
|
1333
|
-
)
|
1334
|
-
print(
|
1335
|
-
f"EMAIL: {self.pref.get('email', '')}",
|
1336
|
-
end="\r\n",
|
1337
|
-
file=file_descriptor,
|
1338
|
-
)
|
1339
|
-
for contact in log:
|
1340
|
-
the_date_and_time = contact.get("TS", "")
|
1341
|
-
mode = contact.get("Mode", "")
|
1342
|
-
if mode == "LSB" or mode == "USB":
|
1343
|
-
mode = "PH"
|
1344
|
-
frequency = str(int(contact.get("Freq", "0"))).rjust(5)
|
1345
|
-
|
1346
|
-
loggeddate = the_date_and_time[:10]
|
1347
|
-
loggedtime = the_date_and_time[11:13] + the_date_and_time[14:16]
|
1348
|
-
print(
|
1349
|
-
f"QSO: {frequency} {mode} {loggeddate} {loggedtime} "
|
1350
|
-
f"{contact.get('StationPrefix', '').ljust(13)} "
|
1351
|
-
f"{str(contact.get('SNT', '')).ljust(3)} "
|
1352
|
-
f"{str(contact.get('SentNr', '')).ljust(6)} "
|
1353
|
-
f"{contact.get('Call', '').ljust(13)} "
|
1354
|
-
f"{str(contact.get('RCV', '')).ljust(3)} "
|
1355
|
-
f"{str(contact.get('NR', '')).ljust(6)}",
|
1356
|
-
end="\r\n",
|
1357
|
-
file=file_descriptor,
|
1358
|
-
)
|
1359
|
-
print("END-OF-LOG:", end="\r\n", file=file_descriptor)
|
1360
|
-
except IOError as exception:
|
1361
|
-
logger.critical(
|
1362
|
-
"cabrillo: IO error: %s, writing to %s", exception, filename
|
1363
|
-
)
|
1364
|
-
return
|
1256
|
+
self.contest.cabrillo(self)
|
1365
1257
|
|
1366
1258
|
|
1367
1259
|
def load_fonts_from_dir(directory: str) -> set:
|
not1mm/lib/database.py
CHANGED
@@ -370,6 +370,30 @@ class DataBase:
|
|
370
370
|
)
|
371
371
|
return cursor.fetchone()
|
372
372
|
|
373
|
+
def check_dupe_on_band(self, call, band) -> dict:
|
374
|
+
"""Checks if a call is dupe on band/mode"""
|
375
|
+
with sqlite3.connect(self.database) as conn:
|
376
|
+
conn.row_factory = self.row_factory
|
377
|
+
cursor = conn.cursor()
|
378
|
+
print(
|
379
|
+
f"select count(*) as isdupe from dxlog where Call = '{call}' and Band = '{band}';"
|
380
|
+
)
|
381
|
+
cursor.execute(
|
382
|
+
f"select count(*) as isdupe from dxlog where Call = '{call}' and Band = '{band}';"
|
383
|
+
)
|
384
|
+
return cursor.fetchone()
|
385
|
+
|
386
|
+
def check_dupe(self, call) -> dict:
|
387
|
+
"""Checks if a call is dupe on band/mode"""
|
388
|
+
with sqlite3.connect(self.database) as conn:
|
389
|
+
conn.row_factory = self.row_factory
|
390
|
+
cursor = conn.cursor()
|
391
|
+
print(f"select count(*) as isdupe from dxlog where Call = '{call}';")
|
392
|
+
cursor.execute(
|
393
|
+
f"select count(*) as isdupe from dxlog where Call = '{call}';"
|
394
|
+
)
|
395
|
+
return cursor.fetchone()
|
396
|
+
|
373
397
|
def fetch_points(self) -> dict:
|
374
398
|
"""return points"""
|
375
399
|
with sqlite3.connect(self.database) as conn:
|
not1mm/lib/version.py
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
"""It's the version"""
|
2
|
-
__version__ = "23.3.
|
2
|
+
__version__ = "23.3.27"
|
@@ -0,0 +1,389 @@
|
|
1
|
+
"""CQ WPX CW plugin"""
|
2
|
+
|
3
|
+
# pylint: disable=invalid-name
|
4
|
+
import logging
|
5
|
+
from pathlib import Path
|
6
|
+
|
7
|
+
from PyQt5 import QtWidgets
|
8
|
+
|
9
|
+
from not1mm.lib.version import __version__
|
10
|
+
|
11
|
+
logger = logging.getLogger("__main__")
|
12
|
+
|
13
|
+
name = "CQ WPX CW"
|
14
|
+
cabrillo_name = "CQ-WPX-CW"
|
15
|
+
mode = "CW" # CW SSB BOTH RTTY
|
16
|
+
|
17
|
+
# 1 once per contest, 2 work each band, 3 each band/mode, 4 no dupe checking
|
18
|
+
dupe_type = 2
|
19
|
+
|
20
|
+
|
21
|
+
def init_contest(self):
|
22
|
+
"""setup plugin"""
|
23
|
+
set_tab_next(self)
|
24
|
+
set_tab_prev(self)
|
25
|
+
interface(self)
|
26
|
+
self.next_field = self.other_2
|
27
|
+
|
28
|
+
|
29
|
+
def interface(self):
|
30
|
+
"""Setup user interface"""
|
31
|
+
self.field1.show()
|
32
|
+
self.field2.show()
|
33
|
+
self.field3.show()
|
34
|
+
self.field4.show()
|
35
|
+
label = self.field3.findChild(QtWidgets.QLabel)
|
36
|
+
label.setText("SentNR")
|
37
|
+
label = self.field4.findChild(QtWidgets.QLabel)
|
38
|
+
label.setText("RcvNR")
|
39
|
+
|
40
|
+
|
41
|
+
def set_tab_next(self):
|
42
|
+
"""Set TAB Advances"""
|
43
|
+
self.tab_next = {
|
44
|
+
self.callsign: self.field1.findChild(QtWidgets.QLineEdit),
|
45
|
+
self.field1.findChild(QtWidgets.QLineEdit): self.field2.findChild(
|
46
|
+
QtWidgets.QLineEdit
|
47
|
+
),
|
48
|
+
self.field2.findChild(QtWidgets.QLineEdit): self.field3.findChild(
|
49
|
+
QtWidgets.QLineEdit
|
50
|
+
),
|
51
|
+
self.field3.findChild(QtWidgets.QLineEdit): self.field4.findChild(
|
52
|
+
QtWidgets.QLineEdit
|
53
|
+
),
|
54
|
+
self.field4.findChild(QtWidgets.QLineEdit): self.callsign,
|
55
|
+
}
|
56
|
+
|
57
|
+
|
58
|
+
def set_tab_prev(self):
|
59
|
+
"""Set TAB Advances"""
|
60
|
+
self.tab_prev = {
|
61
|
+
self.callsign: self.field4.findChild(QtWidgets.QLineEdit),
|
62
|
+
self.field1.findChild(QtWidgets.QLineEdit): self.callsign,
|
63
|
+
self.field2.findChild(QtWidgets.QLineEdit): self.field1.findChild(
|
64
|
+
QtWidgets.QLineEdit
|
65
|
+
),
|
66
|
+
self.field3.findChild(QtWidgets.QLineEdit): self.field2.findChild(
|
67
|
+
QtWidgets.QLineEdit
|
68
|
+
),
|
69
|
+
self.field4.findChild(QtWidgets.QLineEdit): self.field3.findChild(
|
70
|
+
QtWidgets.QLineEdit
|
71
|
+
),
|
72
|
+
}
|
73
|
+
|
74
|
+
|
75
|
+
def set_contact_vars(self):
|
76
|
+
"""Contest Specific"""
|
77
|
+
self.contact["SNT"] = self.sent.text()
|
78
|
+
self.contact["RCV"] = self.receive.text()
|
79
|
+
self.contact["SentNr"] = self.other_1.text()
|
80
|
+
self.contact["NR"] = self.other_2.text()
|
81
|
+
if self.contact.get("WPXPrefix"):
|
82
|
+
result = self.database.fetch_wpx_exists(self.contact.get("WPXPrefix", ""))
|
83
|
+
if result.get("wpx_count"):
|
84
|
+
self.contact["IsMultiplier1"] = 0
|
85
|
+
else:
|
86
|
+
self.contact["IsMultiplier1"] = 1
|
87
|
+
|
88
|
+
|
89
|
+
def prefill(self):
|
90
|
+
"""Fill SentNR"""
|
91
|
+
result = self.database.get_serial()
|
92
|
+
serial_nr = str(result.get("serial_nr", "1"))
|
93
|
+
if serial_nr == "None":
|
94
|
+
serial_nr = "1"
|
95
|
+
field = self.field3.findChild(QtWidgets.QLineEdit)
|
96
|
+
if len(field.text()) == 0:
|
97
|
+
field.setText(serial_nr)
|
98
|
+
|
99
|
+
|
100
|
+
def points(self):
|
101
|
+
"""Calc point"""
|
102
|
+
result = self.cty_lookup(self.pref.get("callsign", ""))
|
103
|
+
if result:
|
104
|
+
for item in result.items():
|
105
|
+
mycountry = item[1].get("entity", "")
|
106
|
+
mycontinent = item[1].get("continent", "")
|
107
|
+
result = self.cty_lookup(self.contact.get("Call", ""))
|
108
|
+
band = int(int(float(self.contact.get("Freq"))) / 1000)
|
109
|
+
if result:
|
110
|
+
for item in result.items():
|
111
|
+
entity = item[1].get("entity", "")
|
112
|
+
continent = item[1].get("continent", "")
|
113
|
+
if mycountry.upper() == entity.upper():
|
114
|
+
return 1
|
115
|
+
if mycontinent and continent == "NA":
|
116
|
+
if band in [28, 21, 14]:
|
117
|
+
return 2
|
118
|
+
return 4
|
119
|
+
if mycontinent == continent:
|
120
|
+
if band in [28, 21, 14]:
|
121
|
+
return 1
|
122
|
+
return 2
|
123
|
+
if band in [28, 21, 14]:
|
124
|
+
return 3
|
125
|
+
return 6
|
126
|
+
return 0
|
127
|
+
|
128
|
+
|
129
|
+
def show_mults(self):
|
130
|
+
"""Return display string for mults"""
|
131
|
+
result = self.database.fetch_wpx_count()
|
132
|
+
if result:
|
133
|
+
return int(result.get("wpx_count", 0))
|
134
|
+
return 0
|
135
|
+
|
136
|
+
|
137
|
+
def show_qso(self):
|
138
|
+
"""Return qso count"""
|
139
|
+
result = self.database.fetch_qso_count()
|
140
|
+
if result:
|
141
|
+
return int(result.get("qsos", 0))
|
142
|
+
return 0
|
143
|
+
|
144
|
+
|
145
|
+
def get_points(self):
|
146
|
+
"""Return raw points before mults"""
|
147
|
+
result = self.database.fetch_points()
|
148
|
+
if result:
|
149
|
+
return int(result.get("Points", 0))
|
150
|
+
return 0
|
151
|
+
|
152
|
+
|
153
|
+
def calc_score(self):
|
154
|
+
"""Return calculated score"""
|
155
|
+
result = self.database.fetch_points()
|
156
|
+
if result is not None:
|
157
|
+
score = result.get("Points", "0")
|
158
|
+
if score is None:
|
159
|
+
score = "0"
|
160
|
+
contest_points = int(score)
|
161
|
+
result = self.database.fetch_wpx_count()
|
162
|
+
mults = int(result.get("wpx_count", 0))
|
163
|
+
return contest_points * mults
|
164
|
+
return 0
|
165
|
+
|
166
|
+
|
167
|
+
def adif(self):
|
168
|
+
"""
|
169
|
+
Creates an ADIF file of the contacts made.
|
170
|
+
"""
|
171
|
+
filename = (
|
172
|
+
str(Path.home())
|
173
|
+
+ "/"
|
174
|
+
+ f"{self.pref.get('callsign').upper()}_{cabrillo_name}.adi"
|
175
|
+
)
|
176
|
+
log = self.database.fetch_all_contacts_asc()
|
177
|
+
try:
|
178
|
+
with open(filename, "w", encoding="utf-8") as file_descriptor:
|
179
|
+
print("<ADIF_VER:5>2.2.0", end="\r\n", file=file_descriptor)
|
180
|
+
print("<EOH>", end="\r\n", file=file_descriptor)
|
181
|
+
for contact in log:
|
182
|
+
|
183
|
+
hiscall = contact.get("Call", "")
|
184
|
+
the_date_and_time = contact.get("TS")
|
185
|
+
# band = contact.get("Band")
|
186
|
+
themode = contact.get("Mode")
|
187
|
+
frequency = str(contact.get("Freq", 0) / 1000)
|
188
|
+
sentrst = contact.get("SNT", "")
|
189
|
+
rcvrst = contact.get("RCV", "")
|
190
|
+
sentnr = str(contact.get("SentNr", "59"))
|
191
|
+
rcvnr = str(contact.get("NR", "59"))
|
192
|
+
grid = contact.get("GridSquare", "")
|
193
|
+
comment = contact.get("ContestName", "")
|
194
|
+
loggeddate = the_date_and_time[:10]
|
195
|
+
loggedtime = the_date_and_time[11:13] + the_date_and_time[14:16]
|
196
|
+
print(
|
197
|
+
f"<QSO_DATE:{len(''.join(loggeddate.split('-')))}:d>"
|
198
|
+
f"{''.join(loggeddate.split('-'))}",
|
199
|
+
end="\r\n",
|
200
|
+
file=file_descriptor,
|
201
|
+
)
|
202
|
+
print(
|
203
|
+
f"<TIME_ON:{len(loggedtime)}>{loggedtime}",
|
204
|
+
end="\r\n",
|
205
|
+
file=file_descriptor,
|
206
|
+
)
|
207
|
+
print(
|
208
|
+
f"<CALL:{len(hiscall)}>{hiscall}",
|
209
|
+
end="\r\n",
|
210
|
+
file=file_descriptor,
|
211
|
+
)
|
212
|
+
print(
|
213
|
+
f"<MODE:{len(themode)}>{themode}", end="\r\n", file=file_descriptor
|
214
|
+
)
|
215
|
+
# print(
|
216
|
+
# f"<BAND:{len(band + 'M')}>{band + 'M'}",
|
217
|
+
# end="\r\n",
|
218
|
+
# file=file_descriptor,
|
219
|
+
# )
|
220
|
+
try:
|
221
|
+
print(
|
222
|
+
f"<FREQ:{len(frequency)}>{frequency}",
|
223
|
+
end="\r\n",
|
224
|
+
file=file_descriptor,
|
225
|
+
)
|
226
|
+
except TypeError:
|
227
|
+
pass # This is bad form... I can't remember why this is in a try block
|
228
|
+
|
229
|
+
print(
|
230
|
+
f"<RST_SENT:{len(sentrst)}>{sentrst}",
|
231
|
+
end="\r\n",
|
232
|
+
file=file_descriptor,
|
233
|
+
)
|
234
|
+
print(
|
235
|
+
f"<RST_RCVD:{len(rcvrst)}>{rcvrst}",
|
236
|
+
end="\r\n",
|
237
|
+
file=file_descriptor,
|
238
|
+
)
|
239
|
+
|
240
|
+
print(
|
241
|
+
f"<STX_STRING:{len(sentnr)}>{sentnr}",
|
242
|
+
end="\r\n",
|
243
|
+
file=file_descriptor,
|
244
|
+
)
|
245
|
+
print(
|
246
|
+
f"<SRX_STRING:{len(rcvnr)}>{rcvnr}",
|
247
|
+
end="\r\n",
|
248
|
+
file=file_descriptor,
|
249
|
+
)
|
250
|
+
if len(grid) > 1:
|
251
|
+
print(
|
252
|
+
f"<GRIDSQUARE:{len(grid)}>{grid}",
|
253
|
+
end="\r\n",
|
254
|
+
file=file_descriptor,
|
255
|
+
)
|
256
|
+
|
257
|
+
print(
|
258
|
+
f"<COMMENT:{len(comment)}>{comment}",
|
259
|
+
end="\r\n",
|
260
|
+
file=file_descriptor,
|
261
|
+
)
|
262
|
+
print("<EOR>", end="\r\n", file=file_descriptor)
|
263
|
+
print("", end="\r\n", file=file_descriptor)
|
264
|
+
except IOError:
|
265
|
+
...
|
266
|
+
|
267
|
+
|
268
|
+
def cabrillo(self):
|
269
|
+
"""Generates Cabrillo file. Maybe."""
|
270
|
+
# https://www.cqwpx.com/cabrillo.htm
|
271
|
+
logger.debug("******Cabrillo*****")
|
272
|
+
filename = (
|
273
|
+
str(Path.home())
|
274
|
+
+ "/"
|
275
|
+
+ f"{self.pref.get('callsign').upper()}_{cabrillo_name}.log"
|
276
|
+
)
|
277
|
+
logger.debug("%s", filename)
|
278
|
+
log = self.database.fetch_all_contacts_asc()
|
279
|
+
try:
|
280
|
+
with open(filename, "w", encoding="ascii") as file_descriptor:
|
281
|
+
print("START-OF-LOG: 3.0", end="\r\n", file=file_descriptor)
|
282
|
+
print(
|
283
|
+
f"CREATED-BY: Not1MM v{__version__}",
|
284
|
+
end="\r\n",
|
285
|
+
file=file_descriptor,
|
286
|
+
)
|
287
|
+
print(
|
288
|
+
f"CONTEST: {cabrillo_name}",
|
289
|
+
end="\r\n",
|
290
|
+
file=file_descriptor,
|
291
|
+
)
|
292
|
+
print(
|
293
|
+
f"CALLSIGN: {self.pref.get('callsign','')}",
|
294
|
+
end="\r\n",
|
295
|
+
file=file_descriptor,
|
296
|
+
)
|
297
|
+
print(
|
298
|
+
f"LOCATION: {self.pref.get('section', '')}",
|
299
|
+
end="\r\n",
|
300
|
+
file=file_descriptor,
|
301
|
+
)
|
302
|
+
# print(
|
303
|
+
# f"ARRL-SECTION: {self.pref.get('section', '')}",
|
304
|
+
# end="\r\n",
|
305
|
+
# file=file_descriptor,
|
306
|
+
# )
|
307
|
+
# CATEGORY-OPERATOR: SINGLE-OP
|
308
|
+
# CATEGORY-ASSISTED: NON-ASSISTED
|
309
|
+
# CATEGORY-BAND: ALL
|
310
|
+
# CATEGORY-MODE: SSB
|
311
|
+
# CATEGORY-TRANSMITTER: ONE
|
312
|
+
# CATEGORY-OVERLAY: CLASSIC
|
313
|
+
# GRID-LOCATOR: DM13at
|
314
|
+
print(
|
315
|
+
f"CATEGORY: {None}",
|
316
|
+
end="\r\n",
|
317
|
+
file=file_descriptor,
|
318
|
+
)
|
319
|
+
print("CATEGORY-POWER: ", end="\r\n", file=file_descriptor)
|
320
|
+
|
321
|
+
print(
|
322
|
+
f"CLAIMED-SCORE: {calc_score(self)}",
|
323
|
+
end="\r\n",
|
324
|
+
file=file_descriptor,
|
325
|
+
)
|
326
|
+
print(
|
327
|
+
"OPERATORS: ",
|
328
|
+
end="\r\n",
|
329
|
+
file=file_descriptor,
|
330
|
+
)
|
331
|
+
print(
|
332
|
+
f"NAME: {self.pref.get('name', '')}",
|
333
|
+
end="\r\n",
|
334
|
+
file=file_descriptor,
|
335
|
+
)
|
336
|
+
print(
|
337
|
+
f"ADDRESS: {self.pref.get('address1', '')}",
|
338
|
+
end="\r\n",
|
339
|
+
file=file_descriptor,
|
340
|
+
)
|
341
|
+
print(
|
342
|
+
f"ADDRESS-CITY: {self.pref.get('city', '')}",
|
343
|
+
end="\r\n",
|
344
|
+
file=file_descriptor,
|
345
|
+
)
|
346
|
+
print(
|
347
|
+
f"ADDRESS-STATE-PROVINCE: {self.pref.get('state', '')}",
|
348
|
+
end="\r\n",
|
349
|
+
file=file_descriptor,
|
350
|
+
)
|
351
|
+
print(
|
352
|
+
f"ADDRESS-POSTALCODE: {self.pref.get('zip', '')}",
|
353
|
+
end="\r\n",
|
354
|
+
file=file_descriptor,
|
355
|
+
)
|
356
|
+
print(
|
357
|
+
f"ADDRESS-COUNTRY: {self.pref.get('country', '')}",
|
358
|
+
end="\r\n",
|
359
|
+
file=file_descriptor,
|
360
|
+
)
|
361
|
+
print(
|
362
|
+
f"EMAIL: {self.pref.get('email', '')}",
|
363
|
+
end="\r\n",
|
364
|
+
file=file_descriptor,
|
365
|
+
)
|
366
|
+
for contact in log:
|
367
|
+
the_date_and_time = contact.get("TS", "")
|
368
|
+
themode = contact.get("Mode", "")
|
369
|
+
if themode == "LSB" or themode == "USB":
|
370
|
+
themode = "PH"
|
371
|
+
frequency = str(int(contact.get("Freq", "0"))).rjust(5)
|
372
|
+
|
373
|
+
loggeddate = the_date_and_time[:10]
|
374
|
+
loggedtime = the_date_and_time[11:13] + the_date_and_time[14:16]
|
375
|
+
print(
|
376
|
+
f"QSO: {frequency} {themode} {loggeddate} {loggedtime} "
|
377
|
+
f"{contact.get('StationPrefix', '').ljust(13)} "
|
378
|
+
f"{str(contact.get('SNT', '')).ljust(3)} "
|
379
|
+
f"{str(contact.get('SentNr', '')).ljust(6)} "
|
380
|
+
f"{contact.get('Call', '').ljust(13)} "
|
381
|
+
f"{str(contact.get('RCV', '')).ljust(3)} "
|
382
|
+
f"{str(contact.get('NR', '')).ljust(6)}",
|
383
|
+
end="\r\n",
|
384
|
+
file=file_descriptor,
|
385
|
+
)
|
386
|
+
print("END-OF-LOG:", end="\r\n", file=file_descriptor)
|
387
|
+
except IOError as exception:
|
388
|
+
logger.critical("cabrillo: IO error: %s, writing to %s", exception, filename)
|
389
|
+
return
|
not1mm/plugins/cq_wpx_ssb.py
CHANGED
@@ -1,15 +1,21 @@
|
|
1
1
|
"""CQ WPX SSB plugin"""
|
2
2
|
|
3
3
|
# pylint: disable=invalid-name
|
4
|
+
import logging
|
5
|
+
from pathlib import Path
|
4
6
|
|
5
7
|
from PyQt5 import QtWidgets
|
6
8
|
|
9
|
+
from not1mm.lib.version import __version__
|
10
|
+
|
11
|
+
logger = logging.getLogger("__main__")
|
12
|
+
|
7
13
|
name = "CQ WPX SSB"
|
8
14
|
cabrillo_name = "CQ-WPX-SSB"
|
9
15
|
mode = "SSB" # CW SSB BOTH RTTY
|
10
16
|
|
11
17
|
# 1 once per contest, 2 work each band, 3 each band/mode, 4 no dupe checking
|
12
|
-
dupe_type =
|
18
|
+
dupe_type = 2
|
13
19
|
|
14
20
|
|
15
21
|
def init_contest(self):
|
@@ -162,17 +168,21 @@ def adif(self):
|
|
162
168
|
"""
|
163
169
|
Creates an ADIF file of the contacts made.
|
164
170
|
"""
|
165
|
-
|
171
|
+
filename = (
|
172
|
+
str(Path.home())
|
173
|
+
+ "/"
|
174
|
+
+ f"{self.pref.get('callsign').upper()}_{cabrillo_name}.adi"
|
175
|
+
)
|
166
176
|
log = self.database.fetch_all_contacts_asc()
|
167
177
|
try:
|
168
|
-
with open(
|
178
|
+
with open(filename, "w", encoding="utf-8") as file_descriptor:
|
169
179
|
print("<ADIF_VER:5>2.2.0", end="\r\n", file=file_descriptor)
|
170
180
|
print("<EOH>", end="\r\n", file=file_descriptor)
|
171
181
|
for contact in log:
|
172
182
|
|
173
183
|
hiscall = contact.get("Call", "")
|
174
184
|
the_date_and_time = contact.get("TS")
|
175
|
-
band = contact.get("Band")
|
185
|
+
# band = contact.get("Band")
|
176
186
|
themode = contact.get("Mode")
|
177
187
|
frequency = str(contact.get("Freq", 0) / 1000)
|
178
188
|
sentrst = contact.get("SNT", "")
|
@@ -253,3 +263,127 @@ def adif(self):
|
|
253
263
|
print("", end="\r\n", file=file_descriptor)
|
254
264
|
except IOError:
|
255
265
|
...
|
266
|
+
|
267
|
+
|
268
|
+
def cabrillo(self):
|
269
|
+
"""Generates Cabrillo file. Maybe."""
|
270
|
+
# https://www.cqwpx.com/cabrillo.htm
|
271
|
+
logger.debug("******Cabrillo*****")
|
272
|
+
filename = (
|
273
|
+
str(Path.home())
|
274
|
+
+ "/"
|
275
|
+
+ f"{self.pref.get('callsign').upper()}_{cabrillo_name}.log"
|
276
|
+
)
|
277
|
+
logger.debug("%s", filename)
|
278
|
+
log = self.database.fetch_all_contacts_asc()
|
279
|
+
try:
|
280
|
+
with open(filename, "w", encoding="ascii") as file_descriptor:
|
281
|
+
print("START-OF-LOG: 3.0", end="\r\n", file=file_descriptor)
|
282
|
+
print(
|
283
|
+
f"CREATED-BY: Not1MM v{__version__}",
|
284
|
+
end="\r\n",
|
285
|
+
file=file_descriptor,
|
286
|
+
)
|
287
|
+
print(
|
288
|
+
f"CONTEST: {cabrillo_name}",
|
289
|
+
end="\r\n",
|
290
|
+
file=file_descriptor,
|
291
|
+
)
|
292
|
+
print(
|
293
|
+
f"CALLSIGN: {self.pref.get('callsign','')}",
|
294
|
+
end="\r\n",
|
295
|
+
file=file_descriptor,
|
296
|
+
)
|
297
|
+
print(
|
298
|
+
f"LOCATION: {self.pref.get('section', '')}",
|
299
|
+
end="\r\n",
|
300
|
+
file=file_descriptor,
|
301
|
+
)
|
302
|
+
# print(
|
303
|
+
# f"ARRL-SECTION: {self.pref.get('section', '')}",
|
304
|
+
# end="\r\n",
|
305
|
+
# file=file_descriptor,
|
306
|
+
# )
|
307
|
+
# CATEGORY-OPERATOR: SINGLE-OP
|
308
|
+
# CATEGORY-ASSISTED: NON-ASSISTED
|
309
|
+
# CATEGORY-BAND: ALL
|
310
|
+
# CATEGORY-MODE: SSB
|
311
|
+
# CATEGORY-TRANSMITTER: ONE
|
312
|
+
# CATEGORY-OVERLAY: CLASSIC
|
313
|
+
# GRID-LOCATOR: DM13at
|
314
|
+
print(
|
315
|
+
f"CATEGORY: {None}",
|
316
|
+
end="\r\n",
|
317
|
+
file=file_descriptor,
|
318
|
+
)
|
319
|
+
print("CATEGORY-POWER: ", end="\r\n", file=file_descriptor)
|
320
|
+
|
321
|
+
print(
|
322
|
+
f"CLAIMED-SCORE: {calc_score(self)}",
|
323
|
+
end="\r\n",
|
324
|
+
file=file_descriptor,
|
325
|
+
)
|
326
|
+
print(
|
327
|
+
"OPERATORS: ",
|
328
|
+
end="\r\n",
|
329
|
+
file=file_descriptor,
|
330
|
+
)
|
331
|
+
print(
|
332
|
+
f"NAME: {self.pref.get('name', '')}",
|
333
|
+
end="\r\n",
|
334
|
+
file=file_descriptor,
|
335
|
+
)
|
336
|
+
print(
|
337
|
+
f"ADDRESS: {self.pref.get('address1', '')}",
|
338
|
+
end="\r\n",
|
339
|
+
file=file_descriptor,
|
340
|
+
)
|
341
|
+
print(
|
342
|
+
f"ADDRESS-CITY: {self.pref.get('city', '')}",
|
343
|
+
end="\r\n",
|
344
|
+
file=file_descriptor,
|
345
|
+
)
|
346
|
+
print(
|
347
|
+
f"ADDRESS-STATE-PROVINCE: {self.pref.get('state', '')}",
|
348
|
+
end="\r\n",
|
349
|
+
file=file_descriptor,
|
350
|
+
)
|
351
|
+
print(
|
352
|
+
f"ADDRESS-POSTALCODE: {self.pref.get('zip', '')}",
|
353
|
+
end="\r\n",
|
354
|
+
file=file_descriptor,
|
355
|
+
)
|
356
|
+
print(
|
357
|
+
f"ADDRESS-COUNTRY: {self.pref.get('country', '')}",
|
358
|
+
end="\r\n",
|
359
|
+
file=file_descriptor,
|
360
|
+
)
|
361
|
+
print(
|
362
|
+
f"EMAIL: {self.pref.get('email', '')}",
|
363
|
+
end="\r\n",
|
364
|
+
file=file_descriptor,
|
365
|
+
)
|
366
|
+
for contact in log:
|
367
|
+
the_date_and_time = contact.get("TS", "")
|
368
|
+
themode = contact.get("Mode", "")
|
369
|
+
if themode == "LSB" or themode == "USB":
|
370
|
+
themode = "PH"
|
371
|
+
frequency = str(int(contact.get("Freq", "0"))).rjust(5)
|
372
|
+
|
373
|
+
loggeddate = the_date_and_time[:10]
|
374
|
+
loggedtime = the_date_and_time[11:13] + the_date_and_time[14:16]
|
375
|
+
print(
|
376
|
+
f"QSO: {frequency} {themode} {loggeddate} {loggedtime} "
|
377
|
+
f"{contact.get('StationPrefix', '').ljust(13)} "
|
378
|
+
f"{str(contact.get('SNT', '')).ljust(3)} "
|
379
|
+
f"{str(contact.get('SentNr', '')).ljust(6)} "
|
380
|
+
f"{contact.get('Call', '').ljust(13)} "
|
381
|
+
f"{str(contact.get('RCV', '')).ljust(3)} "
|
382
|
+
f"{str(contact.get('NR', '')).ljust(6)}",
|
383
|
+
end="\r\n",
|
384
|
+
file=file_descriptor,
|
385
|
+
)
|
386
|
+
print("END-OF-LOG:", end="\r\n", file=file_descriptor)
|
387
|
+
except IOError as exception:
|
388
|
+
logger.critical("cabrillo: IO error: %s, writing to %s", exception, filename)
|
389
|
+
return
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: not1mm
|
3
|
-
Version: 23.3.
|
3
|
+
Version: 23.3.27
|
4
4
|
Summary: NOT1MM Logger
|
5
5
|
Author-email: Michael Bridak <michael.bridak@gmail.com>
|
6
6
|
Project-URL: Homepage, https://github.com/mbridak/not1mm
|
@@ -44,6 +44,7 @@ Requires-Dist: xmltodict
|
|
44
44
|
- [Log Display](#log-display)
|
45
45
|
- [Editing a contact](#editing-a-contact)
|
46
46
|
- [Cabrillo](#cabrillo)
|
47
|
+
- [ADIF](#adif)
|
47
48
|
- [Dupe checking](#dupe-checking)
|
48
49
|
- [CAT](#cat)
|
49
50
|
|
@@ -74,6 +75,7 @@ Feature complete.
|
|
74
75
|
|
75
76
|
## Changes of note
|
76
77
|
|
78
|
+
- [23-3-27] Fix cursor behaviour when editing text in callsign field.
|
77
79
|
- [23-3-25] Fix minimum call length. Fix cabrillo tag. Add adif output.
|
78
80
|
- [23-3-24] Added dupe checking. Added CAT check for flrig or rigctld. Added online flag for flrig.
|
79
81
|
- [23-3-23] Added most of Cabrillo generation. Plan to test it this weekends CQ WPX SSB.
|
@@ -197,6 +199,14 @@ So for me it would be:
|
|
197
199
|
|
198
200
|
K6GTE_CQ-WPX-SSB.log
|
199
201
|
|
202
|
+
## ADIF
|
203
|
+
|
204
|
+
`File` > `Generate ADIF`
|
205
|
+
|
206
|
+
Boom... ADIF
|
207
|
+
|
208
|
+
`StationCall`_`ContestName`.adi
|
209
|
+
|
200
210
|
## Dupe checking
|
201
211
|
|
202
212
|
Added dupe checking. Big Red 'Dupe' will appear if it's a dupe...
|
@@ -1,5 +1,5 @@
|
|
1
1
|
not1mm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
not1mm/__main__.py,sha256=
|
2
|
+
not1mm/__main__.py,sha256=oVY2SStvSXwOb_kWCmKSUquEQ6etJluzKz4EpERvoJo,50566
|
3
3
|
not1mm/logwindow.py,sha256=yjBaHKlAUA3nDeZdBIT6-IGsHi-PZGuV1Kgolxunurk,24930
|
4
4
|
not1mm/test.py,sha256=sCAd6OZQlakGm2gMbjhwZ17UyI-Y5L2CCqsYymx7IPQ,3906
|
5
5
|
not1mm/data/Combinear.qss,sha256=SKqM0g8GvNXay1ovgtwCw3Egt0eLfN5P3iTREInC1eE,16590
|
@@ -25,7 +25,7 @@ not1mm/data/use_qrz_dialog.ui,sha256=sXV1K1tsmYEF7K8nnV_t_UR3k1PzQp43CgvX4KSnR94
|
|
25
25
|
not1mm/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
26
26
|
not1mm/lib/cat_interface.py,sha256=5EhVLWfMOvg-zLkLTGtNLJj2VohxG48uaMCelEdL1wg,10342
|
27
27
|
not1mm/lib/cwinterface.py,sha256=77I7RFtrIljuuWna3mjkjxaPSM1kGaPV4duPkoiT8wA,1772
|
28
|
-
not1mm/lib/database.py,sha256=
|
28
|
+
not1mm/lib/database.py,sha256=SCr97eurpJfongb_mA_-UCNxkNiqCJsPSdTxsSK12Hs,17127
|
29
29
|
not1mm/lib/edit_contact.py,sha256=YwuX-BuIa7AuPtLRENs4jTzxOrtk6MCxZj3BR_bDPW8,357
|
30
30
|
not1mm/lib/edit_macro.py,sha256=lyToZb1nmcONNFh6W35NzYHLU48gbAs2_OsnuRQGHck,559
|
31
31
|
not1mm/lib/edit_opon.py,sha256=GqAOJMiC265_4YRVbkT1PflBuCa4HiCNfRhq8-J6ZVY,363
|
@@ -35,7 +35,7 @@ not1mm/lib/lookup.py,sha256=4OiWZWc3smcB0lqLk4WTs1U3i2k8yZFsX_1OoCGlaWc,13916
|
|
35
35
|
not1mm/lib/multicast.py,sha256=4-vesMxt5n_pDk2oYnL7R_exxLl9C197t569AM2lrD4,1954
|
36
36
|
not1mm/lib/n1mm.py,sha256=bK5d21Yfn6xRpQcu2RdpL2zR8lOlRWOadD6Ai4_lFdc,4434
|
37
37
|
not1mm/lib/qrz_dialog.py,sha256=fLFBkvQ9cuIqKk0-1yl5OFuQ40n904fNi_Vt23je99E,350
|
38
|
-
not1mm/lib/version.py,sha256=
|
38
|
+
not1mm/lib/version.py,sha256=H3AM53QOlozSvTFVbi7jIqx9rOS1-MEL3_qaM4R7rKU,47
|
39
39
|
not1mm/plugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
40
40
|
not1mm/plugins/arrl_dx_cw.py,sha256=VRP-H65SgEaCff6efF85DzU5KMoECkLQad4DraNgUec,1382
|
41
41
|
not1mm/plugins/arrl_dx_phone.py,sha256=9uLZWogzTfLm0SjmcG149dTG_GjDbbVhdInl4Uz7Fck,1385
|
@@ -43,14 +43,15 @@ not1mm/plugins/arrl_field_day.py,sha256=GJhdpkX9pfm8imfIhKKSQh36PRpK4DrqDH3kcN5Z
|
|
43
43
|
not1mm/plugins/arrl_rtty_ru.py,sha256=_cOuXmGTpQ2xbDOEzFVKuitmVlB_F2P5vP3x3fcsDa8,1390
|
44
44
|
not1mm/plugins/arrl_ss_cw.py,sha256=Y0sYwcbzZGcR4843QkMCzZ8RBjXPtJFEa87TWyAGCBA,1391
|
45
45
|
not1mm/plugins/arrl_ss_phone.py,sha256=4AY_S5wx-L0dC5pFLCDTX0FNdxTDFeg_YpaX-7z8nrY,1394
|
46
|
-
not1mm/plugins/
|
46
|
+
not1mm/plugins/cq_wpx_cw.py,sha256=rEWFFBfhudT8X3GP1Vn4L8Q6vKrX9jsh5_NkVkTY6SI,12822
|
47
|
+
not1mm/plugins/cq_wpx_ssb.py,sha256=3WHd_aUyG1yZLAF3IWEAvR92a0QlP_ss7rgLoqagv6s,12826
|
47
48
|
not1mm/plugins/cqww_dx_cw.py,sha256=eKBIQ8WdJXlGtSTDds7BuoFPpn3odEoiiu_RIQQLHb8,2086
|
48
49
|
not1mm/plugins/cqww_dx_ssb.py,sha256=7lPh-VH8nb-qQ-9wYx5pd6Es_qSbiL3ETHpibqhH_r0,2090
|
49
50
|
not1mm/plugins/general_logging.py,sha256=UwHO3g84bghuIaa1JyqMeMFVfmMRvLgV3NQY3zZWW-w,2077
|
50
51
|
not1mm/plugins/winter_field_day.py,sha256=L7co3YEoKt-jaAFJfGw_Y3-uK-G6eQNsOQSCEkT5U24,1631
|
51
|
-
not1mm-23.3.
|
52
|
-
not1mm-23.3.
|
53
|
-
not1mm-23.3.
|
54
|
-
not1mm-23.3.
|
55
|
-
not1mm-23.3.
|
56
|
-
not1mm-23.3.
|
52
|
+
not1mm-23.3.27.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
53
|
+
not1mm-23.3.27.dist-info/METADATA,sha256=auF7-fSveo2JxXCHcWeEsT6KntUfF1ZAs48GQ67-mxE,9100
|
54
|
+
not1mm-23.3.27.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
|
55
|
+
not1mm-23.3.27.dist-info/entry_points.txt,sha256=pMcZk_0dxFgLkcUkF0Q874ojpwOmF3OL6EKw9LgvocM,47
|
56
|
+
not1mm-23.3.27.dist-info/top_level.txt,sha256=0YmTxEcDzQlzXub-lXASvoLpg_mt1c2thb5cVkDf5J4,7
|
57
|
+
not1mm-23.3.27.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|