not1mm 25.5.25__py3-none-any.whl → 25.5.26__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/data/new_contest.ui +5 -0
- not1mm/lib/version.py +1 -1
- not1mm/logwindow.py +3 -2
- not1mm/plugins/ari_dx.py +558 -0
- not1mm/plugins/canada_day.py +1 -1
- {not1mm-25.5.25.dist-info → not1mm-25.5.26.dist-info}/METADATA +25 -4
- {not1mm-25.5.25.dist-info → not1mm-25.5.26.dist-info}/RECORD +11 -10
- {not1mm-25.5.25.dist-info → not1mm-25.5.26.dist-info}/WHEEL +0 -0
- {not1mm-25.5.25.dist-info → not1mm-25.5.26.dist-info}/entry_points.txt +0 -0
- {not1mm-25.5.25.dist-info → not1mm-25.5.26.dist-info}/licenses/LICENSE +0 -0
- {not1mm-25.5.25.dist-info → not1mm-25.5.26.dist-info}/top_level.txt +0 -0
not1mm/data/new_contest.ui
CHANGED
not1mm/lib/version.py
CHANGED
not1mm/logwindow.py
CHANGED
@@ -900,12 +900,13 @@ class LogWindow(QDockWidget):
|
|
900
900
|
self.get_column("UUID"),
|
901
901
|
QtWidgets.QTableWidgetItem(str(log_item.get("ID", ""))),
|
902
902
|
)
|
903
|
-
|
904
|
-
self.focusedLog.blockSignals(False)
|
903
|
+
|
905
904
|
self.generalLog.resizeColumnsToContents()
|
906
905
|
self.generalLog.resizeRowsToContents()
|
907
906
|
self.focusedLog.resizeColumnsToContents()
|
908
907
|
self.focusedLog.resizeRowsToContents()
|
908
|
+
self.generalLog.blockSignals(False)
|
909
|
+
self.focusedLog.blockSignals(False)
|
909
910
|
|
910
911
|
def show_like_calls(self, call: str) -> None:
|
911
912
|
"""
|
not1mm/plugins/ari_dx.py
ADDED
@@ -0,0 +1,558 @@
|
|
1
|
+
"""ARI International DX Contest"""
|
2
|
+
|
3
|
+
# Status: Active
|
4
|
+
# Geographic Focus: Worldwide
|
5
|
+
# Participation: Worldwide
|
6
|
+
# Awards: Worldwide
|
7
|
+
# Mode: Phone, CW, RTTY
|
8
|
+
# Bands: 80, 40, 20, 15, 10m
|
9
|
+
# Classes: Single Op (CW/SSB/RTTY/Mixed)(Low/High)
|
10
|
+
# Single Op Overlays (Italian only): (Rookie/Youth)
|
11
|
+
# Multi-Single
|
12
|
+
# Multi-Multi
|
13
|
+
# SWL
|
14
|
+
# Max power: HP: >100 watts
|
15
|
+
# LP: 100 watts
|
16
|
+
# Exchange: I: RS(T) + 2-letter province
|
17
|
+
# non-I: RS(T) + Serial No.
|
18
|
+
# Work stations: Once per mode per band
|
19
|
+
# QSO Points: 0 points per QSO with same country
|
20
|
+
# 1 point per QSO with different country same continent
|
21
|
+
# 3 points per QSO with different continent
|
22
|
+
# 10 points per QSO with I/IS0/IT9 stations
|
23
|
+
# Multipliers: Each Italian province once per band
|
24
|
+
# Each DXCC country once per band
|
25
|
+
# Score Calculation: Total score = total QSO points x total mults
|
26
|
+
# E-mail logs to: (none)
|
27
|
+
# Upload log at: https://www.ari.it/contest-hf/ari-international/log-upload.html
|
28
|
+
# Mail logs to: (none)
|
29
|
+
# Find rules at: https://www.ari.it/
|
30
|
+
# Cabrillo name: ARI-DX
|
31
|
+
|
32
|
+
|
33
|
+
# pylint: disable=invalid-name, c-extension-no-member, unused-import, line-too-long
|
34
|
+
|
35
|
+
import datetime
|
36
|
+
import logging
|
37
|
+
import platform
|
38
|
+
|
39
|
+
from pathlib import Path
|
40
|
+
|
41
|
+
from PyQt6 import QtWidgets
|
42
|
+
|
43
|
+
from not1mm.lib.plugin_common import gen_adif
|
44
|
+
from not1mm.lib.version import __version__
|
45
|
+
|
46
|
+
logger = logging.getLogger(__name__)
|
47
|
+
|
48
|
+
EXCHANGE_HINT = "Prov or '#'"
|
49
|
+
|
50
|
+
name = "ARI International DX"
|
51
|
+
cabrillo_name = "ARI-DX"
|
52
|
+
mode = "BOTH" # CW SSB BOTH RTTY
|
53
|
+
|
54
|
+
columns = [
|
55
|
+
"YYYY-MM-DD HH:MM:SS",
|
56
|
+
"Call",
|
57
|
+
"Freq",
|
58
|
+
"Mode",
|
59
|
+
"Snt",
|
60
|
+
"Rcv",
|
61
|
+
"SentNr",
|
62
|
+
"RcvNr",
|
63
|
+
"PTS",
|
64
|
+
]
|
65
|
+
|
66
|
+
advance_on_space = [True, True, True, True, True]
|
67
|
+
|
68
|
+
# 1 once per contest, 2 work each band, 3 each band/mode, 4 no dupe checking
|
69
|
+
dupe_type = 3
|
70
|
+
|
71
|
+
|
72
|
+
def init_contest(self):
|
73
|
+
"""setup plugin"""
|
74
|
+
set_tab_next(self)
|
75
|
+
set_tab_prev(self)
|
76
|
+
interface(self)
|
77
|
+
self.next_field = self.other_2
|
78
|
+
|
79
|
+
|
80
|
+
def interface(self):
|
81
|
+
"""Setup user interface"""
|
82
|
+
self.field1.show()
|
83
|
+
self.field2.show()
|
84
|
+
self.field3.show()
|
85
|
+
self.field4.show()
|
86
|
+
self.snt_label.setText("SNT")
|
87
|
+
self.field1.setAccessibleName("RST Sent")
|
88
|
+
self.exch_label.setText("Prov or SN")
|
89
|
+
self.field4.setAccessibleName("Province or Serial Number")
|
90
|
+
|
91
|
+
|
92
|
+
def reset_label(self): # pylint: disable=unused-argument
|
93
|
+
"""reset label after field cleared"""
|
94
|
+
|
95
|
+
|
96
|
+
def set_tab_next(self):
|
97
|
+
"""Set TAB Advances"""
|
98
|
+
self.tab_next = {
|
99
|
+
self.callsign: self.sent,
|
100
|
+
self.sent: self.receive,
|
101
|
+
self.receive: self.other_1,
|
102
|
+
self.other_1: self.other_2,
|
103
|
+
self.other_2: self.callsign,
|
104
|
+
}
|
105
|
+
|
106
|
+
|
107
|
+
def set_tab_prev(self):
|
108
|
+
"""Set TAB Advances"""
|
109
|
+
self.tab_prev = {
|
110
|
+
self.callsign: self.other_2,
|
111
|
+
self.sent: self.callsign,
|
112
|
+
self.receive: self.sent,
|
113
|
+
self.other_1: self.receive,
|
114
|
+
self.other_2: self.other_1,
|
115
|
+
}
|
116
|
+
|
117
|
+
|
118
|
+
def set_contact_vars(self):
|
119
|
+
"""Contest Specific"""
|
120
|
+
self.contact["SNT"] = self.sent.text()
|
121
|
+
self.contact["RCV"] = self.receive.text()
|
122
|
+
self.contact["NR"] = self.other_2.text().upper()
|
123
|
+
self.contact["SentNr"] = self.other_1.text()
|
124
|
+
|
125
|
+
|
126
|
+
def predupe(self): # pylint: disable=unused-argument
|
127
|
+
"""called after callsign entered"""
|
128
|
+
|
129
|
+
|
130
|
+
def prefill(self):
|
131
|
+
"""Fill sentnr"""
|
132
|
+
result = self.database.get_serial()
|
133
|
+
serial_nr = str(result.get("serial_nr", "1")).zfill(3)
|
134
|
+
if serial_nr == "None":
|
135
|
+
serial_nr = "001"
|
136
|
+
|
137
|
+
exchange = self.contest_settings.get("SentExchange", "").replace("#", serial_nr)
|
138
|
+
if len(self.other_1.text()) == 0:
|
139
|
+
self.other_1.setText(exchange)
|
140
|
+
|
141
|
+
|
142
|
+
def points(self) -> int:
|
143
|
+
"""Calc point"""
|
144
|
+
|
145
|
+
# QSO Points: 0 points per QSO with same country
|
146
|
+
# 1 point per QSO with different country same continent
|
147
|
+
# 3 points per QSO with different continent
|
148
|
+
# 10 points per QSO with I/IS0/IT9 stations
|
149
|
+
|
150
|
+
if self.contact_is_dupe > 0:
|
151
|
+
return 0
|
152
|
+
|
153
|
+
result = self.cty_lookup(self.station.get("Call", ""))
|
154
|
+
if result:
|
155
|
+
for item in result.items():
|
156
|
+
mycountry = item[1].get("primary_pfx", "")
|
157
|
+
myentity = item[1].get("entity", "")
|
158
|
+
mycontinent = item[1].get("continent", "")
|
159
|
+
|
160
|
+
result = self.cty_lookup(self.contact.get("Call", ""))
|
161
|
+
|
162
|
+
if result:
|
163
|
+
for item in result.items():
|
164
|
+
hiscountry = item[1].get("primary_pfx", "")
|
165
|
+
hisentity = item[1].get("entity", "")
|
166
|
+
hiscontinent = item[1].get("continent", "")
|
167
|
+
|
168
|
+
_points = 0
|
169
|
+
|
170
|
+
if mycountry == hiscountry:
|
171
|
+
_points = 0
|
172
|
+
if mycountry != hiscountry and mycontinent == hiscontinent:
|
173
|
+
_points = 1
|
174
|
+
if mycontinent != hiscontinent:
|
175
|
+
_points = 3
|
176
|
+
if hiscountry in ("I", "IS0", "IT9"):
|
177
|
+
_points = 10
|
178
|
+
|
179
|
+
return _points
|
180
|
+
|
181
|
+
|
182
|
+
def show_mults(self):
|
183
|
+
"""Return display string for mults"""
|
184
|
+
|
185
|
+
# Multipliers: Each Italian province once per band
|
186
|
+
# Each DXCC country once per band
|
187
|
+
|
188
|
+
_country = 0
|
189
|
+
_province = 0
|
190
|
+
|
191
|
+
sql = (
|
192
|
+
"select count(DISTINCT(NR || ':' || Band)) as mult_count from dxlog "
|
193
|
+
f"where ContestNR = {self.database.current_contest} and typeof(NR) = 'text';"
|
194
|
+
)
|
195
|
+
result = self.database.exec_sql(sql)
|
196
|
+
if result:
|
197
|
+
_province = result.get("mult_count", 0)
|
198
|
+
|
199
|
+
sql = (
|
200
|
+
"select count(DISTINCT(CountryPrefix || ':' || Band)) as cb_count from dxlog "
|
201
|
+
f"where ContestNR = {self.database.current_contest} and CountryPrefix NOT in ('I', 'IS');"
|
202
|
+
)
|
203
|
+
result2 = self.database.exec_sql(sql)
|
204
|
+
if result2:
|
205
|
+
_country = int(result2.get("cb_count", 0))
|
206
|
+
|
207
|
+
return _country + _province
|
208
|
+
|
209
|
+
|
210
|
+
def show_qso(self):
|
211
|
+
"""Return qso count"""
|
212
|
+
result = self.database.fetch_qso_count()
|
213
|
+
if result:
|
214
|
+
return int(result.get("qsos", 0))
|
215
|
+
return 0
|
216
|
+
|
217
|
+
|
218
|
+
def calc_score(self):
|
219
|
+
"""Return calculated score"""
|
220
|
+
result = self.database.fetch_points()
|
221
|
+
if result is not None:
|
222
|
+
score = result.get("Points", "0")
|
223
|
+
if score is None:
|
224
|
+
score = "0"
|
225
|
+
contest_points = int(score)
|
226
|
+
mults = int(show_mults(self))
|
227
|
+
return contest_points * mults
|
228
|
+
return 0
|
229
|
+
|
230
|
+
|
231
|
+
def adif(self):
|
232
|
+
"""Call the generate ADIF function"""
|
233
|
+
gen_adif(self, cabrillo_name, cabrillo_name)
|
234
|
+
|
235
|
+
|
236
|
+
def output_cabrillo_line(line_to_output, ending, file_descriptor, file_encoding):
|
237
|
+
""""""
|
238
|
+
print(
|
239
|
+
line_to_output.encode(file_encoding, errors="ignore").decode(),
|
240
|
+
end=ending,
|
241
|
+
file=file_descriptor,
|
242
|
+
)
|
243
|
+
|
244
|
+
|
245
|
+
def cabrillo(self, file_encoding):
|
246
|
+
"""Generates Cabrillo file. Maybe."""
|
247
|
+
# https://www.cw160.com/cabrillo.htm
|
248
|
+
logger.debug("******Cabrillo*****")
|
249
|
+
logger.debug("Station: %s", f"{self.station}")
|
250
|
+
logger.debug("Contest: %s", f"{self.contest_settings}")
|
251
|
+
now = datetime.datetime.now()
|
252
|
+
date_time = now.strftime("%Y-%m-%d_%H-%M-%S")
|
253
|
+
filename = (
|
254
|
+
str(Path.home())
|
255
|
+
+ "/"
|
256
|
+
+ f"{self.station.get('Call', '').upper()}_{cabrillo_name}_{date_time}.log"
|
257
|
+
)
|
258
|
+
logger.debug("%s", filename)
|
259
|
+
log = self.database.fetch_all_contacts_asc()
|
260
|
+
try:
|
261
|
+
with open(filename, "w", encoding=file_encoding, newline="") as file_descriptor:
|
262
|
+
output_cabrillo_line(
|
263
|
+
"START-OF-LOG: 3.0",
|
264
|
+
"\r\n",
|
265
|
+
file_descriptor,
|
266
|
+
file_encoding,
|
267
|
+
)
|
268
|
+
output_cabrillo_line(
|
269
|
+
f"CREATED-BY: Not1MM v{__version__}",
|
270
|
+
"\r\n",
|
271
|
+
file_descriptor,
|
272
|
+
file_encoding,
|
273
|
+
)
|
274
|
+
output_cabrillo_line(
|
275
|
+
f"CONTEST: {cabrillo_name}",
|
276
|
+
"\r\n",
|
277
|
+
file_descriptor,
|
278
|
+
file_encoding,
|
279
|
+
)
|
280
|
+
if self.station.get("Club", ""):
|
281
|
+
output_cabrillo_line(
|
282
|
+
f"CLUB: {self.station.get('Club', '').upper()}",
|
283
|
+
"\r\n",
|
284
|
+
file_descriptor,
|
285
|
+
file_encoding,
|
286
|
+
)
|
287
|
+
output_cabrillo_line(
|
288
|
+
f"CALLSIGN: {self.station.get('Call','')}",
|
289
|
+
"\r\n",
|
290
|
+
file_descriptor,
|
291
|
+
file_encoding,
|
292
|
+
)
|
293
|
+
output_cabrillo_line(
|
294
|
+
f"LOCATION: {self.station.get('ARRLSection', '')}",
|
295
|
+
"\r\n",
|
296
|
+
file_descriptor,
|
297
|
+
file_encoding,
|
298
|
+
)
|
299
|
+
output_cabrillo_line(
|
300
|
+
f"CATEGORY-OPERATOR: {self.contest_settings.get('OperatorCategory','')}",
|
301
|
+
"\r\n",
|
302
|
+
file_descriptor,
|
303
|
+
file_encoding,
|
304
|
+
)
|
305
|
+
output_cabrillo_line(
|
306
|
+
f"CATEGORY-ASSISTED: {self.contest_settings.get('AssistedCategory','')}",
|
307
|
+
"\r\n",
|
308
|
+
file_descriptor,
|
309
|
+
file_encoding,
|
310
|
+
)
|
311
|
+
output_cabrillo_line(
|
312
|
+
f"CATEGORY-BAND: {self.contest_settings.get('BandCategory','')}",
|
313
|
+
"\r\n",
|
314
|
+
file_descriptor,
|
315
|
+
file_encoding,
|
316
|
+
)
|
317
|
+
mode = self.contest_settings.get("ModeCategory", "")
|
318
|
+
if mode in ["SSB+CW", "SSB+CW+DIGITAL"]:
|
319
|
+
mode = "MIXED"
|
320
|
+
output_cabrillo_line(
|
321
|
+
f"CATEGORY-MODE: {mode}",
|
322
|
+
"\r\n",
|
323
|
+
file_descriptor,
|
324
|
+
file_encoding,
|
325
|
+
)
|
326
|
+
output_cabrillo_line(
|
327
|
+
f"CATEGORY-TRANSMITTER: {self.contest_settings.get('TransmitterCategory','')}",
|
328
|
+
"\r\n",
|
329
|
+
file_descriptor,
|
330
|
+
file_encoding,
|
331
|
+
)
|
332
|
+
if self.contest_settings.get("OverlayCategory", "") != "N/A":
|
333
|
+
output_cabrillo_line(
|
334
|
+
f"CATEGORY-OVERLAY: {self.contest_settings.get('OverlayCategory','')}",
|
335
|
+
"\r\n",
|
336
|
+
file_descriptor,
|
337
|
+
file_encoding,
|
338
|
+
)
|
339
|
+
output_cabrillo_line(
|
340
|
+
f"GRID-LOCATOR: {self.station.get('GridSquare','')}",
|
341
|
+
"\r\n",
|
342
|
+
file_descriptor,
|
343
|
+
file_encoding,
|
344
|
+
)
|
345
|
+
output_cabrillo_line(
|
346
|
+
f"CATEGORY-POWER: {self.contest_settings.get('PowerCategory','')}",
|
347
|
+
"\r\n",
|
348
|
+
file_descriptor,
|
349
|
+
file_encoding,
|
350
|
+
)
|
351
|
+
|
352
|
+
output_cabrillo_line(
|
353
|
+
f"CLAIMED-SCORE: {calc_score(self)}",
|
354
|
+
"\r\n",
|
355
|
+
file_descriptor,
|
356
|
+
file_encoding,
|
357
|
+
)
|
358
|
+
ops = f"@{self.station.get('Call','')}"
|
359
|
+
list_of_ops = self.database.get_ops()
|
360
|
+
for op in list_of_ops:
|
361
|
+
ops += f", {op.get('Operator', '')}"
|
362
|
+
output_cabrillo_line(
|
363
|
+
f"OPERATORS: {ops}",
|
364
|
+
"\r\n",
|
365
|
+
file_descriptor,
|
366
|
+
file_encoding,
|
367
|
+
)
|
368
|
+
output_cabrillo_line(
|
369
|
+
f"NAME: {self.station.get('Name', '')}",
|
370
|
+
"\r\n",
|
371
|
+
file_descriptor,
|
372
|
+
file_encoding,
|
373
|
+
)
|
374
|
+
output_cabrillo_line(
|
375
|
+
f"ADDRESS: {self.station.get('Street1', '')}",
|
376
|
+
"\r\n",
|
377
|
+
file_descriptor,
|
378
|
+
file_encoding,
|
379
|
+
)
|
380
|
+
output_cabrillo_line(
|
381
|
+
f"ADDRESS-CITY: {self.station.get('City', '')}",
|
382
|
+
"\r\n",
|
383
|
+
file_descriptor,
|
384
|
+
file_encoding,
|
385
|
+
)
|
386
|
+
output_cabrillo_line(
|
387
|
+
f"ADDRESS-STATE-PROVINCE: {self.station.get('State', '')}",
|
388
|
+
"\r\n",
|
389
|
+
file_descriptor,
|
390
|
+
file_encoding,
|
391
|
+
)
|
392
|
+
output_cabrillo_line(
|
393
|
+
f"ADDRESS-POSTALCODE: {self.station.get('Zip', '')}",
|
394
|
+
"\r\n",
|
395
|
+
file_descriptor,
|
396
|
+
file_encoding,
|
397
|
+
)
|
398
|
+
output_cabrillo_line(
|
399
|
+
f"ADDRESS-COUNTRY: {self.station.get('Country', '')}",
|
400
|
+
"\r\n",
|
401
|
+
file_descriptor,
|
402
|
+
file_encoding,
|
403
|
+
)
|
404
|
+
output_cabrillo_line(
|
405
|
+
f"EMAIL: {self.station.get('Email', '')}",
|
406
|
+
"\r\n",
|
407
|
+
file_descriptor,
|
408
|
+
file_encoding,
|
409
|
+
)
|
410
|
+
for contact in log:
|
411
|
+
the_date_and_time = contact.get("TS", "")
|
412
|
+
themode = contact.get("Mode", "")
|
413
|
+
if themode == "LSB" or themode == "USB":
|
414
|
+
themode = "PH"
|
415
|
+
if themode == "RTTY":
|
416
|
+
themode = "RY"
|
417
|
+
frequency = str(int(contact.get("Freq", "0"))).rjust(5)
|
418
|
+
|
419
|
+
loggeddate = the_date_and_time[:10]
|
420
|
+
loggedtime = the_date_and_time[11:13] + the_date_and_time[14:16]
|
421
|
+
output_cabrillo_line(
|
422
|
+
f"QSO: {frequency} {themode} {loggeddate} {loggedtime} "
|
423
|
+
f"{contact.get('StationPrefix', '').ljust(13)} "
|
424
|
+
f"{str(contact.get('SNT', '')).ljust(3)} "
|
425
|
+
f"{str(contact.get('SentNr', '')).upper().ljust(6)} "
|
426
|
+
f"{contact.get('Call', '').ljust(13)} "
|
427
|
+
f"{str(contact.get('RCV', '')).ljust(3)} "
|
428
|
+
f"{str(contact.get('Exchange1', '')).upper().ljust(6)}",
|
429
|
+
"\r\n",
|
430
|
+
file_descriptor,
|
431
|
+
file_encoding,
|
432
|
+
)
|
433
|
+
output_cabrillo_line("END-OF-LOG:", "\r\n", file_descriptor, file_encoding)
|
434
|
+
self.show_message_box(f"Cabrillo saved to: {filename}")
|
435
|
+
except IOError as exception:
|
436
|
+
logger.critical("cabrillo: IO error: %s, writing to %s", exception, filename)
|
437
|
+
self.show_message_box(f"Error saving Cabrillo: {exception} {filename}")
|
438
|
+
return
|
439
|
+
|
440
|
+
|
441
|
+
def trigger_update(self):
|
442
|
+
"""Triggers the log window to update."""
|
443
|
+
cmd = {}
|
444
|
+
cmd["cmd"] = "UPDATELOG"
|
445
|
+
if self.log_window:
|
446
|
+
self.log_window.msg_from_main(cmd)
|
447
|
+
|
448
|
+
|
449
|
+
def recalculate_mults(self):
|
450
|
+
"""Recalculates multipliers after change in logged qso."""
|
451
|
+
|
452
|
+
|
453
|
+
def process_esm(self, new_focused_widget=None, with_enter=False):
|
454
|
+
"""ESM State Machine"""
|
455
|
+
|
456
|
+
# self.pref["run_state"]
|
457
|
+
|
458
|
+
# -----===== Assigned F-Keys =====-----
|
459
|
+
# self.esm_dict["CQ"]
|
460
|
+
# self.esm_dict["EXCH"]
|
461
|
+
# self.esm_dict["QRZ"]
|
462
|
+
# self.esm_dict["AGN"]
|
463
|
+
# self.esm_dict["HISCALL"]
|
464
|
+
# self.esm_dict["MYCALL"]
|
465
|
+
# self.esm_dict["QSOB4"]
|
466
|
+
|
467
|
+
# ----==== text fields ====----
|
468
|
+
# self.callsign
|
469
|
+
# self.sent
|
470
|
+
# self.receive
|
471
|
+
# self.other_1
|
472
|
+
# self.other_2
|
473
|
+
|
474
|
+
if new_focused_widget is not None:
|
475
|
+
self.current_widget = self.inputs_dict.get(new_focused_widget)
|
476
|
+
|
477
|
+
# print(f"checking esm {self.current_widget=} {with_enter=} {self.pref.get("run_state")=}")
|
478
|
+
|
479
|
+
for a_button in [
|
480
|
+
self.esm_dict["CQ"],
|
481
|
+
self.esm_dict["EXCH"],
|
482
|
+
self.esm_dict["QRZ"],
|
483
|
+
self.esm_dict["AGN"],
|
484
|
+
self.esm_dict["HISCALL"],
|
485
|
+
self.esm_dict["MYCALL"],
|
486
|
+
self.esm_dict["QSOB4"],
|
487
|
+
]:
|
488
|
+
if a_button is not None:
|
489
|
+
self.restore_button_color(a_button)
|
490
|
+
|
491
|
+
buttons_to_send = []
|
492
|
+
|
493
|
+
if self.pref.get("run_state"):
|
494
|
+
if self.current_widget == "callsign":
|
495
|
+
if len(self.callsign.text()) < 3:
|
496
|
+
self.make_button_green(self.esm_dict["CQ"])
|
497
|
+
buttons_to_send.append(self.esm_dict["CQ"])
|
498
|
+
elif len(self.callsign.text()) > 2:
|
499
|
+
self.make_button_green(self.esm_dict["HISCALL"])
|
500
|
+
self.make_button_green(self.esm_dict["EXCH"])
|
501
|
+
buttons_to_send.append(self.esm_dict["HISCALL"])
|
502
|
+
buttons_to_send.append(self.esm_dict["EXCH"])
|
503
|
+
|
504
|
+
elif self.current_widget in ["other_2"]:
|
505
|
+
if self.other_2.text() == "":
|
506
|
+
self.make_button_green(self.esm_dict["AGN"])
|
507
|
+
buttons_to_send.append(self.esm_dict["AGN"])
|
508
|
+
else:
|
509
|
+
self.make_button_green(self.esm_dict["QRZ"])
|
510
|
+
buttons_to_send.append(self.esm_dict["QRZ"])
|
511
|
+
buttons_to_send.append("LOGIT")
|
512
|
+
|
513
|
+
if with_enter is True and bool(len(buttons_to_send)):
|
514
|
+
for button in buttons_to_send:
|
515
|
+
if button:
|
516
|
+
if button == "LOGIT":
|
517
|
+
self.save_contact()
|
518
|
+
continue
|
519
|
+
self.process_function_key(button)
|
520
|
+
else:
|
521
|
+
if self.current_widget == "callsign":
|
522
|
+
if len(self.callsign.text()) > 2:
|
523
|
+
self.make_button_green(self.esm_dict["MYCALL"])
|
524
|
+
buttons_to_send.append(self.esm_dict["MYCALL"])
|
525
|
+
|
526
|
+
elif self.current_widget in ["other_2"]:
|
527
|
+
if self.other_2.text() == "":
|
528
|
+
self.make_button_green(self.esm_dict["AGN"])
|
529
|
+
buttons_to_send.append(self.esm_dict["AGN"])
|
530
|
+
else:
|
531
|
+
self.make_button_green(self.esm_dict["EXCH"])
|
532
|
+
buttons_to_send.append(self.esm_dict["EXCH"])
|
533
|
+
buttons_to_send.append("LOGIT")
|
534
|
+
|
535
|
+
if with_enter is True and bool(len(buttons_to_send)):
|
536
|
+
for button in buttons_to_send:
|
537
|
+
if button:
|
538
|
+
if button == "LOGIT":
|
539
|
+
self.save_contact()
|
540
|
+
continue
|
541
|
+
self.process_function_key(button)
|
542
|
+
|
543
|
+
|
544
|
+
def populate_history_info_line(self):
|
545
|
+
result = self.database.fetch_call_history(self.callsign.text())
|
546
|
+
if result:
|
547
|
+
self.history_info.setText(f"{result.get('Call', '')}, {result.get('Sect', '')}")
|
548
|
+
else:
|
549
|
+
self.history_info.setText("")
|
550
|
+
|
551
|
+
|
552
|
+
def check_call_history(self):
|
553
|
+
""""""
|
554
|
+
result = self.database.fetch_call_history(self.callsign.text())
|
555
|
+
if result:
|
556
|
+
self.history_info.setText(f"{result.get('UserText','')}")
|
557
|
+
if self.other_2.text() == "":
|
558
|
+
self.other_2.setText(f"{result.get('Sect', '')}")
|
not1mm/plugins/canada_day.py
CHANGED
@@ -174,7 +174,7 @@ def show_mults(self):
|
|
174
174
|
|
175
175
|
sql = (
|
176
176
|
"select count(DISTINCT(NR || ':' || Band || ':' || Mode)) as mult_count from dxlog "
|
177
|
-
"where ContestNR = {self.database.current_contest} and typeof(NR) = 'text';"
|
177
|
+
f"where ContestNR = {self.database.current_contest} and typeof(NR) = 'text';"
|
178
178
|
)
|
179
179
|
result = self.database.exec_sql(sql)
|
180
180
|
if result:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: not1mm
|
3
|
-
Version: 25.5.
|
3
|
+
Version: 25.5.26
|
4
4
|
Summary: NOT1MM Logger
|
5
5
|
Author-email: Michael Bridak <michael.bridak@gmail.com>
|
6
6
|
License: GPL-3.0-or-later
|
@@ -259,6 +259,7 @@ generated, 'cause I'm lazy, list of those who've submitted PR's.
|
|
259
259
|
|
260
260
|
## Recent Changes
|
261
261
|
|
262
|
+
- [25-5-26] Add ARI DX contest, Fix Canada Day mults.
|
262
263
|
- [25-5-25] Added {PREVNR} macro to resend last logged serial number.
|
263
264
|
- Add Bandmap mode indicators for CW, FT*, SSB, Beacons.
|
264
265
|
- Made tuning with the VFO knob smoother.
|
@@ -898,8 +899,26 @@ blue rectangle shows the receivers bandwidth if one is reported.
|
|
898
899
|
|
899
900
|

|
900
901
|
|
901
|
-
|
902
|
-
|
902
|
+
Clicking on a spots tunes the radio to the spot frequency and sets the callsign field.
|
903
|
+
|
904
|
+
Previously worked calls are displayed in Red.
|
905
|
+
|
906
|
+
Callsigns that were marked with CTRL-M to work later are displayed in a Yellow-ish color.
|
907
|
+
|
908
|
+
In between the spots call and time is now a little icon to visually tell you what kind of spot it is.
|
909
|
+
|
910
|
+

|
911
|
+
|
912
|
+
- ○ CW
|
913
|
+
- ⦿ FT*
|
914
|
+
- ⌾ RTTY
|
915
|
+
- 🗼 Beacons
|
916
|
+
- @ Everything else
|
917
|
+
|
918
|
+
Secondary Icons:
|
919
|
+
|
920
|
+
- [P] POTA
|
921
|
+
- [S] SOTA
|
903
922
|
|
904
923
|
### The Check Partial Window
|
905
924
|
|
@@ -927,7 +946,9 @@ This window contains QSO rates and counts.
|
|
927
946
|
|
928
947
|
You can control the VFO on a remote rig by following the directions listed in
|
929
948
|
the link below. It's a small hardware project with a BOM of under $20, and
|
930
|
-
consisting of two parts.
|
949
|
+
consisting of two parts. The VFO knob is now detectable on MacOS. I've made the
|
950
|
+
operation of the knob smoother by having the knob ignore frequency updates from
|
951
|
+
the radio while it's in rotation.
|
931
952
|
|
932
953
|
1. Making the [VFO](https://github.com/mbridak/not1mm/blob/master/usb_vfo_knob/vfo.md)...
|
933
954
|
2. Then... `Window`>`VFO`
|
@@ -3,7 +3,7 @@ not1mm/__main__.py,sha256=FZZGObcnSJEzEFj7a2K_-DPJUivmDS2tV5boPVudSJs,169592
|
|
3
3
|
not1mm/bandmap.py,sha256=0JmZ32UvkaPjXs2xTgowX1GLvZo5zHU_Zo9y_GL-On4,31139
|
4
4
|
not1mm/checkwindow.py,sha256=zEHlw40j6Wr3rvKbCQf2lcezCoiZqaBqEvBjQU5aKW0,7630
|
5
5
|
not1mm/fsutils.py,sha256=ukHKxKTeNKxKwqRaJjtzRShL4X5Xl0jRBbADyy3Ifp8,1701
|
6
|
-
not1mm/logwindow.py,sha256=
|
6
|
+
not1mm/logwindow.py,sha256=hYzpCQKkwgILFUtP5uxQXy6uU9zCB0R-aBDAUsSOPFI,42625
|
7
7
|
not1mm/lookupservice.py,sha256=GkY_qHZfrW6XHf8upIoaG4hCFqm0fg6Ganu9ConGrIc,2628
|
8
8
|
not1mm/radio.py,sha256=4Lysf9BY3vdtYCHwKfzO5WN7IGyh4_lKSVuQ6F4Z08g,5536
|
9
9
|
not1mm/ratewindow.py,sha256=iBjqdOetIEX0wSwdGM89Ibt4gVlFdE-K8HQPnkVPVOg,6965
|
@@ -36,7 +36,7 @@ not1mm/data/k6gte.not1mm-64.png,sha256=6ku45Gq1g5ezh04F07osoKRtanb3e4kbx5XdIEh3N
|
|
36
36
|
not1mm/data/logwindow.ui,sha256=vfkNdzJgFs3tTOBKLDavF2zVMvNHWOZ82fAErRi6pQY,1436
|
37
37
|
not1mm/data/logwindowx.ui,sha256=9FzDJtLRpagvAWcDjFdB9NnvNZ4bVxdTNHy1Jit2ido,1610
|
38
38
|
not1mm/data/main.ui,sha256=gEWmfXmqLM-DiujjnPdU-4buYJF9TQxS9gE0JlVv_4Y,65142
|
39
|
-
not1mm/data/new_contest.ui,sha256=
|
39
|
+
not1mm/data/new_contest.ui,sha256=uYEn8RU8kkGI2jUC7_gsH5HpVvJdG79cl_10OpvFCXw,25412
|
40
40
|
not1mm/data/not1mm.html,sha256=c9-mfjMwDt4f5pySUruz2gREW33CQ2_rCddM2z5CZQo,23273
|
41
41
|
not1mm/data/opon.ui,sha256=mC4OhoVIfR1H9IqHAKXliPMm8VOVmxSEadpsFQ7XnS4,2247
|
42
42
|
not1mm/data/pickcontest.ui,sha256=Pbb_YEOzQfacyhIRkx-M3ZGugIIPL1KPztdwVv5c_q0,1696
|
@@ -120,7 +120,7 @@ not1mm/lib/plugin_common.py,sha256=D1OBjyLmX7zuSPqgTCmHwXzAKA12J_zTQItvyIem-4Y,1
|
|
120
120
|
not1mm/lib/select_contest.py,sha256=WsptLuwkouIHeocJL3oZ6-eUfEnhpwdc-x7eMZ_TIVM,359
|
121
121
|
not1mm/lib/settings.py,sha256=5xnsagH48qGeCDhfxPWW9yaXtv8wT13yoIVvYt8h_Qs,16023
|
122
122
|
not1mm/lib/super_check_partial.py,sha256=hwT2NRwobu0PLDyw6ltmbmcAtGBD02CKGFbgGWjXMqA,2334
|
123
|
-
not1mm/lib/version.py,sha256=
|
123
|
+
not1mm/lib/version.py,sha256=cxRNTW7axUKEXgODc90wjsXYQxIl8QXaOMWrjWgJAus,49
|
124
124
|
not1mm/lib/versiontest.py,sha256=8vDNptuBBunn-1IGkjNaquehqBYUJyjrPSF8Igmd4_Y,1286
|
125
125
|
not1mm/plugins/10_10_fall_cw.py,sha256=oJh3JKqjOpnWElSlZpiQ631UnaOd8qra5s9bl_QoInk,14783
|
126
126
|
not1mm/plugins/10_10_spring_cw.py,sha256=p7dSDtbFK0e6Xouw2V6swYn3VFVgHKyx4IfRWyBjMZY,14786
|
@@ -128,6 +128,7 @@ not1mm/plugins/10_10_summer_phone.py,sha256=NWWT5YTZN6CkPl5Jy4lCuTqHd1R_JodhsOLq
|
|
128
128
|
not1mm/plugins/10_10_winter_phone.py,sha256=4xoWLbnE2di5XnUUlhsvTR__E0Z4kbhu-rcUitPMR0U,14795
|
129
129
|
not1mm/plugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
130
130
|
not1mm/plugins/ari_40_80.py,sha256=_CaUWEo0zJONXvxPqJKyqmStJezqxEsNxOnEdSLmxzY,15333
|
131
|
+
not1mm/plugins/ari_dx.py,sha256=H1eBKS6m-6ZH7l6wUTb6BjQnS8JTiwEv99xzSZnB0ac,18284
|
131
132
|
not1mm/plugins/arrl_10m.py,sha256=9p7EX2vAXVilF8y6AYHG4fXczU6g9QuMA2Pvj64pSXE,18389
|
132
133
|
not1mm/plugins/arrl_160m.py,sha256=rdWDhmPN0h9ADTlYaRLk-5j8KVye0rUEs1tyD-kfHV0,20300
|
133
134
|
not1mm/plugins/arrl_dx_cw.py,sha256=Bx6_PBmTHKf4l52XwLFVeR2y6F134kXbGTfEXC_1agk,18890
|
@@ -139,7 +140,7 @@ not1mm/plugins/arrl_ss_phone.py,sha256=PzybC--tSB7_oNLbbN9xYkMnftH-z6qgcGZUp3-JG
|
|
139
140
|
not1mm/plugins/arrl_vhf_jan.py,sha256=paYrF_o1EotBRmXn_x9_hEM16SWx7sLDzoSoXcYXcCY,20201
|
140
141
|
not1mm/plugins/arrl_vhf_jun.py,sha256=WwQ-UGFekIZj26bIbq3sLacTYMmUzBYySHhPz2APm2M,19293
|
141
142
|
not1mm/plugins/arrl_vhf_sep.py,sha256=kq5Rncru74G9B76VwfXMeTaF9AL8hq-1vw9ZMYmJmvM,19326
|
142
|
-
not1mm/plugins/canada_day.py,sha256=
|
143
|
+
not1mm/plugins/canada_day.py,sha256=L8pBKcfZGUycBfRS3g9PfeavNIL8CTRAUYk-fVMXDoU,15771
|
143
144
|
not1mm/plugins/cq_160_cw.py,sha256=bmHtxVcIWsqmgqpMCMso7DCBERtAr9fIKIjgymSKtms,18711
|
144
145
|
not1mm/plugins/cq_160_ssb.py,sha256=9KKDmmapETEebm1azfEzUWk1NyW3TBnYtBlFIPZYHBs,18754
|
145
146
|
not1mm/plugins/cq_wpx_cw.py,sha256=F5lLuXumrviNHnNEk377OKeEJCnv_j9vnjHEcV70gFc,18249
|
@@ -182,9 +183,9 @@ not1mm/plugins/ukeidx.py,sha256=0ABGW7_9Ui0Rgr8mkPBxOJokAIerM1a4-HWnl6VsnV8,1910
|
|
182
183
|
not1mm/plugins/vhf_sprint.py,sha256=a9QFTpv8XUbZ_GLjdVCh7svykFa-gXOWwKFZ6MD3uQM,19289
|
183
184
|
not1mm/plugins/weekly_rtty.py,sha256=C8Xs3Q5UgSYx-mFFar8BVARWtmqlyrbeC98Ubzb4UN8,20128
|
184
185
|
not1mm/plugins/winter_field_day.py,sha256=hmAMgkdqIXtnCNyUp8J9Bb8liN8wj10wps6ROuG-Bok,15284
|
185
|
-
not1mm-25.5.
|
186
|
-
not1mm-25.5.
|
187
|
-
not1mm-25.5.
|
188
|
-
not1mm-25.5.
|
189
|
-
not1mm-25.5.
|
190
|
-
not1mm-25.5.
|
186
|
+
not1mm-25.5.26.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
187
|
+
not1mm-25.5.26.dist-info/METADATA,sha256=ADt5-FyZpdmXoqQlQzxeDeb2hnYOaXNyhCgg1cA7YmQ,41888
|
188
|
+
not1mm-25.5.26.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
|
189
|
+
not1mm-25.5.26.dist-info/entry_points.txt,sha256=pMcZk_0dxFgLkcUkF0Q874ojpwOmF3OL6EKw9LgvocM,47
|
190
|
+
not1mm-25.5.26.dist-info/top_level.txt,sha256=0YmTxEcDzQlzXub-lXASvoLpg_mt1c2thb5cVkDf5J4,7
|
191
|
+
not1mm-25.5.26.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|