not1mm 25.4.7__py3-none-any.whl → 25.4.9__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 +11 -4
- not1mm/data/new_contest.ui +5 -0
- not1mm/lib/version.py +2 -1
- not1mm/plugins/ukeidx.py +597 -0
- not1mm/statistics.py +2 -1
- {not1mm-25.4.7.dist-info → not1mm-25.4.9.dist-info}/METADATA +10 -1
- {not1mm-25.4.7.dist-info → not1mm-25.4.9.dist-info}/RECORD +11 -10
- {not1mm-25.4.7.dist-info → not1mm-25.4.9.dist-info}/WHEEL +0 -0
- {not1mm-25.4.7.dist-info → not1mm-25.4.9.dist-info}/entry_points.txt +0 -0
- {not1mm-25.4.7.dist-info → not1mm-25.4.9.dist-info}/licenses/LICENSE +0 -0
- {not1mm-25.4.7.dist-info → not1mm-25.4.9.dist-info}/top_level.txt +0 -0
not1mm/__main__.py
CHANGED
@@ -795,12 +795,20 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
795
795
|
try:
|
796
796
|
with open(filename, "rt", encoding="utf-8") as file_descriptor:
|
797
797
|
lines = file_descriptor.readlines()
|
798
|
-
|
799
|
-
|
798
|
+
substring_to_find = "!!Order!!"
|
799
|
+
found_index = -1 # Initialize to -1 to indicate not found
|
800
|
+
|
801
|
+
for index, item in enumerate(lines):
|
802
|
+
if substring_to_find in item:
|
803
|
+
found_index = index
|
804
|
+
break # Exit the loop once found
|
805
|
+
|
806
|
+
if found_index != -1:
|
807
|
+
item_names = lines[found_index].strip().split(",")
|
800
808
|
# ['!!Order!!', 'Call', 'Sect', 'State', 'CK', 'UserText', '']
|
801
809
|
item_names = item_names[1:]
|
802
810
|
# ['Call', 'Sect', 'State', 'CK', 'UserText', '']
|
803
|
-
lines = lines[1:]
|
811
|
+
lines = lines[found_index + 1 :]
|
804
812
|
group_list = []
|
805
813
|
for line in lines:
|
806
814
|
if line.startswith("#"):
|
@@ -1026,7 +1034,6 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
1026
1034
|
if self.bandmap_window:
|
1027
1035
|
self.bandmap_window.msg_from_main(cmd)
|
1028
1036
|
|
1029
|
-
|
1030
1037
|
if setdarkmode:
|
1031
1038
|
darkPalette = QPalette()
|
1032
1039
|
darkColor = QColor(56, 56, 56)
|
not1mm/data/new_contest.ui
CHANGED
not1mm/lib/version.py
CHANGED
not1mm/plugins/ukeidx.py
ADDED
@@ -0,0 +1,597 @@
|
|
1
|
+
"""10 10 fall cw plugin"""
|
2
|
+
|
3
|
+
# pylint: disable=invalid-name, unused-argument, unused-variable, c-extension-no-member, unused-import
|
4
|
+
|
5
|
+
import datetime
|
6
|
+
import logging
|
7
|
+
from pathlib import Path
|
8
|
+
|
9
|
+
from PyQt6 import QtWidgets
|
10
|
+
|
11
|
+
from not1mm.lib.plugin_common import gen_adif, get_points, online_score_xml
|
12
|
+
from not1mm.lib.version import __version__
|
13
|
+
|
14
|
+
logger = logging.getLogger(__name__)
|
15
|
+
|
16
|
+
EXCHANGE_HINT = "# or # And Dist"
|
17
|
+
|
18
|
+
ukei_pfx = [
|
19
|
+
"G",
|
20
|
+
"GD",
|
21
|
+
"GJ",
|
22
|
+
"GM",
|
23
|
+
"GI",
|
24
|
+
"GW",
|
25
|
+
"GU",
|
26
|
+
"EI",
|
27
|
+
]
|
28
|
+
|
29
|
+
name = "UKEI-DX"
|
30
|
+
cabrillo_name = "UKEI-DX"
|
31
|
+
mode = "BOTH" # CW SSB BOTH RTTY
|
32
|
+
# columns = [0, 1, 2, 3, 4, 5, 6, 15]
|
33
|
+
columns = [
|
34
|
+
"YYYY-MM-DD HH:MM:SS",
|
35
|
+
"Call",
|
36
|
+
"Freq",
|
37
|
+
"Snt",
|
38
|
+
"Rcv",
|
39
|
+
"SentNr",
|
40
|
+
"RcvNr",
|
41
|
+
"PTS",
|
42
|
+
]
|
43
|
+
|
44
|
+
# 1 once per contest, 2 work each band, 3 each band/mode, 4 no dupe checking
|
45
|
+
dupe_type = 2
|
46
|
+
|
47
|
+
|
48
|
+
def init_contest(self):
|
49
|
+
"""setup plugin"""
|
50
|
+
set_tab_next(self)
|
51
|
+
set_tab_prev(self)
|
52
|
+
interface(self)
|
53
|
+
self.next_field = self.other_2
|
54
|
+
|
55
|
+
|
56
|
+
def interface(self):
|
57
|
+
"""Setup user interface"""
|
58
|
+
self.field1.show()
|
59
|
+
self.field2.show()
|
60
|
+
self.field3.show()
|
61
|
+
self.field4.show()
|
62
|
+
self.snt_label.setText("SNT")
|
63
|
+
self.field1.setAccessibleName("RST Sent")
|
64
|
+
self.other_label.setText("Sent Nr")
|
65
|
+
self.field2.setAccessibleName("Sent Number")
|
66
|
+
self.exch_label.setText("# and Dist")
|
67
|
+
self.field4.setAccessibleName("Number and District")
|
68
|
+
|
69
|
+
|
70
|
+
def reset_label(self):
|
71
|
+
"""reset label after field cleared"""
|
72
|
+
|
73
|
+
|
74
|
+
def set_tab_next(self):
|
75
|
+
"""Set TAB Advances"""
|
76
|
+
self.tab_next = {
|
77
|
+
self.callsign: self.sent,
|
78
|
+
self.sent: self.receive,
|
79
|
+
self.receive: self.other_1,
|
80
|
+
self.other_1: self.other_2,
|
81
|
+
self.other_2: self.callsign,
|
82
|
+
}
|
83
|
+
|
84
|
+
|
85
|
+
def set_tab_prev(self):
|
86
|
+
"""Set TAB Advances"""
|
87
|
+
self.tab_prev = {
|
88
|
+
self.callsign: self.other_2,
|
89
|
+
self.sent: self.callsign,
|
90
|
+
self.receive: self.sent,
|
91
|
+
self.other_1: self.receive,
|
92
|
+
self.other_2: self.other_1,
|
93
|
+
}
|
94
|
+
|
95
|
+
|
96
|
+
def validate(self):
|
97
|
+
"""doc"""
|
98
|
+
return True
|
99
|
+
|
100
|
+
|
101
|
+
def set_contact_vars(self):
|
102
|
+
"""Contest Specific"""
|
103
|
+
self.contact["SNT"] = self.sent.text()
|
104
|
+
self.contact["RCV"] = self.receive.text()
|
105
|
+
self.contact["NR"] = self.other_2.text().upper()
|
106
|
+
self.contact["SentNr"] = self.other_1.text()
|
107
|
+
|
108
|
+
|
109
|
+
def predupe(self):
|
110
|
+
"""called after callsign entered"""
|
111
|
+
|
112
|
+
|
113
|
+
def prefill(self):
|
114
|
+
"""Fill sentnr"""
|
115
|
+
exch = str(self.contest_settings.get("SentExchange", 0))
|
116
|
+
result = self.database.get_serial()
|
117
|
+
serial_nr = str(result.get("serial_nr", "1")).zfill(3)
|
118
|
+
if serial_nr == "None":
|
119
|
+
serial_nr = "001"
|
120
|
+
if len(self.other_1.text()) == 0:
|
121
|
+
self.other_1.setText(exch.replace("#", serial_nr))
|
122
|
+
|
123
|
+
|
124
|
+
def points(self):
|
125
|
+
"""Calc point"""
|
126
|
+
|
127
|
+
# UK/EI stations contacting :
|
128
|
+
# UK/EI/Europe 80m, 40m - 4 points 20m, 15m, 10m - 2 points
|
129
|
+
# DX (Outside Europe) 80m, 40m - 8 points 20m, 15m, 10m - 4 points
|
130
|
+
|
131
|
+
# Note : For UK/EI stations only, all QSOs will score double points between the hours of 0100z and 0459z.
|
132
|
+
|
133
|
+
# European stations contacting :
|
134
|
+
# UK/EI 80m, 40m - 4 points 20m, 15m, 10m - 2 points
|
135
|
+
# Europe 80m, 40m - 2 points 20m, 15m, 10m - 1 points
|
136
|
+
# DX (Outside Europe) 80m, 40m - 4 points 20m, 15m, 10m - 2 points
|
137
|
+
|
138
|
+
# DX (Outside Europe) contacting :
|
139
|
+
# UK/EI 80m, 40m - 8 points 20m, 15m, 10m - 4 points
|
140
|
+
# Europe 80m, 40m - 4 points 20m, 15m, 10m - 2 points
|
141
|
+
# DX (Outside Europe) 80m, 40m - 2 points 20m, 15m, 10m - 1 points
|
142
|
+
|
143
|
+
# f"{primary_pfx}: {continent}/{entity} cq:{cq} itu:{itu}"
|
144
|
+
|
145
|
+
if self.contact_is_dupe > 0:
|
146
|
+
return 0
|
147
|
+
|
148
|
+
myprimary_pfx = ""
|
149
|
+
# mycountry = ""
|
150
|
+
mycontinent = ""
|
151
|
+
hisprimary_pfx = ""
|
152
|
+
# hiscountry = ""
|
153
|
+
hiscontinent = ""
|
154
|
+
|
155
|
+
result = self.cty_lookup(self.station.get("Call", ""))
|
156
|
+
if result:
|
157
|
+
for item in result.items():
|
158
|
+
myprimary_pfx = item[1].get("primary_pfx", "")
|
159
|
+
# mycountry = item[1].get("entity", "")
|
160
|
+
mycontinent = item[1].get("continent", "")
|
161
|
+
|
162
|
+
result = self.cty_lookup(self.contact.get("Call", ""))
|
163
|
+
if result:
|
164
|
+
for item in result.items():
|
165
|
+
hisprimary_pfx = item[1].get("primary_pfx", "")
|
166
|
+
# hiscountry = item[1].get("entity", "")
|
167
|
+
hiscontinent = item[1].get("continent", "")
|
168
|
+
|
169
|
+
st = 100
|
170
|
+
et = 459
|
171
|
+
zt = datetime.datetime.now(datetime.timezone.utc).isoformat(" ")[11:16]
|
172
|
+
ct = int(zt[0:2]) * 100 + int(zt[3:5])
|
173
|
+
double_window = st <= ct <= et
|
174
|
+
|
175
|
+
# UK/EI stations:
|
176
|
+
if myprimary_pfx in ukei_pfx:
|
177
|
+
if hiscontinent == "EU":
|
178
|
+
if self.contact.get("Band", 0) in ["3.5", "7"]:
|
179
|
+
return 4 + (4 * double_window)
|
180
|
+
return 2 + (2 * double_window)
|
181
|
+
if self.contact.get("Band", 0) in ["3.5", "7"]:
|
182
|
+
return 8 + (8 * double_window)
|
183
|
+
return 4 + (4 * double_window)
|
184
|
+
|
185
|
+
# European stations:
|
186
|
+
if mycontinent == "EU":
|
187
|
+
if hisprimary_pfx in ukei_pfx:
|
188
|
+
if self.contact.get("Band", 0) in ["3.5", "7"]:
|
189
|
+
return 4
|
190
|
+
return 2
|
191
|
+
elif hiscontinent == "EU":
|
192
|
+
if self.contact.get("Band", 0) in ["3.5", "7"]:
|
193
|
+
return 2
|
194
|
+
return 1
|
195
|
+
if self.contact.get("Band", 0) in ["3.5", "7"]:
|
196
|
+
return 4
|
197
|
+
return 2
|
198
|
+
|
199
|
+
# DX (Outside Europe)
|
200
|
+
if mycontinent != "EU":
|
201
|
+
if hisprimary_pfx in ukei_pfx:
|
202
|
+
if self.contact.get("Band", "") in ["3.5", "7"]:
|
203
|
+
return 8
|
204
|
+
return 4
|
205
|
+
elif hiscontinent == "EU":
|
206
|
+
if self.contact.get("Band", "") in ["3.5", "7"]:
|
207
|
+
return 4
|
208
|
+
return 2
|
209
|
+
if self.contact.get("Band", "") in ["3.5", "7"]:
|
210
|
+
return 2
|
211
|
+
return 1
|
212
|
+
|
213
|
+
return 0
|
214
|
+
|
215
|
+
|
216
|
+
def show_mults(self):
|
217
|
+
"""Return display string for mults"""
|
218
|
+
|
219
|
+
query = f"SELECT COUNT(DISTINCT CountryPrefix) as dxcc_count FROM DXLOG WHERE CountryPrefix NOT IN ('EI', 'G', 'GD', 'GI', 'GJ', 'GM', 'GU', 'GW') and ContestNR = {self.pref.get('contest', '1')};"
|
220
|
+
result = self.database.exec_sql(query)
|
221
|
+
dxcc_count = result.get("dxcc_count", 0)
|
222
|
+
|
223
|
+
query = f"SELECT COUNT(DISTINCT SUBSTR(NR, LENGTH(NR) - 1)) as code_count FROM DXLOG WHERE ContestNR = {self.pref.get('contest', '1')} and typeof(NR) = 'text';"
|
224
|
+
result = self.database.exec_sql(query)
|
225
|
+
code_count = result.get("code_count", 0)
|
226
|
+
|
227
|
+
return dxcc_count + code_count
|
228
|
+
|
229
|
+
|
230
|
+
def show_qso(self):
|
231
|
+
"""Return qso count"""
|
232
|
+
result = self.database.fetch_qso_count()
|
233
|
+
if result:
|
234
|
+
return int(result.get("qsos", 0))
|
235
|
+
return 0
|
236
|
+
|
237
|
+
|
238
|
+
def calc_score(self):
|
239
|
+
"""Return calculated score"""
|
240
|
+
result = self.database.fetch_points()
|
241
|
+
if result is not None:
|
242
|
+
score = result.get("Points", "0")
|
243
|
+
if score is None:
|
244
|
+
score = "0"
|
245
|
+
contest_points = int(score)
|
246
|
+
mults = show_mults(self)
|
247
|
+
return contest_points * mults
|
248
|
+
return 0
|
249
|
+
|
250
|
+
|
251
|
+
def adif(self):
|
252
|
+
"""Call the generate ADIF function"""
|
253
|
+
gen_adif(self, cabrillo_name)
|
254
|
+
|
255
|
+
|
256
|
+
def output_cabrillo_line(line_to_output, ending, file_descriptor, file_encoding):
|
257
|
+
""""""
|
258
|
+
print(
|
259
|
+
line_to_output.encode(file_encoding, errors="ignore").decode(),
|
260
|
+
end=ending,
|
261
|
+
file=file_descriptor,
|
262
|
+
)
|
263
|
+
|
264
|
+
|
265
|
+
def cabrillo(self, file_encoding):
|
266
|
+
"""Generates Cabrillo file. Maybe."""
|
267
|
+
# https://www.cqwpx.com/cabrillo.htm
|
268
|
+
logger.debug("******Cabrillo*****")
|
269
|
+
logger.debug("Station: %s", f"{self.station}")
|
270
|
+
logger.debug("Contest: %s", f"{self.contest_settings}")
|
271
|
+
now = datetime.datetime.now()
|
272
|
+
date_time = now.strftime("%Y-%m-%d_%H-%M-%S")
|
273
|
+
filename = (
|
274
|
+
str(Path.home())
|
275
|
+
+ "/"
|
276
|
+
+ f"{self.station.get('Call', '').upper()}_{cabrillo_name}_{date_time}.log"
|
277
|
+
)
|
278
|
+
logger.debug("%s", filename)
|
279
|
+
log = self.database.fetch_all_contacts_asc()
|
280
|
+
try:
|
281
|
+
with open(filename, "w", encoding=file_encoding, newline="") as file_descriptor:
|
282
|
+
output_cabrillo_line(
|
283
|
+
"START-OF-LOG: 3.0",
|
284
|
+
"\r\n",
|
285
|
+
file_descriptor,
|
286
|
+
file_encoding,
|
287
|
+
)
|
288
|
+
output_cabrillo_line(
|
289
|
+
f"CREATED-BY: Not1MM v{__version__}",
|
290
|
+
"\r\n",
|
291
|
+
file_descriptor,
|
292
|
+
file_encoding,
|
293
|
+
)
|
294
|
+
output_cabrillo_line(
|
295
|
+
f"CONTEST: {cabrillo_name}",
|
296
|
+
"\r\n",
|
297
|
+
file_descriptor,
|
298
|
+
file_encoding,
|
299
|
+
)
|
300
|
+
if self.station.get("Club", ""):
|
301
|
+
output_cabrillo_line(
|
302
|
+
f"CLUB: {self.station.get('Club', '').upper()}",
|
303
|
+
"\r\n",
|
304
|
+
file_descriptor,
|
305
|
+
file_encoding,
|
306
|
+
)
|
307
|
+
output_cabrillo_line(
|
308
|
+
f"CALLSIGN: {self.station.get('Call','')}",
|
309
|
+
"\r\n",
|
310
|
+
file_descriptor,
|
311
|
+
file_encoding,
|
312
|
+
)
|
313
|
+
output_cabrillo_line(
|
314
|
+
f"LOCATION: {self.station.get('ARRLSection', '')}",
|
315
|
+
"\r\n",
|
316
|
+
file_descriptor,
|
317
|
+
file_encoding,
|
318
|
+
)
|
319
|
+
output_cabrillo_line(
|
320
|
+
f"CATEGORY-OPERATOR: {self.contest_settings.get('OperatorCategory','')}",
|
321
|
+
"\r\n",
|
322
|
+
file_descriptor,
|
323
|
+
file_encoding,
|
324
|
+
)
|
325
|
+
output_cabrillo_line(
|
326
|
+
f"CATEGORY-ASSISTED: {self.contest_settings.get('AssistedCategory','')}",
|
327
|
+
"\r\n",
|
328
|
+
file_descriptor,
|
329
|
+
file_encoding,
|
330
|
+
)
|
331
|
+
output_cabrillo_line(
|
332
|
+
f"CATEGORY-BAND: {self.contest_settings.get('BandCategory','')}",
|
333
|
+
"\r\n",
|
334
|
+
file_descriptor,
|
335
|
+
file_encoding,
|
336
|
+
)
|
337
|
+
mode = self.contest_settings.get("ModeCategory", "")
|
338
|
+
if mode in ["SSB+CW", "SSB+CW+DIGITAL"]:
|
339
|
+
mode = "MIXED"
|
340
|
+
output_cabrillo_line(
|
341
|
+
f"CATEGORY-MODE: {mode}",
|
342
|
+
"\r\n",
|
343
|
+
file_descriptor,
|
344
|
+
file_encoding,
|
345
|
+
)
|
346
|
+
output_cabrillo_line(
|
347
|
+
f"CATEGORY-TRANSMITTER: {self.contest_settings.get('TransmitterCategory','')}",
|
348
|
+
"\r\n",
|
349
|
+
file_descriptor,
|
350
|
+
file_encoding,
|
351
|
+
)
|
352
|
+
if self.contest_settings.get("OverlayCategory", "") != "N/A":
|
353
|
+
output_cabrillo_line(
|
354
|
+
f"CATEGORY-OVERLAY: {self.contest_settings.get('OverlayCategory','')}",
|
355
|
+
"\r\n",
|
356
|
+
file_descriptor,
|
357
|
+
file_encoding,
|
358
|
+
)
|
359
|
+
output_cabrillo_line(
|
360
|
+
f"GRID-LOCATOR: {self.station.get('GridSquare','')}",
|
361
|
+
"\r\n",
|
362
|
+
file_descriptor,
|
363
|
+
file_encoding,
|
364
|
+
)
|
365
|
+
output_cabrillo_line(
|
366
|
+
f"CATEGORY-POWER: {self.contest_settings.get('PowerCategory','')}",
|
367
|
+
"\r\n",
|
368
|
+
file_descriptor,
|
369
|
+
file_encoding,
|
370
|
+
)
|
371
|
+
|
372
|
+
output_cabrillo_line(
|
373
|
+
f"CLAIMED-SCORE: {calc_score(self)}",
|
374
|
+
"\r\n",
|
375
|
+
file_descriptor,
|
376
|
+
file_encoding,
|
377
|
+
)
|
378
|
+
ops = f"@{self.station.get('Call','')}"
|
379
|
+
list_of_ops = self.database.get_ops()
|
380
|
+
for op in list_of_ops:
|
381
|
+
ops += f", {op.get('Operator', '')}"
|
382
|
+
output_cabrillo_line(
|
383
|
+
f"OPERATORS: {ops}",
|
384
|
+
"\r\n",
|
385
|
+
file_descriptor,
|
386
|
+
file_encoding,
|
387
|
+
)
|
388
|
+
output_cabrillo_line(
|
389
|
+
f"NAME: {self.station.get('Name', '')}",
|
390
|
+
"\r\n",
|
391
|
+
file_descriptor,
|
392
|
+
file_encoding,
|
393
|
+
)
|
394
|
+
output_cabrillo_line(
|
395
|
+
f"ADDRESS: {self.station.get('Street1', '')}",
|
396
|
+
"\r\n",
|
397
|
+
file_descriptor,
|
398
|
+
file_encoding,
|
399
|
+
)
|
400
|
+
output_cabrillo_line(
|
401
|
+
f"ADDRESS-CITY: {self.station.get('City', '')}",
|
402
|
+
"\r\n",
|
403
|
+
file_descriptor,
|
404
|
+
file_encoding,
|
405
|
+
)
|
406
|
+
output_cabrillo_line(
|
407
|
+
f"ADDRESS-STATE-PROVINCE: {self.station.get('State', '')}",
|
408
|
+
"\r\n",
|
409
|
+
file_descriptor,
|
410
|
+
file_encoding,
|
411
|
+
)
|
412
|
+
output_cabrillo_line(
|
413
|
+
f"ADDRESS-POSTALCODE: {self.station.get('Zip', '')}",
|
414
|
+
"\r\n",
|
415
|
+
file_descriptor,
|
416
|
+
file_encoding,
|
417
|
+
)
|
418
|
+
output_cabrillo_line(
|
419
|
+
f"ADDRESS-COUNTRY: {self.station.get('Country', '')}",
|
420
|
+
"\r\n",
|
421
|
+
file_descriptor,
|
422
|
+
file_encoding,
|
423
|
+
)
|
424
|
+
output_cabrillo_line(
|
425
|
+
f"EMAIL: {self.station.get('Email', '')}",
|
426
|
+
"\r\n",
|
427
|
+
file_descriptor,
|
428
|
+
file_encoding,
|
429
|
+
)
|
430
|
+
for contact in log:
|
431
|
+
the_date_and_time = contact.get("TS", "")
|
432
|
+
themode = contact.get("Mode", "")
|
433
|
+
if themode == "LSB" or themode == "USB":
|
434
|
+
themode = "PH"
|
435
|
+
frequency = str(int(contact.get("Freq", "0"))).rjust(5)
|
436
|
+
|
437
|
+
loggeddate = the_date_and_time[:10]
|
438
|
+
loggedtime = the_date_and_time[11:13] + the_date_and_time[14:16]
|
439
|
+
sentnr = str(contact.get("SentNr", "")).upper().split()
|
440
|
+
if len(sentnr) == 2:
|
441
|
+
sentnr = sentnr[0].zfill(3) + " " + sentnr[1]
|
442
|
+
else:
|
443
|
+
sentnr = sentnr[0].zfill(3) + " --"
|
444
|
+
|
445
|
+
nr = str(contact.get("NR", "")).upper().split()
|
446
|
+
if len(nr) == 2:
|
447
|
+
nr = nr[0].zfill(3) + " " + nr[1]
|
448
|
+
else:
|
449
|
+
if nr[0][-2:].isalpha():
|
450
|
+
nr = nr[0][:-2].zfill(3) + " " + nr[0][-2:]
|
451
|
+
else:
|
452
|
+
nr = nr[0].zfill(3) + " --"
|
453
|
+
|
454
|
+
output_cabrillo_line(
|
455
|
+
f"QSO: {frequency} {themode} {loggeddate} {loggedtime} "
|
456
|
+
f"{contact.get('StationPrefix', '').ljust(13)} "
|
457
|
+
f"{str(contact.get('SNT', '')).ljust(3)} "
|
458
|
+
f"{sentnr} "
|
459
|
+
f"{contact.get('Call', '').ljust(13)} "
|
460
|
+
f"{str(contact.get('RCV', '')).ljust(3)} "
|
461
|
+
f"{nr}",
|
462
|
+
"\r\n",
|
463
|
+
file_descriptor,
|
464
|
+
file_encoding,
|
465
|
+
)
|
466
|
+
output_cabrillo_line("END-OF-LOG:", "\r\n", file_descriptor, file_encoding)
|
467
|
+
self.show_message_box(f"Cabrillo saved to: {filename}")
|
468
|
+
except IOError as exception:
|
469
|
+
logger.critical("cabrillo: IO error: %s, writing to %s", exception, filename)
|
470
|
+
self.show_message_box(f"Error saving Cabrillo: {exception} {filename}")
|
471
|
+
return
|
472
|
+
|
473
|
+
|
474
|
+
def recalculate_mults(self):
|
475
|
+
"""Recalculates multipliers after change in logged qso."""
|
476
|
+
|
477
|
+
|
478
|
+
def process_esm(self, new_focused_widget=None, with_enter=False):
|
479
|
+
"""ESM State Machine"""
|
480
|
+
|
481
|
+
# self.pref["run_state"]
|
482
|
+
|
483
|
+
# -----===== Assigned F-Keys =====-----
|
484
|
+
# self.esm_dict["CQ"]
|
485
|
+
# self.esm_dict["EXCH"]
|
486
|
+
# self.esm_dict["QRZ"]
|
487
|
+
# self.esm_dict["AGN"]
|
488
|
+
# self.esm_dict["HISCALL"]
|
489
|
+
# self.esm_dict["MYCALL"]
|
490
|
+
# self.esm_dict["QSOB4"]
|
491
|
+
|
492
|
+
# ----==== text fields ====----
|
493
|
+
# self.callsign
|
494
|
+
# self.sent
|
495
|
+
# self.receive
|
496
|
+
# self.other_1
|
497
|
+
# self.other_2
|
498
|
+
|
499
|
+
if new_focused_widget is not None:
|
500
|
+
self.current_widget = self.inputs_dict.get(new_focused_widget)
|
501
|
+
|
502
|
+
# print(f"checking esm {self.current_widget=} {with_enter=} {self.pref.get("run_state")=}")
|
503
|
+
|
504
|
+
for a_button in [
|
505
|
+
self.esm_dict["CQ"],
|
506
|
+
self.esm_dict["EXCH"],
|
507
|
+
self.esm_dict["QRZ"],
|
508
|
+
self.esm_dict["AGN"],
|
509
|
+
self.esm_dict["HISCALL"],
|
510
|
+
self.esm_dict["MYCALL"],
|
511
|
+
self.esm_dict["QSOB4"],
|
512
|
+
]:
|
513
|
+
if a_button is not None:
|
514
|
+
self.restore_button_color(a_button)
|
515
|
+
|
516
|
+
buttons_to_send = []
|
517
|
+
|
518
|
+
if self.pref.get("run_state"):
|
519
|
+
if self.current_widget == "callsign":
|
520
|
+
if len(self.callsign.text()) < 3:
|
521
|
+
self.make_button_green(self.esm_dict["CQ"])
|
522
|
+
buttons_to_send.append(self.esm_dict["CQ"])
|
523
|
+
elif len(self.callsign.text()) > 2:
|
524
|
+
self.make_button_green(self.esm_dict["HISCALL"])
|
525
|
+
self.make_button_green(self.esm_dict["EXCH"])
|
526
|
+
buttons_to_send.append(self.esm_dict["HISCALL"])
|
527
|
+
buttons_to_send.append(self.esm_dict["EXCH"])
|
528
|
+
|
529
|
+
elif self.current_widget in ["other_2"]:
|
530
|
+
if self.other_2.text() == "":
|
531
|
+
self.make_button_green(self.esm_dict["AGN"])
|
532
|
+
buttons_to_send.append(self.esm_dict["AGN"])
|
533
|
+
else:
|
534
|
+
self.make_button_green(self.esm_dict["QRZ"])
|
535
|
+
buttons_to_send.append(self.esm_dict["QRZ"])
|
536
|
+
buttons_to_send.append("LOGIT")
|
537
|
+
|
538
|
+
if with_enter is True and bool(len(buttons_to_send)):
|
539
|
+
for button in buttons_to_send:
|
540
|
+
if button:
|
541
|
+
if button == "LOGIT":
|
542
|
+
self.save_contact()
|
543
|
+
continue
|
544
|
+
self.process_function_key(button)
|
545
|
+
else:
|
546
|
+
if self.current_widget == "callsign":
|
547
|
+
if len(self.callsign.text()) > 2:
|
548
|
+
self.make_button_green(self.esm_dict["MYCALL"])
|
549
|
+
buttons_to_send.append(self.esm_dict["MYCALL"])
|
550
|
+
|
551
|
+
elif self.current_widget in ["other_2"]:
|
552
|
+
if self.other_2.text() == "":
|
553
|
+
self.make_button_green(self.esm_dict["AGN"])
|
554
|
+
buttons_to_send.append(self.esm_dict["AGN"])
|
555
|
+
else:
|
556
|
+
self.make_button_green(self.esm_dict["EXCH"])
|
557
|
+
buttons_to_send.append(self.esm_dict["EXCH"])
|
558
|
+
buttons_to_send.append("LOGIT")
|
559
|
+
|
560
|
+
if with_enter is True and bool(len(buttons_to_send)):
|
561
|
+
for button in buttons_to_send:
|
562
|
+
if button:
|
563
|
+
if button == "LOGIT":
|
564
|
+
self.save_contact()
|
565
|
+
continue
|
566
|
+
self.process_function_key(button)
|
567
|
+
|
568
|
+
|
569
|
+
def get_mults(self):
|
570
|
+
""""""
|
571
|
+
|
572
|
+
mults = {}
|
573
|
+
return mults
|
574
|
+
|
575
|
+
|
576
|
+
def just_points(self):
|
577
|
+
""""""
|
578
|
+
return get_points(self)
|
579
|
+
|
580
|
+
|
581
|
+
def populate_history_info_line(self):
|
582
|
+
result = self.database.fetch_call_history(self.callsign.text())
|
583
|
+
if result:
|
584
|
+
self.history_info.setText(
|
585
|
+
f"{result.get('Call', '')}, {result.get('Exch1', '')}, {result.get('UserText','...')}"
|
586
|
+
)
|
587
|
+
else:
|
588
|
+
self.history_info.setText("")
|
589
|
+
|
590
|
+
|
591
|
+
def check_call_history(self):
|
592
|
+
""""""
|
593
|
+
result = self.database.fetch_call_history(self.callsign.text())
|
594
|
+
if result:
|
595
|
+
self.history_info.setText(f"{result.get('UserText','')}")
|
596
|
+
if self.other_2.text() == "":
|
597
|
+
self.other_2.setText(f"{result.get('Exch1', '')}")
|
not1mm/statistics.py
CHANGED
@@ -6,7 +6,7 @@ import os
|
|
6
6
|
|
7
7
|
from PyQt6 import uic, QtWidgets
|
8
8
|
from PyQt6.QtWidgets import QDockWidget
|
9
|
-
from PyQt6.QtCore import pyqtSignal
|
9
|
+
from PyQt6.QtCore import pyqtSignal, Qt
|
10
10
|
|
11
11
|
import not1mm.fsutils as fsutils
|
12
12
|
from not1mm.lib.database import DataBase
|
@@ -98,6 +98,7 @@ class StatsWindow(QDockWidget):
|
|
98
98
|
if self.active is False:
|
99
99
|
return
|
100
100
|
self.tableWidget.clear()
|
101
|
+
self.tableWidget.setFocusPolicy(Qt.FocusPolicy.NoFocus)
|
101
102
|
self.tableWidget.setColumnCount(7)
|
102
103
|
self.tableWidget.setHorizontalHeaderLabels(
|
103
104
|
["BAND", "QSO", "CALLS", "CW", "PH", "DI", "PTS"]
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: not1mm
|
3
|
-
Version: 25.4.
|
3
|
+
Version: 25.4.9
|
4
4
|
Summary: NOT1MM Logger
|
5
5
|
Author-email: Michael Bridak <michael.bridak@gmail.com>
|
6
6
|
License: GPL-3.0-or-later
|
@@ -141,6 +141,7 @@ Dynamic: license-file
|
|
141
141
|
- [The exchange](#the-exchange)
|
142
142
|
- [RAEM](#raem)
|
143
143
|
- [RandomGram](#randomgram)
|
144
|
+
- [UKEI DX](#ukei-dx)
|
144
145
|
|
145
146
|
## What and Why is Not1MM
|
146
147
|
|
@@ -243,11 +244,14 @@ generated, 'cause I'm lazy, list of those who've submitted PR's.
|
|
243
244
|
- REF CW, SSB
|
244
245
|
- SPDX
|
245
246
|
- Stew Perry Topband
|
247
|
+
- UK/EI DX
|
246
248
|
- Weekly RTTY
|
247
249
|
- Winter Field Day
|
248
250
|
|
249
251
|
## Recent Changes
|
250
252
|
|
253
|
+
- [25-4-9] Added UKEI DX
|
254
|
+
- [25-4-8] Remove focus from statistics table widget.
|
251
255
|
- [25-4-7] Merge in changes from dj1yfk correcting SPDX Cabrillo name.
|
252
256
|
- [25-4-5] Add SPDX.
|
253
257
|
- [25-4-2] Add some tool tips to bandmap and main. Updated Zoom buttons on bandmap. Updated minimum Python version to 3.10.
|
@@ -1033,3 +1037,8 @@ for me 33N117W. And in the exchange macro put `# {EXCH}`.
|
|
1033
1037
|
### RandomGram
|
1034
1038
|
|
1035
1039
|
This plugin was submitted by @alduhoo. It reads a rg.txt file if it exists in the user's home directory to populate the next group in the sent exchange field.
|
1040
|
+
|
1041
|
+
### UKEI DX
|
1042
|
+
|
1043
|
+
For the Run exchange macro I'd put '{SNT} # {EXCH}'
|
1044
|
+
|
@@ -1,5 +1,5 @@
|
|
1
1
|
not1mm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
not1mm/__main__.py,sha256=
|
2
|
+
not1mm/__main__.py,sha256=tFLfbd7kbc4GiR4RKYK3F4DKnohI1SBIiKMsjw67--E,151892
|
3
3
|
not1mm/bandmap.py,sha256=-zu5slsuAm2GmeW8g3yvURzsuQxemwIQfw1HEq8xKHM,29920
|
4
4
|
not1mm/checkwindow.py,sha256=zEHlw40j6Wr3rvKbCQf2lcezCoiZqaBqEvBjQU5aKW0,7630
|
5
5
|
not1mm/fsutils.py,sha256=ukHKxKTeNKxKwqRaJjtzRShL4X5Xl0jRBbADyy3Ifp8,1701
|
@@ -8,7 +8,7 @@ not1mm/lookupservice.py,sha256=GkY_qHZfrW6XHf8upIoaG4hCFqm0fg6Ganu9ConGrIc,2628
|
|
8
8
|
not1mm/radio.py,sha256=_b-tSFuDLoBKnABxrsafGQu2p33U-KOubY7-qgLV2yg,5408
|
9
9
|
not1mm/ratewindow.py,sha256=PeFmmXYKA6ikR8AzWB6n5TS_1NoaHLocw4pSdySq_7A,6995
|
10
10
|
not1mm/rtc_service.py,sha256=axAwnCBuTr-QL0YwXtWvg9tjwhcFsiiEZFgFjOofX6k,2816
|
11
|
-
not1mm/statistics.py,sha256=
|
11
|
+
not1mm/statistics.py,sha256=YbXBCr8wtmXlF21ojgsh0jY_G-dnCApUFe87JZclZAI,7712
|
12
12
|
not1mm/test.py,sha256=RN71m2S9MPIOJMaoCi0wZhwEhpEZunvtosZxaKahRB4,101
|
13
13
|
not1mm/vfo.py,sha256=3kdSfLHLHAGgSE8b8H9n-jFUg_5L7tvrZt_7YCkdsLo,8945
|
14
14
|
not1mm/voice_keying.py,sha256=HZImqC5NgnyW2nknNYQ3b7I8-6S_hxpq5G4RcIRXn_k,3005
|
@@ -34,7 +34,7 @@ not1mm/data/k6gte.not1mm-64.png,sha256=6ku45Gq1g5ezh04F07osoKRtanb3e4kbx5XdIEh3N
|
|
34
34
|
not1mm/data/logwindow.ui,sha256=f7vULj96tHIQuR1nJMyvPHHcmVgzkhv9D1isyojsnFU,1458
|
35
35
|
not1mm/data/logwindowx.ui,sha256=CwpI-h7cI1yqyldH9quKftsdHL5lTyL9ABOcf80nfqc,1632
|
36
36
|
not1mm/data/main.ui,sha256=DNJ7jK_1Dd9SDiiGbdwvXDA0WEKjApdRKqBPYFt7S3c,63737
|
37
|
-
not1mm/data/new_contest.ui,sha256
|
37
|
+
not1mm/data/new_contest.ui,sha256=-EMhmysI9hq3HbMv-SH8bJGzsiW0wOhmRE2iOjqxFQ0,24806
|
38
38
|
not1mm/data/not1mm.html,sha256=c9-mfjMwDt4f5pySUruz2gREW33CQ2_rCddM2z5CZQo,23273
|
39
39
|
not1mm/data/opon.ui,sha256=QDicqAk2lORG2UWsHa6jHlsGn6uzrrI2R4HSAocpPes,2258
|
40
40
|
not1mm/data/pickcontest.ui,sha256=4hPBszCglObThx_eIWtmK9CEcbr7WBjbB1rKZdI-o3I,1707
|
@@ -118,7 +118,7 @@ not1mm/lib/plugin_common.py,sha256=D1OBjyLmX7zuSPqgTCmHwXzAKA12J_zTQItvyIem-4Y,1
|
|
118
118
|
not1mm/lib/select_contest.py,sha256=WsptLuwkouIHeocJL3oZ6-eUfEnhpwdc-x7eMZ_TIVM,359
|
119
119
|
not1mm/lib/settings.py,sha256=mXffn8Xaj5KATPQinNBR0V5DbHWQPsRfh24_axWGYuk,15254
|
120
120
|
not1mm/lib/super_check_partial.py,sha256=hwT2NRwobu0PLDyw6ltmbmcAtGBD02CKGFbgGWjXMqA,2334
|
121
|
-
not1mm/lib/version.py,sha256=
|
121
|
+
not1mm/lib/version.py,sha256=lbRD-owMDb7rKcR3mQWVmU6ChK_06HlEYDAkRCUHqd8,48
|
122
122
|
not1mm/lib/versiontest.py,sha256=8vDNptuBBunn-1IGkjNaquehqBYUJyjrPSF8Igmd4_Y,1286
|
123
123
|
not1mm/plugins/10_10_fall_cw.py,sha256=oJh3JKqjOpnWElSlZpiQ631UnaOd8qra5s9bl_QoInk,14783
|
124
124
|
not1mm/plugins/10_10_spring_cw.py,sha256=p7dSDtbFK0e6Xouw2V6swYn3VFVgHKyx4IfRWyBjMZY,14786
|
@@ -172,11 +172,12 @@ not1mm/plugins/ref_cw.py,sha256=SY-U-DSyhkTFrsQ6ZLYAt0jTWKa8z05rIZiQ8sTQC-U,2138
|
|
172
172
|
not1mm/plugins/ref_ssb.py,sha256=cUFUtbe7-5rwZZHEzpPnaIAnwrwayqBvtgctxQDF5Gw,21592
|
173
173
|
not1mm/plugins/spdx.py,sha256=O_PhTaWdjaV29hj2G8tUK3m6GNx8f40hO1JAF-olLMg,15909
|
174
174
|
not1mm/plugins/stew_perry_topband.py,sha256=3U-Dr28haBTqTaZWLiC1qHQBmLsLENDL-ihyddPpJbg,15403
|
175
|
+
not1mm/plugins/ukeidx.py,sha256=0ABGW7_9Ui0Rgr8mkPBxOJokAIerM1a4-HWnl6VsnV8,19105
|
175
176
|
not1mm/plugins/weekly_rtty.py,sha256=C8Xs3Q5UgSYx-mFFar8BVARWtmqlyrbeC98Ubzb4UN8,20128
|
176
177
|
not1mm/plugins/winter_field_day.py,sha256=hmAMgkdqIXtnCNyUp8J9Bb8liN8wj10wps6ROuG-Bok,15284
|
177
|
-
not1mm-25.4.
|
178
|
-
not1mm-25.4.
|
179
|
-
not1mm-25.4.
|
180
|
-
not1mm-25.4.
|
181
|
-
not1mm-25.4.
|
182
|
-
not1mm-25.4.
|
178
|
+
not1mm-25.4.9.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
179
|
+
not1mm-25.4.9.dist-info/METADATA,sha256=Lrk0LmsoyTv2hyw5_Kl8yGDeWZkyPe6hMnYbGF2WSw8,37550
|
180
|
+
not1mm-25.4.9.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
181
|
+
not1mm-25.4.9.dist-info/entry_points.txt,sha256=pMcZk_0dxFgLkcUkF0Q874ojpwOmF3OL6EKw9LgvocM,47
|
182
|
+
not1mm-25.4.9.dist-info/top_level.txt,sha256=0YmTxEcDzQlzXub-lXASvoLpg_mt1c2thb5cVkDf5J4,7
|
183
|
+
not1mm-25.4.9.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|