not1mm 25.4.2__py3-none-any.whl → 25.4.7__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/data/ratewindow.ui +2 -2
- not1mm/lib/version.py +1 -1
- not1mm/plugins/spdx.py +510 -0
- not1mm/ratewindow.py +2 -2
- {not1mm-25.4.2.dist-info → not1mm-25.4.7.dist-info}/METADATA +7 -3
- {not1mm-25.4.2.dist-info → not1mm-25.4.7.dist-info}/RECORD +11 -10
- {not1mm-25.4.2.dist-info → not1mm-25.4.7.dist-info}/WHEEL +0 -0
- {not1mm-25.4.2.dist-info → not1mm-25.4.7.dist-info}/entry_points.txt +0 -0
- {not1mm-25.4.2.dist-info → not1mm-25.4.7.dist-info}/licenses/LICENSE +0 -0
- {not1mm-25.4.2.dist-info → not1mm-25.4.7.dist-info}/top_level.txt +0 -0
not1mm/data/new_contest.ui
CHANGED
not1mm/data/ratewindow.ui
CHANGED
@@ -309,7 +309,7 @@
|
|
309
309
|
<item row="2" column="0">
|
310
310
|
<widget class="QLabel" name="label_18">
|
311
311
|
<property name="text">
|
312
|
-
<string>
|
312
|
+
<string> Hour Run QSO:</string>
|
313
313
|
</property>
|
314
314
|
<property name="alignment">
|
315
315
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
@@ -335,7 +335,7 @@
|
|
335
335
|
<item row="3" column="0">
|
336
336
|
<widget class="QLabel" name="label_17">
|
337
337
|
<property name="text">
|
338
|
-
<string>
|
338
|
+
<string> Hour S&P QSO:</string>
|
339
339
|
</property>
|
340
340
|
<property name="alignment">
|
341
341
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
not1mm/lib/version.py
CHANGED
not1mm/plugins/spdx.py
ADDED
@@ -0,0 +1,510 @@
|
|
1
|
+
"""sp dx contest"""
|
2
|
+
|
3
|
+
# pylint: disable=invalid-name, unused-argument, unused-variable, c-extension-no-member, unused-import
|
4
|
+
|
5
|
+
import datetime
|
6
|
+
import logging
|
7
|
+
|
8
|
+
from pathlib import Path
|
9
|
+
|
10
|
+
from PyQt6 import QtWidgets
|
11
|
+
|
12
|
+
from not1mm.lib.plugin_common import gen_adif, get_points, online_score_xml
|
13
|
+
from not1mm.lib.version import __version__
|
14
|
+
|
15
|
+
logger = logging.getLogger(__name__)
|
16
|
+
|
17
|
+
EXCHANGE_HINT = "Province/Territory"
|
18
|
+
|
19
|
+
name = "SPDX"
|
20
|
+
cabrillo_name = "SPDX"
|
21
|
+
mode = "BOTH" # CW SSB BOTH RTTY
|
22
|
+
|
23
|
+
columns = [
|
24
|
+
"YYYY-MM-DD HH:MM:SS",
|
25
|
+
"Call",
|
26
|
+
"Freq",
|
27
|
+
"Snt",
|
28
|
+
"Rcv",
|
29
|
+
"SentNr",
|
30
|
+
"RcvNr",
|
31
|
+
"PTS",
|
32
|
+
]
|
33
|
+
|
34
|
+
advance_on_space = [True, True, True, True, True]
|
35
|
+
|
36
|
+
# 1 once per contest, 2 work each band, 3 each band/mode, 4 no dupe checking
|
37
|
+
dupe_type = 3
|
38
|
+
|
39
|
+
|
40
|
+
def init_contest(self):
|
41
|
+
"""setup plugin"""
|
42
|
+
set_tab_next(self)
|
43
|
+
set_tab_prev(self)
|
44
|
+
interface(self)
|
45
|
+
self.next_field = self.other_2
|
46
|
+
|
47
|
+
|
48
|
+
def interface(self):
|
49
|
+
"""Setup user interface"""
|
50
|
+
self.field1.show()
|
51
|
+
self.field2.show()
|
52
|
+
self.field3.show()
|
53
|
+
self.field4.show()
|
54
|
+
self.snt_label.setText("SNT")
|
55
|
+
self.field1.setAccessibleName("RST Sent")
|
56
|
+
self.other_label.setText("SentNR")
|
57
|
+
self.field3.setAccessibleName("Sent Number")
|
58
|
+
self.exch_label.setText("Prov or SN")
|
59
|
+
self.field4.setAccessibleName("Province or Serial Number")
|
60
|
+
|
61
|
+
|
62
|
+
def reset_label(self):
|
63
|
+
"""reset label after field cleared"""
|
64
|
+
|
65
|
+
|
66
|
+
def set_tab_next(self):
|
67
|
+
"""Set TAB Advances"""
|
68
|
+
self.tab_next = {
|
69
|
+
self.callsign: self.sent,
|
70
|
+
self.sent: self.receive,
|
71
|
+
self.receive: self.other_1,
|
72
|
+
self.other_1: self.other_2,
|
73
|
+
self.other_2: self.callsign,
|
74
|
+
}
|
75
|
+
|
76
|
+
|
77
|
+
def set_tab_prev(self):
|
78
|
+
"""Set TAB Advances"""
|
79
|
+
self.tab_prev = {
|
80
|
+
self.callsign: self.other_2,
|
81
|
+
self.sent: self.callsign,
|
82
|
+
self.receive: self.sent,
|
83
|
+
self.other_1: self.receive,
|
84
|
+
self.other_2: self.other_1,
|
85
|
+
}
|
86
|
+
|
87
|
+
|
88
|
+
def validate(self):
|
89
|
+
"""doc"""
|
90
|
+
return True
|
91
|
+
|
92
|
+
|
93
|
+
def set_contact_vars(self):
|
94
|
+
"""Contest Specific"""
|
95
|
+
self.contact["SNT"] = self.sent.text()
|
96
|
+
self.contact["RCV"] = self.receive.text()
|
97
|
+
self.contact["NR"] = self.other_2.text().upper()
|
98
|
+
self.contact["SentNr"] = self.other_1.text()
|
99
|
+
|
100
|
+
|
101
|
+
def predupe(self):
|
102
|
+
"""called after callsign entered"""
|
103
|
+
|
104
|
+
|
105
|
+
def prefill(self):
|
106
|
+
"""Fill sentnr"""
|
107
|
+
result = self.database.get_serial()
|
108
|
+
serial_nr = str(result.get("serial_nr", "1")).zfill(3)
|
109
|
+
if serial_nr == "None":
|
110
|
+
serial_nr = "001"
|
111
|
+
|
112
|
+
exchange = self.contest_settings.get("SentExchange", "").replace("#", serial_nr)
|
113
|
+
if len(self.other_1.text()) == 0:
|
114
|
+
self.other_1.setText(exchange)
|
115
|
+
|
116
|
+
|
117
|
+
def points(self):
|
118
|
+
"""Calc point"""
|
119
|
+
|
120
|
+
if self.contact_is_dupe > 0:
|
121
|
+
return 0
|
122
|
+
|
123
|
+
# For Polish stations: A QSO with a DX station (outside Europe) is 3 points,
|
124
|
+
# a QSO with a station in Europe is 1 point.
|
125
|
+
# Contacts between Polish stations: 0 points.
|
126
|
+
|
127
|
+
# For foreign stations: 3 points for every contact with a Polish station.
|
128
|
+
|
129
|
+
mycountry = ""
|
130
|
+
hiscountry = ""
|
131
|
+
hiscontinent = ""
|
132
|
+
|
133
|
+
result = self.cty_lookup(self.station.get("Call", ""))
|
134
|
+
if result:
|
135
|
+
for item in result.items():
|
136
|
+
mycountry = item[1].get("entity", "")
|
137
|
+
|
138
|
+
result = self.cty_lookup(self.contact.get("Call", ""))
|
139
|
+
if result:
|
140
|
+
for item in result.items():
|
141
|
+
hiscountry = item[1].get("entity", "")
|
142
|
+
hiscontinent = item[1].get("continent", "")
|
143
|
+
|
144
|
+
if mycountry == "Poland":
|
145
|
+
if hiscountry == "Poland":
|
146
|
+
return 0
|
147
|
+
if hiscontinent == "EU":
|
148
|
+
return 1
|
149
|
+
return 3
|
150
|
+
else:
|
151
|
+
if hiscountry == "Poland":
|
152
|
+
return 3
|
153
|
+
return 0
|
154
|
+
|
155
|
+
|
156
|
+
def show_mults(self):
|
157
|
+
"""Return display string for mults"""
|
158
|
+
|
159
|
+
sql = (
|
160
|
+
"select count(DISTINCT(NR || ':' || Band || ':' || Mode)) as mult_count from dxlog "
|
161
|
+
"where ContestNR = {self.database.current_contest} and typeof(NR) = 'text';"
|
162
|
+
)
|
163
|
+
result = self.database.exec_sql(sql)
|
164
|
+
if result:
|
165
|
+
return result.get("mult_count", 0)
|
166
|
+
return 0
|
167
|
+
|
168
|
+
|
169
|
+
def show_qso(self):
|
170
|
+
"""Return qso count"""
|
171
|
+
result = self.database.fetch_qso_count()
|
172
|
+
if result:
|
173
|
+
return int(result.get("qsos", 0))
|
174
|
+
return 0
|
175
|
+
|
176
|
+
|
177
|
+
def calc_score(self):
|
178
|
+
"""Return calculated score"""
|
179
|
+
mults = show_mults(self)
|
180
|
+
result = self.database.fetch_points()
|
181
|
+
if result is not None:
|
182
|
+
score = result.get("Points", "0")
|
183
|
+
if score is None:
|
184
|
+
score = "0"
|
185
|
+
if int(mults) > 0:
|
186
|
+
contest_points = int(score) * int(mults)
|
187
|
+
return contest_points
|
188
|
+
contest_points = int(score)
|
189
|
+
return contest_points
|
190
|
+
return 0
|
191
|
+
|
192
|
+
|
193
|
+
def adif(self):
|
194
|
+
"""Call the generate ADIF function"""
|
195
|
+
gen_adif(self, cabrillo_name, "SPDXContest")
|
196
|
+
|
197
|
+
|
198
|
+
def output_cabrillo_line(line_to_output, ending, file_descriptor, file_encoding):
|
199
|
+
""""""
|
200
|
+
print(
|
201
|
+
line_to_output.encode(file_encoding, errors="ignore").decode(),
|
202
|
+
end=ending,
|
203
|
+
file=file_descriptor,
|
204
|
+
)
|
205
|
+
|
206
|
+
|
207
|
+
def cabrillo(self, file_encoding):
|
208
|
+
"""Generates Cabrillo file. Maybe."""
|
209
|
+
# https://www.cqwpx.com/cabrillo.htm
|
210
|
+
logger.debug("******Cabrillo*****")
|
211
|
+
logger.debug("Station: %s", f"{self.station}")
|
212
|
+
logger.debug("Contest: %s", f"{self.contest_settings}")
|
213
|
+
now = datetime.datetime.now()
|
214
|
+
date_time = now.strftime("%Y-%m-%d_%H-%M-%S")
|
215
|
+
filename = (
|
216
|
+
str(Path.home())
|
217
|
+
+ "/"
|
218
|
+
+ f"{self.station.get('Call', '').upper()}_{cabrillo_name}_{date_time}.log"
|
219
|
+
)
|
220
|
+
logger.debug("%s", filename)
|
221
|
+
log = self.database.fetch_all_contacts_asc()
|
222
|
+
try:
|
223
|
+
with open(filename, "w", encoding=file_encoding, newline="") as file_descriptor:
|
224
|
+
output_cabrillo_line(
|
225
|
+
"START-OF-LOG: 3.0",
|
226
|
+
"\r\n",
|
227
|
+
file_descriptor,
|
228
|
+
file_encoding,
|
229
|
+
)
|
230
|
+
output_cabrillo_line(
|
231
|
+
f"CREATED-BY: Not1MM v{__version__}",
|
232
|
+
"\r\n",
|
233
|
+
file_descriptor,
|
234
|
+
file_encoding,
|
235
|
+
)
|
236
|
+
output_cabrillo_line(
|
237
|
+
f"CONTEST: {cabrillo_name}",
|
238
|
+
"\r\n",
|
239
|
+
file_descriptor,
|
240
|
+
file_encoding,
|
241
|
+
)
|
242
|
+
if self.station.get("Club", ""):
|
243
|
+
output_cabrillo_line(
|
244
|
+
f"CLUB: {self.station.get('Club', '').upper()}",
|
245
|
+
"\r\n",
|
246
|
+
file_descriptor,
|
247
|
+
file_encoding,
|
248
|
+
)
|
249
|
+
output_cabrillo_line(
|
250
|
+
f"CALLSIGN: {self.station.get('Call','')}",
|
251
|
+
"\r\n",
|
252
|
+
file_descriptor,
|
253
|
+
file_encoding,
|
254
|
+
)
|
255
|
+
output_cabrillo_line(
|
256
|
+
f"LOCATION: {self.station.get('ARRLSection', '')}",
|
257
|
+
"\r\n",
|
258
|
+
file_descriptor,
|
259
|
+
file_encoding,
|
260
|
+
)
|
261
|
+
output_cabrillo_line(
|
262
|
+
f"CATEGORY-OPERATOR: {self.contest_settings.get('OperatorCategory','')}",
|
263
|
+
"\r\n",
|
264
|
+
file_descriptor,
|
265
|
+
file_encoding,
|
266
|
+
)
|
267
|
+
output_cabrillo_line(
|
268
|
+
f"CATEGORY-ASSISTED: {self.contest_settings.get('AssistedCategory','')}",
|
269
|
+
"\r\n",
|
270
|
+
file_descriptor,
|
271
|
+
file_encoding,
|
272
|
+
)
|
273
|
+
output_cabrillo_line(
|
274
|
+
f"CATEGORY-BAND: {self.contest_settings.get('BandCategory','')}",
|
275
|
+
"\r\n",
|
276
|
+
file_descriptor,
|
277
|
+
file_encoding,
|
278
|
+
)
|
279
|
+
mode = self.contest_settings.get("ModeCategory", "")
|
280
|
+
if mode in ["SSB+CW", "SSB+CW+DIGITAL"]:
|
281
|
+
mode = "MIXED"
|
282
|
+
output_cabrillo_line(
|
283
|
+
f"CATEGORY-MODE: {mode}",
|
284
|
+
"\r\n",
|
285
|
+
file_descriptor,
|
286
|
+
file_encoding,
|
287
|
+
)
|
288
|
+
output_cabrillo_line(
|
289
|
+
f"CATEGORY-TRANSMITTER: {self.contest_settings.get('TransmitterCategory','')}",
|
290
|
+
"\r\n",
|
291
|
+
file_descriptor,
|
292
|
+
file_encoding,
|
293
|
+
)
|
294
|
+
if self.contest_settings.get("OverlayCategory", "") != "N/A":
|
295
|
+
output_cabrillo_line(
|
296
|
+
f"CATEGORY-OVERLAY: {self.contest_settings.get('OverlayCategory','')}",
|
297
|
+
"\r\n",
|
298
|
+
file_descriptor,
|
299
|
+
file_encoding,
|
300
|
+
)
|
301
|
+
output_cabrillo_line(
|
302
|
+
f"GRID-LOCATOR: {self.station.get('GridSquare','')}",
|
303
|
+
"\r\n",
|
304
|
+
file_descriptor,
|
305
|
+
file_encoding,
|
306
|
+
)
|
307
|
+
output_cabrillo_line(
|
308
|
+
f"CATEGORY-POWER: {self.contest_settings.get('PowerCategory','')}",
|
309
|
+
"\r\n",
|
310
|
+
file_descriptor,
|
311
|
+
file_encoding,
|
312
|
+
)
|
313
|
+
|
314
|
+
output_cabrillo_line(
|
315
|
+
f"CLAIMED-SCORE: {calc_score(self)}",
|
316
|
+
"\r\n",
|
317
|
+
file_descriptor,
|
318
|
+
file_encoding,
|
319
|
+
)
|
320
|
+
ops = f"@{self.station.get('Call','')}"
|
321
|
+
list_of_ops = self.database.get_ops()
|
322
|
+
for op in list_of_ops:
|
323
|
+
ops += f", {op.get('Operator', '')}"
|
324
|
+
output_cabrillo_line(
|
325
|
+
f"OPERATORS: {ops}",
|
326
|
+
"\r\n",
|
327
|
+
file_descriptor,
|
328
|
+
file_encoding,
|
329
|
+
)
|
330
|
+
output_cabrillo_line(
|
331
|
+
f"NAME: {self.station.get('Name', '')}",
|
332
|
+
"\r\n",
|
333
|
+
file_descriptor,
|
334
|
+
file_encoding,
|
335
|
+
)
|
336
|
+
output_cabrillo_line(
|
337
|
+
f"ADDRESS: {self.station.get('Street1', '')}",
|
338
|
+
"\r\n",
|
339
|
+
file_descriptor,
|
340
|
+
file_encoding,
|
341
|
+
)
|
342
|
+
output_cabrillo_line(
|
343
|
+
f"ADDRESS-CITY: {self.station.get('City', '')}",
|
344
|
+
"\r\n",
|
345
|
+
file_descriptor,
|
346
|
+
file_encoding,
|
347
|
+
)
|
348
|
+
output_cabrillo_line(
|
349
|
+
f"ADDRESS-STATE-PROVINCE: {self.station.get('State', '')}",
|
350
|
+
"\r\n",
|
351
|
+
file_descriptor,
|
352
|
+
file_encoding,
|
353
|
+
)
|
354
|
+
output_cabrillo_line(
|
355
|
+
f"ADDRESS-POSTALCODE: {self.station.get('Zip', '')}",
|
356
|
+
"\r\n",
|
357
|
+
file_descriptor,
|
358
|
+
file_encoding,
|
359
|
+
)
|
360
|
+
output_cabrillo_line(
|
361
|
+
f"ADDRESS-COUNTRY: {self.station.get('Country', '')}",
|
362
|
+
"\r\n",
|
363
|
+
file_descriptor,
|
364
|
+
file_encoding,
|
365
|
+
)
|
366
|
+
output_cabrillo_line(
|
367
|
+
f"EMAIL: {self.station.get('Email', '')}",
|
368
|
+
"\r\n",
|
369
|
+
file_descriptor,
|
370
|
+
file_encoding,
|
371
|
+
)
|
372
|
+
for contact in log:
|
373
|
+
the_date_and_time = contact.get("TS", "")
|
374
|
+
themode = contact.get("Mode", "")
|
375
|
+
if themode == "LSB" or themode == "USB":
|
376
|
+
themode = "PH"
|
377
|
+
frequency = str(int(contact.get("Freq", "0"))).rjust(5)
|
378
|
+
|
379
|
+
loggeddate = the_date_and_time[:10]
|
380
|
+
loggedtime = the_date_and_time[11:13] + the_date_and_time[14:16]
|
381
|
+
output_cabrillo_line(
|
382
|
+
f"QSO: {frequency} {themode} {loggeddate} {loggedtime} "
|
383
|
+
f"{contact.get('StationPrefix', '').ljust(13)} "
|
384
|
+
f"{str(contact.get('SNT', '')).ljust(3)} "
|
385
|
+
f"{str(contact.get('SentNr', '')).ljust(6)} "
|
386
|
+
f"{contact.get('Call', '').ljust(13)} "
|
387
|
+
f"{str(contact.get('RCV', '')).ljust(3)} "
|
388
|
+
f"{str(contact.get('NR', '')).ljust(6)}",
|
389
|
+
"\r\n",
|
390
|
+
file_descriptor,
|
391
|
+
file_encoding,
|
392
|
+
)
|
393
|
+
output_cabrillo_line("END-OF-LOG:", "\r\n", file_descriptor, file_encoding)
|
394
|
+
self.show_message_box(f"Cabrillo saved to: {filename}")
|
395
|
+
except IOError as exception:
|
396
|
+
logger.critical("cabrillo: IO error: %s, writing to %s", exception, filename)
|
397
|
+
self.show_message_box(f"Error saving Cabrillo: {exception} {filename}")
|
398
|
+
return
|
399
|
+
|
400
|
+
|
401
|
+
def recalculate_mults(self):
|
402
|
+
"""Recalculates multipliers after change in logged qso."""
|
403
|
+
|
404
|
+
|
405
|
+
def process_esm(self, new_focused_widget=None, with_enter=False):
|
406
|
+
"""ESM State Machine"""
|
407
|
+
|
408
|
+
# self.pref["run_state"]
|
409
|
+
|
410
|
+
# -----===== Assigned F-Keys =====-----
|
411
|
+
# self.esm_dict["CQ"]
|
412
|
+
# self.esm_dict["EXCH"]
|
413
|
+
# self.esm_dict["QRZ"]
|
414
|
+
# self.esm_dict["AGN"]
|
415
|
+
# self.esm_dict["HISCALL"]
|
416
|
+
# self.esm_dict["MYCALL"]
|
417
|
+
# self.esm_dict["QSOB4"]
|
418
|
+
|
419
|
+
# ----==== text fields ====----
|
420
|
+
# self.callsign
|
421
|
+
# self.sent
|
422
|
+
# self.receive
|
423
|
+
# self.other_1
|
424
|
+
# self.other_2
|
425
|
+
|
426
|
+
if new_focused_widget is not None:
|
427
|
+
self.current_widget = self.inputs_dict.get(new_focused_widget)
|
428
|
+
|
429
|
+
for a_button in [
|
430
|
+
self.esm_dict["CQ"],
|
431
|
+
self.esm_dict["EXCH"],
|
432
|
+
self.esm_dict["QRZ"],
|
433
|
+
self.esm_dict["AGN"],
|
434
|
+
self.esm_dict["HISCALL"],
|
435
|
+
self.esm_dict["MYCALL"],
|
436
|
+
self.esm_dict["QSOB4"],
|
437
|
+
]:
|
438
|
+
if a_button is not None:
|
439
|
+
self.restore_button_color(a_button)
|
440
|
+
|
441
|
+
buttons_to_send = []
|
442
|
+
|
443
|
+
if self.pref.get("run_state"):
|
444
|
+
if self.current_widget == "callsign":
|
445
|
+
if len(self.callsign.text()) < 3:
|
446
|
+
self.make_button_green(self.esm_dict["CQ"])
|
447
|
+
buttons_to_send.append(self.esm_dict["CQ"])
|
448
|
+
elif len(self.callsign.text()) > 2:
|
449
|
+
self.make_button_green(self.esm_dict["HISCALL"])
|
450
|
+
self.make_button_green(self.esm_dict["EXCH"])
|
451
|
+
buttons_to_send.append(self.esm_dict["HISCALL"])
|
452
|
+
buttons_to_send.append(self.esm_dict["EXCH"])
|
453
|
+
|
454
|
+
elif self.current_widget in ["other_1", "other_2"]:
|
455
|
+
if self.other_1.text() == "" or self.other_2.text() == "":
|
456
|
+
self.make_button_green(self.esm_dict["AGN"])
|
457
|
+
buttons_to_send.append(self.esm_dict["AGN"])
|
458
|
+
else:
|
459
|
+
self.make_button_green(self.esm_dict["QRZ"])
|
460
|
+
buttons_to_send.append(self.esm_dict["QRZ"])
|
461
|
+
buttons_to_send.append("LOGIT")
|
462
|
+
|
463
|
+
if with_enter is True and bool(len(buttons_to_send)):
|
464
|
+
for button in buttons_to_send:
|
465
|
+
if button:
|
466
|
+
if button == "LOGIT":
|
467
|
+
self.save_contact()
|
468
|
+
continue
|
469
|
+
self.process_function_key(button)
|
470
|
+
else:
|
471
|
+
if self.current_widget == "callsign":
|
472
|
+
if len(self.callsign.text()) > 2:
|
473
|
+
self.make_button_green(self.esm_dict["MYCALL"])
|
474
|
+
buttons_to_send.append(self.esm_dict["MYCALL"])
|
475
|
+
|
476
|
+
elif self.current_widget in ["other_1", "other_2"]:
|
477
|
+
if self.other_1.text() == "" or self.other_2.text() == "":
|
478
|
+
self.make_button_green(self.esm_dict["AGN"])
|
479
|
+
buttons_to_send.append(self.esm_dict["AGN"])
|
480
|
+
else:
|
481
|
+
self.make_button_green(self.esm_dict["EXCH"])
|
482
|
+
buttons_to_send.append(self.esm_dict["EXCH"])
|
483
|
+
buttons_to_send.append("LOGIT")
|
484
|
+
|
485
|
+
if with_enter is True and bool(len(buttons_to_send)):
|
486
|
+
for button in buttons_to_send:
|
487
|
+
if button:
|
488
|
+
if button == "LOGIT":
|
489
|
+
self.save_contact()
|
490
|
+
continue
|
491
|
+
self.process_function_key(button)
|
492
|
+
|
493
|
+
|
494
|
+
def get_mults(self):
|
495
|
+
""""""
|
496
|
+
|
497
|
+
mults = {}
|
498
|
+
mults["state"] = show_mults(self)
|
499
|
+
return mults
|
500
|
+
|
501
|
+
|
502
|
+
def just_points(self):
|
503
|
+
""""""
|
504
|
+
result = self.database.fetch_points()
|
505
|
+
if result is not None:
|
506
|
+
score = result.get("Points", "0")
|
507
|
+
if score is None:
|
508
|
+
score = "0"
|
509
|
+
return int(score)
|
510
|
+
return 0
|
not1mm/ratewindow.py
CHANGED
@@ -160,11 +160,11 @@ class RateWindow(QDockWidget):
|
|
160
160
|
...
|
161
161
|
|
162
162
|
# Get rate for the current hour
|
163
|
-
query = f"SELECT strftime('%Y-%m-%d %H:00:00','now') as limit_stamp, strftime('%
|
163
|
+
query = f"SELECT strftime('%Y-%m-%d %H:00:00','now') as limit_stamp, strftime('%H00','now') as current_hour, count(*) as items FROM DXLOG where ContestNR = {self.database.current_contest} and datetime(TS) > limit_stamp;"
|
164
164
|
result = self.database.exec_sql(query)
|
165
165
|
|
166
166
|
self.since_lasthour_label.setText(
|
167
|
-
f"Since {result.get('current_hour', '
|
167
|
+
f"Since {result.get('current_hour', '0000')}z:"
|
168
168
|
)
|
169
169
|
self.since_lasthour.setText(f"{result.get('items', '0')} QSO")
|
170
170
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: not1mm
|
3
|
-
Version: 25.4.
|
3
|
+
Version: 25.4.7
|
4
4
|
Summary: NOT1MM Logger
|
5
5
|
Author-email: Michael Bridak <michael.bridak@gmail.com>
|
6
6
|
License: GPL-3.0-or-later
|
@@ -39,7 +39,7 @@ Dynamic: license-file
|
|
39
39
|
|
40
40
|
[](https://pypi.org/project/not1mm/)
|
41
41
|
[](https://www.gnu.org/licenses/gpl-3.0)
|
42
|
-
[](https://www.python.org/downloads/)
|
43
43
|
[](https://pypi.org/project/PyQt6/)
|
44
44
|
[](https://xkcd.com/1695/)
|
45
45
|
[](https://pypi.org/project/not1mm/)
|
@@ -241,12 +241,15 @@ generated, 'cause I'm lazy, list of those who've submitted PR's.
|
|
241
241
|
- RandomGram
|
242
242
|
- RAC Canada Day
|
243
243
|
- REF CW, SSB
|
244
|
+
- SPDX
|
244
245
|
- Stew Perry Topband
|
245
246
|
- Weekly RTTY
|
246
247
|
- Winter Field Day
|
247
248
|
|
248
249
|
## Recent Changes
|
249
250
|
|
251
|
+
- [25-4-7] Merge in changes from dj1yfk correcting SPDX Cabrillo name.
|
252
|
+
- [25-4-5] Add SPDX.
|
250
253
|
- [25-4-2] Add some tool tips to bandmap and main. Updated Zoom buttons on bandmap. Updated minimum Python version to 3.10.
|
251
254
|
- [25-4-1] Fix: statistics window not populating when initially activated from the window menu. Removed unused code chucks. Removed some unused and hidden visual elements.
|
252
255
|
|
@@ -658,7 +661,8 @@ pressing F1 - F12. See next section on Editing macro keys.
|
|
658
661
|
|
659
662
|
If you press `SHIFT-F1` The Auto CQ mode will be activated and the F1 macro will be resent
|
660
663
|
after each Auto CQ Delay interval has passed. The delay can be changed by going to the
|
661
|
-
`Options` TAB in the Configuration dialog.
|
664
|
+
`Options` TAB in the Configuration dialog. If you are in S&P mode, you will be automatically
|
665
|
+
switched into RUN mode.
|
662
666
|
|
663
667
|
The auto CQ can be cancelled by either typing in the call sign field, or by pressing ESC.
|
664
668
|
|
@@ -6,7 +6,7 @@ not1mm/fsutils.py,sha256=ukHKxKTeNKxKwqRaJjtzRShL4X5Xl0jRBbADyy3Ifp8,1701
|
|
6
6
|
not1mm/logwindow.py,sha256=5I0nNfTR0zGw1LQ3cC4drcZo3l58kxf5UA5F0AZ-fKc,42565
|
7
7
|
not1mm/lookupservice.py,sha256=GkY_qHZfrW6XHf8upIoaG4hCFqm0fg6Ganu9ConGrIc,2628
|
8
8
|
not1mm/radio.py,sha256=_b-tSFuDLoBKnABxrsafGQu2p33U-KOubY7-qgLV2yg,5408
|
9
|
-
not1mm/ratewindow.py,sha256=
|
9
|
+
not1mm/ratewindow.py,sha256=PeFmmXYKA6ikR8AzWB6n5TS_1NoaHLocw4pSdySq_7A,6995
|
10
10
|
not1mm/rtc_service.py,sha256=axAwnCBuTr-QL0YwXtWvg9tjwhcFsiiEZFgFjOofX6k,2816
|
11
11
|
not1mm/statistics.py,sha256=PtlOUmogW9JSTBlQmMhU6yXl_hoLJquYrdX88Oi-2NA,7644
|
12
12
|
not1mm/test.py,sha256=RN71m2S9MPIOJMaoCi0wZhwEhpEZunvtosZxaKahRB4,101
|
@@ -34,14 +34,14 @@ 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=7B8l_pCaL43ECvGva5S9_gU6_JoNWFEGBE4-EO6BTBY,24703
|
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
|
41
41
|
not1mm/data/radio_green.png,sha256=PXlvRI2x0C8yLVkxRwrZe6tex8k9GtM-1Cj2Vy6KP7o,1234
|
42
42
|
not1mm/data/radio_grey.png,sha256=9eOtMHDpQvRYY29D7_vPeacWbwotRXZTMm8EiHE9TW0,1258
|
43
43
|
not1mm/data/radio_red.png,sha256=QvkMk7thd_hCEIyK5xGAG4xVVXivl39nwOfD8USDI20,957
|
44
|
-
not1mm/data/ratewindow.ui,sha256=
|
44
|
+
not1mm/data/ratewindow.ui,sha256=uikGzsvEGG-RPIgZFLLSJHRRRrlzqDJvDuz7DXrSiFM,11563
|
45
45
|
not1mm/data/reddot.png,sha256=M33jEMoU8W4rQ4_MVyzzKxDPDte1ypKBch5VnUMNLKE,565
|
46
46
|
not1mm/data/rttymacros.txt,sha256=FQ2BnAChXF5w-tzmMnBOE8IgvviAEsd3cmmz4b8GOPk,467
|
47
47
|
not1mm/data/settings.ui,sha256=rZmhUjFAyCA8B-cd4Ljrvz5qC3NKy6S3feYVh5WX-tw,40084
|
@@ -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=NA-5bEubD0W-8k5VFfCmY_3Gl8_LkxNwflNMKAbDXTo,47
|
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
|
@@ -170,12 +170,13 @@ not1mm/plugins/raem.py,sha256=EWoUWhuYrLaR6lRz8fDG09GT4AyZNuf7LlkKg1i1aYc,19624
|
|
170
170
|
not1mm/plugins/randomgram.py,sha256=h68Ul57maCRhZOou7jU4_B1Dfd3d4n5r-Qzex80yJOk,7401
|
171
171
|
not1mm/plugins/ref_cw.py,sha256=SY-U-DSyhkTFrsQ6ZLYAt0jTWKa8z05rIZiQ8sTQC-U,21382
|
172
172
|
not1mm/plugins/ref_ssb.py,sha256=cUFUtbe7-5rwZZHEzpPnaIAnwrwayqBvtgctxQDF5Gw,21592
|
173
|
+
not1mm/plugins/spdx.py,sha256=O_PhTaWdjaV29hj2G8tUK3m6GNx8f40hO1JAF-olLMg,15909
|
173
174
|
not1mm/plugins/stew_perry_topband.py,sha256=3U-Dr28haBTqTaZWLiC1qHQBmLsLENDL-ihyddPpJbg,15403
|
174
175
|
not1mm/plugins/weekly_rtty.py,sha256=C8Xs3Q5UgSYx-mFFar8BVARWtmqlyrbeC98Ubzb4UN8,20128
|
175
176
|
not1mm/plugins/winter_field_day.py,sha256=hmAMgkdqIXtnCNyUp8J9Bb8liN8wj10wps6ROuG-Bok,15284
|
176
|
-
not1mm-25.4.
|
177
|
-
not1mm-25.4.
|
178
|
-
not1mm-25.4.
|
179
|
-
not1mm-25.4.
|
180
|
-
not1mm-25.4.
|
181
|
-
not1mm-25.4.
|
177
|
+
not1mm-25.4.7.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
178
|
+
not1mm-25.4.7.dist-info/METADATA,sha256=B9oqzlPf74X08weJrQef3ruQZG9qQKrgNVukCqSskfA,37367
|
179
|
+
not1mm-25.4.7.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
180
|
+
not1mm-25.4.7.dist-info/entry_points.txt,sha256=pMcZk_0dxFgLkcUkF0Q874ojpwOmF3OL6EKw9LgvocM,47
|
181
|
+
not1mm-25.4.7.dist-info/top_level.txt,sha256=0YmTxEcDzQlzXub-lXASvoLpg_mt1c2thb5cVkDf5J4,7
|
182
|
+
not1mm-25.4.7.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|