not1mm 25.1.26.1__py3-none-any.whl → 25.1.27.1__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 CHANGED
@@ -725,7 +725,9 @@ class MainWindow(QtWidgets.QMainWindow):
725
725
  if VersionTest(__version__).test():
726
726
  self.show_message_box(
727
727
  "There is a newer version of not1mm available.\n"
728
- "You can udate to the current version by using:\npip install -U not1mm"
728
+ "You can udate to the current version by using:\n\n"
729
+ "pip install -U not1mm\n\tor\n"
730
+ "pipx upgrade not1mm"
729
731
  )
730
732
 
731
733
  self.udp_socket = QtNetwork.QUdpSocket()
@@ -362,6 +362,11 @@
362
362
  <string>K1USN SST</string>
363
363
  </property>
364
364
  </item>
365
+ <item>
366
+ <property name="text">
367
+ <string>LABRE RS DIGI</string>
368
+ </property>
369
+ </item>
365
370
  <item>
366
371
  <property name="text">
367
372
  <string>LZ-DX</string>
not1mm/lib/version.py CHANGED
@@ -1,3 +1,3 @@
1
1
  """It's the version"""
2
2
 
3
- __version__ = "25.1.26.1"
3
+ __version__ = "25.1.27.1"
@@ -0,0 +1,634 @@
1
+ """LABRE-RS Digi"""
2
+
3
+ # LABRE-RS Digi Contest
4
+ # Status: Active
5
+ # Geographic Focus: Worldwide
6
+ # Participation: Worldwide
7
+ # Mode: FT4/8
8
+ # Bands: 80, 40, 20, 15, 10m
9
+ # Classes: Single Op(QRP/Low/High)
10
+ # Multi-Single (Low/High)
11
+ # Multi-Multi
12
+ # Max power: HP: 1500 watts
13
+ # LP: 100 watts
14
+ # QRP: 5 watts
15
+ # Exchange: 4-character grid square
16
+ # Work stations: Once per band
17
+ # QSO Points: 1 point per QSO
18
+ # 1 additional point per QSO with PY3,PU3,ZZ3,PP3,etc
19
+ # Multipliers: Each grid field (first 2 letters of grid square) once per band
20
+ # Score Calculation: Total score = total QSO points x total mults
21
+ # E-mail logs to: (none)
22
+ # Upload log at: https://hampass.org/contests
23
+ # Mail logs to: (none)
24
+ # Find rules at: https://labre-rs.org.br/labre-rs-digi-contest/
25
+ # Cabrillo name: CQWW-DIGI
26
+ # Cabrillo name aliases:
27
+
28
+ # pylint: disable=invalid-name, unused-argument, unused-variable, c-extension-no-member
29
+
30
+ import datetime
31
+ import logging
32
+
33
+ from pathlib import Path
34
+ from PyQt6 import QtWidgets
35
+
36
+ from not1mm.lib.ham_utility import get_logged_band
37
+ from not1mm.lib.plugin_common import gen_adif, get_points, online_score_xml
38
+ from not1mm.lib.version import __version__
39
+
40
+ logger = logging.getLogger(__name__)
41
+
42
+ ALTEREGO = None
43
+ EXCHANGE_HINT = "4-character grid square"
44
+
45
+ name = "LABRE-RS Digi"
46
+ mode = "RTTY" # CW SSB BOTH RTTY
47
+ cabrillo_name = "CQWW-DIGI"
48
+
49
+ columns = [
50
+ "YYYY-MM-DD HH:MM:SS",
51
+ "Call",
52
+ "Freq",
53
+ "Mode",
54
+ "SentNr",
55
+ "RcvNr",
56
+ "PTS",
57
+ ]
58
+
59
+ advance_on_space = [True, True, True, True, True]
60
+
61
+ # 1 once per contest, 2 work each band, 3 each band/mode, 4 no dupe checking
62
+ dupe_type = 2
63
+
64
+
65
+ def init_contest(self):
66
+ """setup plugin"""
67
+ set_tab_next(self)
68
+ set_tab_prev(self)
69
+ interface(self)
70
+ self.next_field = self.other_2
71
+
72
+
73
+ def interface(self):
74
+ """Setup user interface"""
75
+ self.field1.show()
76
+ self.field2.show()
77
+ self.field3.show()
78
+ self.field4.show()
79
+ self.snt_label.setText("SNT")
80
+ self.field1.setAccessibleName("RST Sent")
81
+ self.other_label.setText("SentNR")
82
+ self.field3.setAccessibleName("Sent Grid")
83
+ self.exch_label.setText("Grid")
84
+ self.field4.setAccessibleName("Gridsquare")
85
+
86
+
87
+ def reset_label(self):
88
+ """reset label after field cleared"""
89
+
90
+
91
+ def set_tab_next(self):
92
+ """Set TAB Advances"""
93
+ self.tab_next = {
94
+ self.callsign: self.sent,
95
+ self.sent: self.receive,
96
+ self.receive: self.other_1,
97
+ self.other_1: self.other_2,
98
+ self.other_2: self.callsign,
99
+ }
100
+
101
+
102
+ def set_tab_prev(self):
103
+ """Set TAB Advances"""
104
+ self.tab_prev = {
105
+ self.callsign: self.other_2,
106
+ self.sent: self.callsign,
107
+ self.receive: self.sent,
108
+ self.other_1: self.receive,
109
+ self.other_2: self.other_1,
110
+ }
111
+
112
+
113
+ def validate(self):
114
+ """doc"""
115
+ # exchange = self.other_2.text().upper().split()
116
+ # if len(exchange) == 3:
117
+ # if exchange[0].isalpha() and exchange[1].isdigit() and exchange[2].isalpha():
118
+ # return True
119
+ # return False
120
+ return True
121
+
122
+
123
+ def set_contact_vars(self):
124
+ """Contest Specific"""
125
+ self.contact["SNT"] = self.sent.text()
126
+ self.contact["RCV"] = self.receive.text()
127
+ self.contact["NR"] = self.other_2.text().upper()
128
+ self.contact["SentNr"] = self.other_1.text()
129
+
130
+
131
+ def predupe(self):
132
+ """called after callsign entered"""
133
+
134
+
135
+ def prefill(self):
136
+ """Fill sentnr"""
137
+ result = self.database.get_serial()
138
+ serial_nr = str(result.get("serial_nr", "1")).zfill(3)
139
+ if serial_nr == "None":
140
+ serial_nr = "001"
141
+
142
+ exchange = self.contest_settings.get("SentExchange", "").replace("#", serial_nr)
143
+ if len(self.other_1.text()) == 0:
144
+ self.other_1.setText(exchange)
145
+
146
+
147
+ def points(self):
148
+ """Calc point"""
149
+
150
+ # QSO Points: 1 point per QSO
151
+ # 1 additional point per QSO with PY3,PU3,ZZ3,PP3,etc
152
+
153
+ if self.contact.get("Call", "") in ["PY3", "PU3", "ZZ3", "PP3"]:
154
+ return 2
155
+ return 1
156
+
157
+
158
+ def show_mults(self):
159
+ """Return display string for mults"""
160
+ # Each grid field (first 2 letters of grid square) once per band
161
+
162
+ dx = 0
163
+
164
+ sql = (
165
+ "select count(DISTINCT(SUBSTR(NR,1,2) || ':' || Band)) as mult_count "
166
+ f"from dxlog where ContestNR = {self.database.current_contest} and typeof(NR) = 'text';"
167
+ )
168
+ result = self.database.exec_sql(sql)
169
+
170
+ if result:
171
+ dx = result.get("mult_count", 0)
172
+
173
+ return dx
174
+
175
+
176
+ def show_qso(self):
177
+ """Return qso count"""
178
+ result = self.database.fetch_qso_count()
179
+ if result:
180
+ return int(result.get("qsos", 0))
181
+ return 0
182
+
183
+
184
+ def calc_score(self):
185
+ """Return calculated score"""
186
+ # Multipliers: Each US State + DC once per mode
187
+ _points = get_points(self)
188
+ _mults = show_mults(self)
189
+ _power_mult = 1
190
+ return _points * _power_mult * _mults
191
+
192
+
193
+ def adif(self):
194
+ """Call the generate ADIF function"""
195
+ gen_adif(self, cabrillo_name)
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) 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
+
376
+ if themode in ("LSB", "USB", "AM"):
377
+ themode = "PH"
378
+ if themode in (
379
+ "FT8",
380
+ "FT4",
381
+ "RTTY",
382
+ "PSK31",
383
+ "FSK441",
384
+ "MSK144",
385
+ "JT65",
386
+ "JT9",
387
+ "Q65",
388
+ ):
389
+ themode = "DG"
390
+ freq = int(contact.get("Freq", "0")) / 1000
391
+
392
+ frequency = str(int(freq)).rjust(4)
393
+
394
+ loggeddate = the_date_and_time[:10]
395
+ loggedtime = the_date_and_time[11:13] + the_date_and_time[14:16]
396
+ output_cabrillo_line(
397
+ f"QSO: {frequency} {themode} {loggeddate} {loggedtime} "
398
+ f"{contact.get('StationPrefix', '').ljust(13)} "
399
+ # f"{str(contact.get('SNT', '')).ljust(3)} "
400
+ f"{str(contact.get('SentNr', '')).ljust(6)} "
401
+ f"{contact.get('Call', '').ljust(13)} "
402
+ # f"{str(contact.get('RCV', '')).ljust(3)} "
403
+ f"{str(contact.get('NR', '')).ljust(6)}",
404
+ "\r\n",
405
+ file_descriptor,
406
+ file_encoding,
407
+ )
408
+ output_cabrillo_line("END-OF-LOG:", "\r\n", file_descriptor, file_encoding)
409
+ self.show_message_box(f"Cabrillo saved to: {filename}")
410
+ except IOError as exception:
411
+ logger.critical("cabrillo: IO error: %s, writing to %s", exception, filename)
412
+ self.show_message_box(f"Error saving Cabrillo: {exception} {filename}")
413
+ return
414
+
415
+
416
+ def recalculate_mults(self):
417
+ """Recalculates multipliers after change in logged qso."""
418
+
419
+
420
+ def set_self(the_outie):
421
+ """..."""
422
+ globals()["ALTEREGO"] = the_outie
423
+
424
+
425
+ def ft8_handler(the_packet: dict):
426
+ """Process FT8 QSO packets
427
+ FT8
428
+ {
429
+ 'CALL': 'KE0OG',
430
+ 'GRIDSQUARE': 'DM10AT',
431
+ 'MODE': 'FT8',
432
+ 'RST_SENT': '',
433
+ 'RST_RCVD': '',
434
+ 'QSO_DATE': '20210329',
435
+ 'TIME_ON': '183213',
436
+ 'QSO_DATE_OFF': '20210329',
437
+ 'TIME_OFF': '183213',
438
+ 'BAND': '20M',
439
+ 'FREQ': '14.074754',
440
+ 'STATION_CALLSIGN': 'K6GTE',
441
+ 'MY_GRIDSQUARE': 'DM13AT',
442
+ 'CONTEST_ID': 'ARRL-FIELD-DAY',
443
+ 'SRX_STRING': '1D UT',
444
+ 'CLASS': '1D',
445
+ 'ARRL_SECT': 'UT'
446
+ }
447
+ FlDigi
448
+ {
449
+ 'FREQ': '7.029500',
450
+ 'CALL': 'DL2DSL',
451
+ 'MODE': 'RTTY',
452
+ 'NAME': 'BOB',
453
+ 'QSO_DATE': '20240904',
454
+ 'QSO_DATE_OFF': '20240904',
455
+ 'TIME_OFF': '212825',
456
+ 'TIME_ON': '212800',
457
+ 'RST_RCVD': '599',
458
+ 'RST_SENT': '599',
459
+ 'BAND': '40M',
460
+ 'COUNTRY': 'FED. REP. OF GERMANY',
461
+ 'CQZ': '14',
462
+ 'STX': '000',
463
+ 'STX_STRING': '1D ORG',
464
+ 'CLASS': '1D',
465
+ 'ARRL_SECT': 'DX',
466
+ 'TX_PWR': '0',
467
+ 'OPERATOR': 'K6GTE',
468
+ 'STATION_CALLSIGN': 'K6GTE',
469
+ 'MY_GRIDSQUARE': 'DM13AT',
470
+ 'MY_CITY': 'ANAHEIM, CA',
471
+ 'MY_STATE': 'CA'
472
+ }
473
+
474
+ """
475
+ # print(f"\n{the_packet=}\n")
476
+ if ALTEREGO is not None:
477
+ ALTEREGO.callsign.setText(the_packet.get("CALL"))
478
+ ALTEREGO.contact["Call"] = the_packet.get("CALL", "")
479
+ ALTEREGO.contact["SNT"] = ALTEREGO.sent.text()
480
+ ALTEREGO.contact["RCV"] = ALTEREGO.receive.text()
481
+ my_grid = the_packet.get("MY_GRIDSQUARE", "")
482
+ if my_grid:
483
+ if len(my_grid) > 4:
484
+ my_grid = my_grid[:4]
485
+ their_grid = the_packet.get("GRIDSQUARE", "")
486
+ if their_grid:
487
+ if len(their_grid) > 4:
488
+ their_grid = their_grid[:4]
489
+ ALTEREGO.contact["NR"] = their_grid
490
+ if the_packet.get("SUBMODE"):
491
+ ALTEREGO.contact["Mode"] = the_packet.get("SUBMODE", "ERR")
492
+ else:
493
+ ALTEREGO.contact["Mode"] = the_packet.get("MODE", "ERR")
494
+ ALTEREGO.contact["Freq"] = round(float(the_packet.get("FREQ", "0.0")) * 1000, 2)
495
+ ALTEREGO.contact["QSXFreq"] = round(
496
+ float(the_packet.get("FREQ", "0.0")) * 1000, 2
497
+ )
498
+ ALTEREGO.contact["Band"] = get_logged_band(
499
+ str(int(float(the_packet.get("FREQ", "0.0")) * 1000000))
500
+ )
501
+ # print(f"\n{ALTEREGO.contact=}\n")
502
+ ALTEREGO.other_1.setText(my_grid)
503
+ ALTEREGO.other_2.setText(their_grid)
504
+ ALTEREGO.save_contact()
505
+
506
+
507
+ def process_esm(self, new_focused_widget=None, with_enter=False):
508
+ """ESM State Machine"""
509
+
510
+ # self.pref["run_state"]
511
+
512
+ # -----===== Assigned F-Keys =====-----
513
+ # self.esm_dict["CQ"]
514
+ # self.esm_dict["EXCH"]
515
+ # self.esm_dict["QRZ"]
516
+ # self.esm_dict["AGN"]
517
+ # self.esm_dict["HISCALL"]
518
+ # self.esm_dict["MYCALL"]
519
+ # self.esm_dict["QSOB4"]
520
+
521
+ # ----==== text fields ====----
522
+ # self.callsign
523
+ # self.sent
524
+ # self.receive
525
+ # self.other_1
526
+ # self.other_2
527
+
528
+ if new_focused_widget is not None:
529
+ self.current_widget = self.inputs_dict.get(new_focused_widget)
530
+
531
+ # print(f"checking esm {self.current_widget=} {with_enter=} {self.pref.get("run_state")=}")
532
+
533
+ for a_button in [
534
+ self.esm_dict["CQ"],
535
+ self.esm_dict["EXCH"],
536
+ self.esm_dict["QRZ"],
537
+ self.esm_dict["AGN"],
538
+ self.esm_dict["HISCALL"],
539
+ self.esm_dict["MYCALL"],
540
+ self.esm_dict["QSOB4"],
541
+ ]:
542
+ if a_button is not None:
543
+ self.restore_button_color(a_button)
544
+
545
+ buttons_to_send = []
546
+
547
+ if self.pref.get("run_state"):
548
+ if self.current_widget == "callsign":
549
+ if len(self.callsign.text()) < 3:
550
+ self.make_button_green(self.esm_dict["CQ"])
551
+ buttons_to_send.append(self.esm_dict["CQ"])
552
+ elif len(self.callsign.text()) > 2:
553
+ self.make_button_green(self.esm_dict["HISCALL"])
554
+ self.make_button_green(self.esm_dict["EXCH"])
555
+ buttons_to_send.append(self.esm_dict["HISCALL"])
556
+ buttons_to_send.append(self.esm_dict["EXCH"])
557
+
558
+ elif self.current_widget in ["other_2"]:
559
+ if self.other_2.text() == "":
560
+ self.make_button_green(self.esm_dict["AGN"])
561
+ buttons_to_send.append(self.esm_dict["AGN"])
562
+ else:
563
+ self.make_button_green(self.esm_dict["QRZ"])
564
+ buttons_to_send.append(self.esm_dict["QRZ"])
565
+ buttons_to_send.append("LOGIT")
566
+
567
+ if with_enter is True and bool(len(buttons_to_send)):
568
+ for button in buttons_to_send:
569
+ if button:
570
+ if button == "LOGIT":
571
+ self.save_contact()
572
+ continue
573
+ self.process_function_key(button)
574
+ else:
575
+ if self.current_widget == "callsign":
576
+ if len(self.callsign.text()) > 2:
577
+ self.make_button_green(self.esm_dict["MYCALL"])
578
+ buttons_to_send.append(self.esm_dict["MYCALL"])
579
+
580
+ elif self.current_widget in ["other_2"]:
581
+ if self.other_2.text() == "":
582
+ self.make_button_green(self.esm_dict["AGN"])
583
+ buttons_to_send.append(self.esm_dict["AGN"])
584
+ else:
585
+ self.make_button_green(self.esm_dict["EXCH"])
586
+ buttons_to_send.append(self.esm_dict["EXCH"])
587
+ buttons_to_send.append("LOGIT")
588
+
589
+ if with_enter is True and bool(len(buttons_to_send)):
590
+ for button in buttons_to_send:
591
+ if button:
592
+ if button == "LOGIT":
593
+ self.save_contact()
594
+ continue
595
+ self.process_function_key(button)
596
+
597
+
598
+ def populate_history_info_line(self):
599
+ result = self.database.fetch_call_history(self.callsign.text())
600
+ if result:
601
+ self.history_info.setText(
602
+ f"{result.get('Call', '')}, {result.get('Name', '')}, {result.get('Loc1', '')}, {result.get('UserText','...')}"
603
+ )
604
+ else:
605
+ self.history_info.setText("")
606
+
607
+
608
+ def check_call_history(self):
609
+ """"""
610
+ result = self.database.fetch_call_history(self.callsign.text())
611
+ if result:
612
+ self.history_info.setText(f"{result.get('UserText','')}")
613
+ if self.other_2.text() == "":
614
+ self.other_2.setText(f"{result.get('Loc1', '')}")
615
+
616
+
617
+ # gridsquare
618
+ def get_mults(self):
619
+ """"""
620
+
621
+ mults = {}
622
+ mults["gridsquare"] = show_mults(self)
623
+ return mults
624
+
625
+
626
+ def just_points(self):
627
+ """"""
628
+ result = self.database.fetch_points()
629
+ if result is not None:
630
+ score = result.get("Points", "0")
631
+ if score is None:
632
+ score = "0"
633
+ return int(score)
634
+ return 0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: not1mm
3
- Version: 25.1.26.1
3
+ Version: 25.1.27.1
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
@@ -46,22 +46,22 @@ Requires-Dist: Levenshtein
46
46
  ![main screen](https://github.com/mbridak/not1mm/raw/master/pic/main.png)
47
47
 
48
48
  - [Not1MM](#not1mm)
49
- - [What and why is Not1MM](#what-and-why-is-not1mm)
50
- - [The elephant in the room](#the-elephant-in-the-room)
49
+ - [What and Why is Not1MM](#what-and-why-is-not1mm)
50
+ - [The Elephant in the Room](#the-elephant-in-the-room)
51
51
  - [The What](#the-what)
52
52
  - [Target Environment](#target-environment)
53
53
  - [The Why](#the-why)
54
- - [Current state](#current-state)
55
- - [Code maturity](#code-maturity)
54
+ - [Current State](#current-state)
55
+ - [Code Maturity](#code-maturity)
56
56
  - [Data and RTTY](#data-and-rtty)
57
- - [Other not so supported contests](#other-not-so-supported-contests)
57
+ - [Other not so Supported Contests](#other-not-so-supported-contests)
58
58
  - [Our Code Contributors ✨](#our-code-contributors-)
59
- - [List of should be working contests](#list-of-should-be-working-contests)
60
- - [Recent Changes (Polishing the Turd)](#recent-changes-polishing-the-turd)
59
+ - [List of Should be Working Contests](#list-of-should-be-working-contests)
60
+ - [Recent Changes](#recent-changes)
61
61
  - [Flatpak](#flatpak)
62
62
  - [Installation](#installation)
63
63
  - [Prerequisites](#prerequisites)
64
- - [Common installation recipes for Ubuntu and Fedora](#common-installation-recipes-for-ubuntu-and-fedora)
64
+ - [Common Installation Recipes for Ubuntu and Fedora](#common-installation-recipes-for-ubuntu-and-fedora)
65
65
  - [Ubuntu 22.04 LTS](#ubuntu-2204-lts)
66
66
  - [Ubuntu 23.04](#ubuntu-2304)
67
67
  - [Ubuntu 24.04 LTS](#ubuntu-2404-lts)
@@ -72,8 +72,8 @@ Requires-Dist: Levenshtein
72
72
  - [Python, PyPI, pip and pipx](#python-pypi-pip-and-pipx)
73
73
  - [Bootstrapping pipx](#bootstrapping-pipx)
74
74
  - [Installing with pipx](#installing-with-pipx)
75
- - [Installing from GitHub source](#installing-from-github-source)
76
- - [After the install](#after-the-install)
75
+ - [Installing from GitHub Source](#installing-from-github-source)
76
+ - [After the Install](#after-the-install)
77
77
  - [You may or may not get a warning message like](#you-may-or-may-not-get-a-warning-message-like)
78
78
  - [Or this fan favorite](#or-this-fan-favorite)
79
79
  - [Update your CTY and SCP files](#update-your-cty-and-scp-files)
@@ -136,9 +136,9 @@ Requires-Dist: Levenshtein
136
136
  - [The exchange](#the-exchange)
137
137
  - [RAEM](#raem)
138
138
 
139
- ## What and why is Not1MM
139
+ ## What and Why is Not1MM
140
140
 
141
- ### The elephant in the room
141
+ ### The Elephant in the Room
142
142
 
143
143
  Not1MM's interface is a blatant ripoff of N1MM. It is NOT N1MM and any problem
144
144
  you have with this software should in no way reflect on their software.
@@ -164,9 +164,9 @@ I'm a casual contester and could not find any contesting software for Linux that
164
164
  I wanted to use. There is [Tucnak](http://tucnak.nagano.cz/) which is very robust
165
165
  and mature. It just wasn't for me.
166
166
 
167
- ## Current state
167
+ ## Current State
168
168
 
169
- ### Code maturity
169
+ ### Code Maturity
170
170
 
171
171
  The current state is "**BETA**".
172
172
 
@@ -183,7 +183,7 @@ Day and ARRL VHF. Found it works better if you don't use FlDigi for making the Q
183
183
  Rather just using it as a RTTY modem and sending the text for it to send from Not1MM
184
184
  using the function keys or ESM.
185
185
 
186
- ### Other not so supported contests
186
+ ### Other not so Supported Contests
187
187
 
188
188
  Of note, state QSO parties. I haven't worked any yet. And no one has submitted a PR
189
189
  adding one... So there you go. In the near future I'll probably add California, guess
@@ -198,9 +198,9 @@ generated, 'cause I'm lazy, list of those who've submitted PR's.
198
198
  <img src="https://contrib.rocks/image?repo=mbridak/not1mm" alt="Avatar icons for code contributors." />
199
199
  </a>
200
200
 
201
- ## List of should be working contests
201
+ ## List of Should be Working Contests
202
202
 
203
- - General Logging (There are better general loggers like QLog, KLog, CQRLog)
203
+ - General Logging
204
204
  - 10 10 Fall CW
205
205
  - 10 10 Spring CW
206
206
  - 10 10 Summer Phone
@@ -223,6 +223,7 @@ generated, 'cause I'm lazy, list of those who've submitted PR's.
223
223
  - ICWC MST
224
224
  - Japan International DX CW, SSB
225
225
  - K1USN Slow Speed Test
226
+ - Labre RS Digi
226
227
  - LZ DX
227
228
  - NAQP CW, RTTY, SSB
228
229
  - Phone Weekly Test
@@ -233,8 +234,10 @@ generated, 'cause I'm lazy, list of those who've submitted PR's.
233
234
  - Weekly RTTY
234
235
  - Winter Field Day
235
236
 
236
- ## Recent Changes (Polishing the Turd)
237
+ ## Recent Changes
237
238
 
239
+ - [25-1-27-1] Add LABRE-RS Digi
240
+ - [25-1-27] Update pop up about updates...
238
241
  - [25-1-26] Add macros for MARK, SPOT, WIPE, RUN, SANDP.
239
242
  - [25-1-25-2] Add call history to REF CW and SSB.
240
243
  - [25-1-25-1] Fix:ratewindow failed to change stats when contest changed.
@@ -267,7 +270,7 @@ Not1MM requires:
267
270
 
268
271
  You should install these through your distribution's package manager before continuing.
269
272
 
270
- ### Common installation recipes for Ubuntu and Fedora
273
+ ### Common Installation Recipes for Ubuntu and Fedora
271
274
 
272
275
  I've taken the time to install some common Linux distributions into a VM and
273
276
  noted the minimum steps needed to install Not1MM.
@@ -405,7 +408,7 @@ pipx upgrade not1mm
405
408
  <details>
406
409
  <summary><b>Installing from GitHub source.</b></summary>
407
410
 
408
- ### Installing from GitHub source
411
+ ### Installing from GitHub Source
409
412
 
410
413
  Since this is packaged for PyPI, if you want to work on your own source branch,
411
414
  after cloning from github you would:
@@ -436,7 +439,7 @@ not1mm
436
439
 
437
440
  </details>
438
441
 
439
- ## After the install
442
+ ## After the Install
440
443
 
441
444
  You can now open a new terminal and type `not1mm`. On it's first run, it may or
442
445
  may not install a lovely non AI generated icon, which you can later click on to
@@ -1,5 +1,5 @@
1
1
  not1mm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- not1mm/__main__.py,sha256=FWmlZTC3tuBkQvowFLO7hhC9aI_aZNb3c12X8RZ0N0M,147149
2
+ not1mm/__main__.py,sha256=g0o9K_koq2alfJffLvSYAEB_jjRetCfy1ZyjsSe6-vw,147224
3
3
  not1mm/bandmap.py,sha256=BpaR8ENrDJyyPBDeNiHrNYGPU6vRNMoCl2J8HBx4FtE,31137
4
4
  not1mm/checkwindow.py,sha256=VFAcKYTcoWhmIf91chwY6tyao9FQMWPiUkgDDkkWaog,9670
5
5
  not1mm/fsutils.py,sha256=ukHKxKTeNKxKwqRaJjtzRShL4X5Xl0jRBbADyy3Ifp8,1701
@@ -33,7 +33,7 @@ not1mm/data/k6gte.not1mm-64.png,sha256=6ku45Gq1g5ezh04F07osoKRtanb3e4kbx5XdIEh3N
33
33
  not1mm/data/logwindow.ui,sha256=f7vULj96tHIQuR1nJMyvPHHcmVgzkhv9D1isyojsnFU,1458
34
34
  not1mm/data/logwindowx.ui,sha256=CwpI-h7cI1yqyldH9quKftsdHL5lTyL9ABOcf80nfqc,1632
35
35
  not1mm/data/main.ui,sha256=LEziByl_8nNTBYR0Z-6CgqDcMbsvQVgfWOfF-B9z3MQ,63537
36
- not1mm/data/new_contest.ui,sha256=Sc8HquH7BK0bmkypeK_HbfhArE6yaw02WONOUlRdmuA,23953
36
+ not1mm/data/new_contest.ui,sha256=UQNSl28_PrtVA6to2uKBCZTa7LCOh5peGOmuxIWHBw8,24063
37
37
  not1mm/data/not1mm.html,sha256=c9-mfjMwDt4f5pySUruz2gREW33CQ2_rCddM2z5CZQo,23273
38
38
  not1mm/data/opon.ui,sha256=QDicqAk2lORG2UWsHa6jHlsGn6uzrrI2R4HSAocpPes,2258
39
39
  not1mm/data/pickcontest.ui,sha256=4hPBszCglObThx_eIWtmK9CEcbr7WBjbB1rKZdI-o3I,1707
@@ -116,7 +116,7 @@ not1mm/lib/plugin_common.py,sha256=M5reDYM-v5IjAa2yTROvZTeTDkXYHb3U52W9mc9GxwA,1
116
116
  not1mm/lib/select_contest.py,sha256=WsptLuwkouIHeocJL3oZ6-eUfEnhpwdc-x7eMZ_TIVM,359
117
117
  not1mm/lib/settings.py,sha256=j5lIMLHJ-eqIaVr_QhI82gkbOl17_C-5suRkWbHYET8,14717
118
118
  not1mm/lib/super_check_partial.py,sha256=hwT2NRwobu0PLDyw6ltmbmcAtGBD02CKGFbgGWjXMqA,2334
119
- not1mm/lib/version.py,sha256=yW91dn5kBhj1ZqiN4aKZqlz736_lgaaCSHfNvourXrg,50
119
+ not1mm/lib/version.py,sha256=vfggR4aagLgq0Z-62g_sIFuPURJDRsfYYSPS1gT0eMc,50
120
120
  not1mm/lib/versiontest.py,sha256=8vDNptuBBunn-1IGkjNaquehqBYUJyjrPSF8Igmd4_Y,1286
121
121
  not1mm/plugins/10_10_fall_cw.py,sha256=5QUyGMvGBC-HxcY_z9QbfuxSg3f7p6C9K4qhTxgZE7k,14719
122
122
  not1mm/plugins/10_10_spring_cw.py,sha256=XjYFM263WYyG6nVQzPObW4YC7Z9L93rixSOcVsxPvH4,14722
@@ -154,6 +154,7 @@ not1mm/plugins/icwc_mst.py,sha256=XfaIRIj0BxWvpWk2nmy_dMseVuKVOh-_m3UcIGOy6wI,16
154
154
  not1mm/plugins/jidx_cw.py,sha256=gSScw21ac2Rpdd7jspgh5gnH9JdiR8h3YOa-41B_T94,15881
155
155
  not1mm/plugins/jidx_ph.py,sha256=0E5xHs0WXh-x2Z6UC2PGqmLdIkn-jWbENOeLopr7rys,14830
156
156
  not1mm/plugins/k1usn_sst.py,sha256=WfRF-emC52IIjOEddGmEQ_gWlMqoBbhCQ7S56nAZ4M8,17134
157
+ not1mm/plugins/labre_rs_digi.py,sha256=ueytVNrg2mkTEouq9dkWI90EZMgtDLCZ1TWNeXB-iyA,19975
157
158
  not1mm/plugins/lz-dx.py,sha256=HLU7FopHryEHPtAH2-mopeWSY6E_uwNgh8_sM27E2F0,19824
158
159
  not1mm/plugins/naqp_cw.py,sha256=Aq9bRn9uRm6PXd1WVckZJ4GTbiBcPFnPRQAydEVmeAs,18897
159
160
  not1mm/plugins/naqp_rtty.py,sha256=JbjsY9DvVexXdzoPE4k9zSmcYNEMQpB9lrxdRxl_ldc,22639
@@ -165,9 +166,9 @@ not1mm/plugins/ref_ssb.py,sha256=Z_XmMpYKcI5dZh4TQqvQDcz-cLpMzpDEKBnb5iHeBLQ,215
165
166
  not1mm/plugins/stew_perry_topband.py,sha256=D1hekmMbx-i4BhaP2uzOK3OzaVVMMdgcN3RmfweNqHo,15341
166
167
  not1mm/plugins/weekly_rtty.py,sha256=rdlIrsxBeuj-RQc5OStVNF7sGCtBK5t6inN5Z7DI4tw,20066
167
168
  not1mm/plugins/winter_field_day.py,sha256=JK4r1vfxs7aADR7ZYbjZniz3f5s3_ipSQDZ0GRNWC7I,15222
168
- not1mm-25.1.26.1.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
169
- not1mm-25.1.26.1.dist-info/METADATA,sha256=edpQnNg4zGP8fZyoOUN3CyqnfWk8I9ExkNs-ejZHDaw,36066
170
- not1mm-25.1.26.1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
171
- not1mm-25.1.26.1.dist-info/entry_points.txt,sha256=pMcZk_0dxFgLkcUkF0Q874ojpwOmF3OL6EKw9LgvocM,47
172
- not1mm-25.1.26.1.dist-info/top_level.txt,sha256=0YmTxEcDzQlzXub-lXASvoLpg_mt1c2thb5cVkDf5J4,7
173
- not1mm-25.1.26.1.dist-info/RECORD,,
169
+ not1mm-25.1.27.1.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
170
+ not1mm-25.1.27.1.dist-info/METADATA,sha256=Y28G2qoTsLkqDuE4h-BWmfZBZd9mhQFDQ9ex9gBw7b8,36037
171
+ not1mm-25.1.27.1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
172
+ not1mm-25.1.27.1.dist-info/entry_points.txt,sha256=pMcZk_0dxFgLkcUkF0Q874ojpwOmF3OL6EKw9LgvocM,47
173
+ not1mm-25.1.27.1.dist-info/top_level.txt,sha256=0YmTxEcDzQlzXub-lXASvoLpg_mt1c2thb5cVkDf5J4,7
174
+ not1mm-25.1.27.1.dist-info/RECORD,,