not1mm 25.5.26.1__py3-none-any.whl → 25.6.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.
Files changed (50) hide show
  1. not1mm/__main__.py +66 -43
  2. not1mm/data/MASTER.SCP +2636 -2654
  3. not1mm/data/cty.json +1 -1
  4. not1mm/data/new_contest.ui +5 -0
  5. not1mm/lib/database.py +14 -45
  6. not1mm/lib/edit_station.py +5 -5
  7. not1mm/lib/plugin_common.py +21 -0
  8. not1mm/lib/super_check_partial.py +28 -12
  9. not1mm/lib/version.py +1 -1
  10. not1mm/logwindow.py +4 -0
  11. not1mm/plugins/ari_dx.py +11 -11
  12. not1mm/plugins/arrl_160m.py +13 -13
  13. not1mm/plugins/arrl_dx_cw.py +47 -47
  14. not1mm/plugins/arrl_dx_ssb.py +48 -48
  15. not1mm/plugins/canada_day.py +6 -6
  16. not1mm/plugins/cq_160_cw.py +16 -16
  17. not1mm/plugins/cq_160_ssb.py +16 -16
  18. not1mm/plugins/cq_wpx_cw.py +28 -28
  19. not1mm/plugins/cq_wpx_rtty.py +20 -20
  20. not1mm/plugins/cq_wpx_ssb.py +28 -28
  21. not1mm/plugins/cq_ww_cw.py +19 -19
  22. not1mm/plugins/cq_ww_rtty.py +14 -14
  23. not1mm/plugins/cq_ww_ssb.py +18 -18
  24. not1mm/plugins/ea_majistad_cw.py +6 -6
  25. not1mm/plugins/ea_majistad_ssb.py +6 -6
  26. not1mm/plugins/ea_rtty.py +6 -6
  27. not1mm/plugins/es_field_day.py +604 -0
  28. not1mm/plugins/es_open.py +37 -26
  29. not1mm/plugins/helvetia.py +12 -12
  30. not1mm/plugins/iaru_hf.py +3 -3
  31. not1mm/plugins/jidx_cw.py +4 -4
  32. not1mm/plugins/jidx_ph.py +4 -4
  33. not1mm/plugins/lz-dx.py +12 -12
  34. not1mm/plugins/naqp_cw.py +6 -6
  35. not1mm/plugins/naqp_rtty.py +6 -6
  36. not1mm/plugins/naqp_ssb.py +6 -6
  37. not1mm/plugins/phone_weekly_test.py +6 -6
  38. not1mm/plugins/ref_cw.py +8 -8
  39. not1mm/plugins/ref_ssb.py +8 -8
  40. not1mm/plugins/sac_cw.py +9 -9
  41. not1mm/plugins/sac_ssb.py +11 -11
  42. not1mm/plugins/spdx.py +7 -7
  43. not1mm/plugins/ukeidx.py +10 -10
  44. not1mm/statistics.py +1 -0
  45. {not1mm-25.5.26.1.dist-info → not1mm-25.6.1.dist-info}/METADATA +7 -277
  46. {not1mm-25.5.26.1.dist-info → not1mm-25.6.1.dist-info}/RECORD +50 -49
  47. {not1mm-25.5.26.1.dist-info → not1mm-25.6.1.dist-info}/WHEEL +1 -1
  48. {not1mm-25.5.26.1.dist-info → not1mm-25.6.1.dist-info}/entry_points.txt +0 -0
  49. {not1mm-25.5.26.1.dist-info → not1mm-25.6.1.dist-info}/licenses/LICENSE +0 -0
  50. {not1mm-25.5.26.1.dist-info → not1mm-25.6.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,604 @@
1
+ """ """
2
+
3
+ import logging
4
+ import platform
5
+ from datetime import datetime
6
+ from datetime import timedelta
7
+ from datetime import timezone
8
+
9
+ from pathlib import Path
10
+
11
+ from PyQt6 import QtWidgets
12
+
13
+ from not1mm.lib.plugin_common import gen_adif, get_points, get_station_state_code, get_station_arrlsection_code
14
+
15
+ from not1mm.lib.ham_utility import calculate_wpx_prefix
16
+ from not1mm.lib.version import __version__
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+ EXCHANGE_HINT = "#"
21
+
22
+ name = "ES FIELD DAY"
23
+ cabrillo_name = "ES-FIELD-DAY"
24
+ mode = "BOTH" # CW SSB BOTH RTTY
25
+
26
+ columns = [
27
+ "YYYY-MM-DD HH:MM:SS",
28
+ "Call",
29
+ "Freq",
30
+ "Mode",
31
+ "Snt",
32
+ "Rcv",
33
+ "SentNr",
34
+ "RcvNr",
35
+ "PTS",
36
+ ]
37
+
38
+ advance_on_space = [True, True, True, True, True]
39
+
40
+ # 5 Contest specific dupe check.
41
+ dupe_type = 5
42
+
43
+ estonian_regions = [
44
+ "HM",
45
+ "HR",
46
+ "IV",
47
+ "JG",
48
+ "JR",
49
+ "LN",
50
+ "LV",
51
+ "PL",
52
+ "PU",
53
+ "RP",
54
+ "SR",
55
+ "TA",
56
+ "TL",
57
+ "VC",
58
+ "VO",
59
+ "VP"
60
+ ]
61
+
62
+ def specific_contest_check_dupe(self, call):
63
+ """"""
64
+ # get mode from radio state
65
+ mode = self.radio_state.get("mode", "")
66
+ """Dupe checking specific to just this contest."""
67
+ # constant to split the contest - correct ES Open Contest length is 4 hours
68
+ contest_length_in_minutes = 90
69
+ split_contest_by_minutes = 30
70
+
71
+ period_count = int(contest_length_in_minutes / split_contest_by_minutes)
72
+
73
+ # think about generic solution by splitting the contest to n different periods
74
+ start_date_init = self.contest_settings.get("StartDate", "")
75
+ start_date_init_date = datetime.strptime(start_date_init, "%Y-%m-%d %H:%M:%S")
76
+
77
+ # Create time periods dynamically based on period count
78
+ time_periods = []
79
+ for i in range(period_count):
80
+ minutes_to_add = split_contest_by_minutes * (i + 1)
81
+ time_period = start_date_init_date + timedelta(minutes=minutes_to_add)
82
+ time_periods.append(time_period)
83
+
84
+ # Assign to variables for backwards compatibility
85
+ time_period_1 = time_periods[0] if len(time_periods) > 0 else None
86
+ time_period_2 = time_periods[1] if len(time_periods) > 1 else None
87
+ time_period_3 = time_periods[2] if len(time_periods) > 2 else None
88
+
89
+ # get current time in UTC
90
+ iso_current_time = datetime.now(timezone.utc)
91
+ current_time = iso_current_time.replace(tzinfo=None)
92
+
93
+ result = {}
94
+ result["isdupe"] = False
95
+
96
+ if current_time < time_period_1 and current_time >= start_date_init_date:
97
+
98
+ result = self.database.check_dupe_on_period_mode(
99
+ call,
100
+ self.contact.get("Band", ""),
101
+ mode,
102
+ start_date_init_date,
103
+ time_period_1.strftime("%Y-%m-%d %H:%M:%S"),
104
+ )
105
+
106
+ if current_time < time_period_2 and current_time >= time_period_1:
107
+
108
+ result = self.database.check_dupe_on_period_mode(
109
+ call,
110
+ self.contact.get("Band", ""),
111
+ mode,
112
+ time_period_1.strftime("%Y-%m-%d %H:%M:%S"),
113
+ time_period_2.strftime("%Y-%m-%d %H:%M:%S"),
114
+ )
115
+
116
+ if current_time < time_period_3 and current_time >= time_period_2:
117
+
118
+ result = self.database.check_dupe_on_period_mode(
119
+ call,
120
+ self.contact.get("Band", ""),
121
+ mode,
122
+ time_period_2.strftime("%Y-%m-%d %H:%M:%S"),
123
+ time_period_3.strftime("%Y-%m-%d %H:%M:%S"),
124
+ )
125
+
126
+ # just for band and mode if outside of time period
127
+ else:
128
+ result = self.database.check_dupe_on_band_mode(
129
+ call, self.contact.get("Band", ""), mode
130
+ )
131
+
132
+ return result
133
+
134
+ def init_contest(self):
135
+ """setup plugin"""
136
+ set_tab_next(self)
137
+ set_tab_prev(self)
138
+ interface(self)
139
+ self.next_field = self.other_2
140
+
141
+
142
+ def interface(self):
143
+ """Setup user interface"""
144
+ """Setup user interface"""
145
+ self.field1.show()
146
+ self.field2.show()
147
+ self.field3.show()
148
+ self.field4.show()
149
+ self.other_label.setText("Sent")
150
+ self.field3.setAccessibleName("Sent")
151
+ self.exch_label.setText("SN")
152
+ self.field4.setAccessibleName("SN")
153
+
154
+
155
+ def reset_label(self):
156
+ """reset label after field cleared"""
157
+
158
+
159
+ def set_tab_next(self):
160
+ """Set TAB Advances"""
161
+ self.tab_next = {
162
+ self.callsign: self.other_1,
163
+ self.sent: self.other_1,
164
+ self.receive: self.other_1,
165
+ self.other_1: self.other_2,
166
+ self.other_2: self.callsign,
167
+ }
168
+
169
+
170
+ def set_tab_prev(self):
171
+ """Set TAB Advances"""
172
+ self.tab_prev = {
173
+ self.callsign: self.other_2,
174
+ self.sent: self.callsign,
175
+ self.receive: self.callsign,
176
+ self.other_1: self.callsign,
177
+ self.other_2: self.other_1,
178
+ }
179
+
180
+
181
+ def set_contact_vars(self):
182
+ """Contest Specific"""
183
+ self.contact["SNT"] = self.sent.text()
184
+ self.contact["RCV"] = self.receive.text()
185
+ self.contact["SentNr"] = self.other_1.text().upper()
186
+ self.contact["NR"] = self.other_2.text().upper()
187
+
188
+ self.contact["IsMultiplier1"] = 0
189
+ self.contact["IsMultiplier2"] = 0
190
+
191
+
192
+ def predupe(self):
193
+ """called after callsign entered"""
194
+
195
+
196
+ def prefill(self):
197
+ """Fill SentNR"""
198
+
199
+ sent_sxchange_setting = self.contest_settings.get("SentExchange", "")
200
+ if sent_sxchange_setting.strip() == "#":
201
+ result = self.database.get_serial()
202
+ serial_nr = str(result.get("serial_nr", "1")).zfill(3)
203
+ # get station region code from setup ARRLSection field
204
+ serial_nr = serial_nr + " " + get_station_state_code(self)
205
+
206
+ if serial_nr == "None":
207
+ serial_nr = "001"
208
+ if len(self.other_1.text()) == 0:
209
+ self.other_1.setText(serial_nr)
210
+ else:
211
+ self.other_1.setText(sent_sxchange_setting)
212
+
213
+
214
+ def points(self):
215
+ """ """
216
+ if self.contact_is_dupe > 0:
217
+ return 0
218
+
219
+ # get received number and region code
220
+
221
+ check_call = self.contact.get("Call", "")
222
+ # all stations with /p give 3 points
223
+ if "/p" in check_call.lower():
224
+ return 3
225
+ # all stations with /qrp give 5 points
226
+ elif "/qrp" in check_call.lower():
227
+ return 5
228
+ else:
229
+ return 1
230
+
231
+ def show_mults(self, rtc=None):
232
+ """Return display string for mults"""
233
+
234
+ # implement here multipliers checks
235
+ # get received number and region code
236
+
237
+ call_result = str(self.contact.get("NR", ""))
238
+ # create placeholders
239
+ placeholders = ','.join(['?'] * len(estonian_regions))
240
+ # main query to filter by regions
241
+ query = f"SELECT count(distinct(SUBSTR(NR, -2)) || ':' || Band || ':' || Mode) as mults from DXLOG where ContestNR = {self.pref.get('contest', '1')} AND CountryPrefix = 'ES' AND NR GLOB '*[A-Z]*' AND substr(NR,-2) IN ({placeholders});"
242
+ # apply params
243
+ params = estonian_regions
244
+ # run query
245
+ result = self.database.exec_sql_params_mult(query, params)
246
+ if result:
247
+ mult_count = result.get("mults", 0)
248
+ return mult_count
249
+ return 0
250
+
251
+ def show_qso(self):
252
+ """Return qso count"""
253
+ result = self.database.fetch_qso_count()
254
+ if result:
255
+ return int(result.get("qsos", 0))
256
+ return 0
257
+
258
+
259
+ def calc_score(self):
260
+ """Return calculated score"""
261
+ result = self.database.fetch_points()
262
+ if result is not None:
263
+ score = result.get("Points", "0")
264
+ if score is None:
265
+ score = "0"
266
+ contest_points = int(score)
267
+ mults = show_mults(self)
268
+ return contest_points * (mults + 1)
269
+ return 0
270
+
271
+
272
+ def recalculate_mults(self):
273
+ """Recalculates multipliers after change in logged qso."""
274
+
275
+
276
+ def adif(self):
277
+ """Call the generate ADIF function"""
278
+ gen_adif(self, cabrillo_name, "ES OPEN")
279
+
280
+
281
+ def output_cabrillo_line(line_to_output, ending, file_descriptor, file_encoding):
282
+ """"""
283
+ print(
284
+ line_to_output.encode(file_encoding, errors="ignore").decode(),
285
+ end=ending,
286
+ file=file_descriptor,
287
+ )
288
+
289
+
290
+ def cabrillo(self, file_encoding):
291
+ """Generates Cabrillo file. Maybe."""
292
+ # https://www.cqwpx.com/cabrillo.htm
293
+ logger.debug("******Cabrillo*****")
294
+ logger.debug("Station: %s", f"{self.station}")
295
+ logger.debug("Contest: %s", f"{self.contest_settings}")
296
+ now = datetime.now()
297
+ date_time = now.strftime("%Y-%m-%d_%H-%M-%S")
298
+ filename = (
299
+ str(Path.home())
300
+ + "/"
301
+ + f"{self.station.get('Call', '').upper()}_{cabrillo_name}_{date_time}.log"
302
+ )
303
+ logger.debug("%s", filename)
304
+ log = self.database.fetch_all_contacts_asc()
305
+ try:
306
+ with open(filename, "w", encoding=file_encoding, newline="") as file_descriptor:
307
+ output_cabrillo_line(
308
+ "START-OF-LOG: 3.0",
309
+ "\r\n",
310
+ file_descriptor,
311
+ file_encoding,
312
+ )
313
+ output_cabrillo_line(
314
+ f"CREATED-BY: Not1MM v{__version__}",
315
+ "\r\n",
316
+ file_descriptor,
317
+ file_encoding,
318
+ )
319
+ output_cabrillo_line(
320
+ f"CONTEST: {cabrillo_name}",
321
+ "\r\n",
322
+ file_descriptor,
323
+ file_encoding,
324
+ )
325
+ if self.station.get("Club", ""):
326
+ output_cabrillo_line(
327
+ f"CLUB: {self.station.get('Club', '').upper()}",
328
+ "\r\n",
329
+ file_descriptor,
330
+ file_encoding,
331
+ )
332
+ output_cabrillo_line(
333
+ f"CALLSIGN: {self.station.get('Call','')}",
334
+ "\r\n",
335
+ file_descriptor,
336
+ file_encoding,
337
+ )
338
+ output_cabrillo_line(
339
+ f"LOCATION: {self.station.get('ARRLSection', '')}",
340
+ "\r\n",
341
+ file_descriptor,
342
+ file_encoding,
343
+ )
344
+ output_cabrillo_line(
345
+ f"CATEGORY-OPERATOR: {self.contest_settings.get('OperatorCategory','')}",
346
+ "\r\n",
347
+ file_descriptor,
348
+ file_encoding,
349
+ )
350
+ output_cabrillo_line(
351
+ f"CATEGORY-ASSISTED: {self.contest_settings.get('AssistedCategory','')}",
352
+ "\r\n",
353
+ file_descriptor,
354
+ file_encoding,
355
+ )
356
+ output_cabrillo_line(
357
+ f"CATEGORY-BAND: {self.contest_settings.get('BandCategory','')}",
358
+ "\r\n",
359
+ file_descriptor,
360
+ file_encoding,
361
+ )
362
+ mode = self.contest_settings.get("ModeCategory", "")
363
+ if mode in ["SSB+CW", "SSB+CW+DIGITAL"]:
364
+ mode = "MIXED"
365
+ output_cabrillo_line(
366
+ f"CATEGORY-MODE: {mode}",
367
+ "\r\n",
368
+ file_descriptor,
369
+ file_encoding,
370
+ )
371
+ output_cabrillo_line(
372
+ f"CATEGORY-TRANSMITTER: {self.contest_settings.get('TransmitterCategory','')}",
373
+ "\r\n",
374
+ file_descriptor,
375
+ file_encoding,
376
+ )
377
+ if self.contest_settings.get("OverlayCategory", "") != "N/A":
378
+ output_cabrillo_line(
379
+ f"CATEGORY-OVERLAY: {self.contest_settings.get('OverlayCategory','')}",
380
+ "\r\n",
381
+ file_descriptor,
382
+ file_encoding,
383
+ )
384
+ output_cabrillo_line(
385
+ f"GRID-LOCATOR: {self.station.get('GridSquare','')}",
386
+ "\r\n",
387
+ file_descriptor,
388
+ file_encoding,
389
+ )
390
+ output_cabrillo_line(
391
+ f"CATEGORY-POWER: {self.contest_settings.get('PowerCategory','')}",
392
+ "\r\n",
393
+ file_descriptor,
394
+ file_encoding,
395
+ )
396
+
397
+ output_cabrillo_line(
398
+ f"CLAIMED-SCORE: {calc_score(self)}",
399
+ "\r\n",
400
+ file_descriptor,
401
+ file_encoding,
402
+ )
403
+ ops = f"@{self.station.get('Call','')}"
404
+ list_of_ops = self.database.get_ops()
405
+ for op in list_of_ops:
406
+ ops += f", {op.get('Operator', '')}"
407
+ output_cabrillo_line(
408
+ f"OPERATORS: {ops}",
409
+ "\r\n",
410
+ file_descriptor,
411
+ file_encoding,
412
+ )
413
+ output_cabrillo_line(
414
+ f"NAME: {self.station.get('Name', '')}",
415
+ "\r\n",
416
+ file_descriptor,
417
+ file_encoding,
418
+ )
419
+ output_cabrillo_line(
420
+ f"ADDRESS: {self.station.get('Street1', '')}",
421
+ "\r\n",
422
+ file_descriptor,
423
+ file_encoding,
424
+ )
425
+ output_cabrillo_line(
426
+ f"ADDRESS-CITY: {self.station.get('City', '')}",
427
+ "\r\n",
428
+ file_descriptor,
429
+ file_encoding,
430
+ )
431
+ output_cabrillo_line(
432
+ f"ADDRESS-STATE-PROVINCE: {self.station.get('State', '')}",
433
+ "\r\n",
434
+ file_descriptor,
435
+ file_encoding,
436
+ )
437
+ output_cabrillo_line(
438
+ f"ADDRESS-POSTALCODE: {self.station.get('Zip', '')}",
439
+ "\r\n",
440
+ file_descriptor,
441
+ file_encoding,
442
+ )
443
+ output_cabrillo_line(
444
+ f"ADDRESS-COUNTRY: {self.station.get('Country', '')}",
445
+ "\r\n",
446
+ file_descriptor,
447
+ file_encoding,
448
+ )
449
+ output_cabrillo_line(
450
+ f"EMAIL: {self.station.get('Email', '')}",
451
+ "\r\n",
452
+ file_descriptor,
453
+ file_encoding,
454
+ )
455
+ for contact in log:
456
+ the_date_and_time = contact.get("TS", "")
457
+ themode = contact.get("Mode", "")
458
+ if themode == "LSB" or themode == "USB":
459
+ themode = "PH"
460
+ frequency = str(int(contact.get("Freq", "0"))).rjust(5)
461
+
462
+ loggeddate = the_date_and_time[:10]
463
+ loggedtime = the_date_and_time[11:13] + the_date_and_time[14:16]
464
+ output_cabrillo_line(
465
+ f"QSO: {frequency} {themode} {loggeddate} {loggedtime} "
466
+ f"{contact.get('StationPrefix', '').ljust(13)} "
467
+ f"{str(contact.get('SNT', '')).ljust(3)} "
468
+ f"{str(contact.get('SentNr', '')).ljust(6)} "
469
+ f"{contact.get('Call', '').ljust(13)} "
470
+ f"{str(contact.get('RCV', '')).ljust(3)} "
471
+ f"{str(contact.get('NR', '')).ljust(6)}",
472
+ "\r\n",
473
+ file_descriptor,
474
+ file_encoding,
475
+ )
476
+ output_cabrillo_line("END-OF-LOG:", "\r\n", file_descriptor, file_encoding)
477
+ self.show_message_box(f"Cabrillo saved to: {filename}")
478
+ except IOError as exception:
479
+ logger.critical("cabrillo: IO error: %s, writing to %s", exception, filename)
480
+ self.show_message_box(f"Error saving Cabrillo: {exception} {filename}")
481
+ return
482
+
483
+
484
+ # def populate_history_info_line(self):
485
+ # result = self.database.fetch_call_history(self.callsign.text())
486
+ # if result:
487
+ # self.history_info.setText(
488
+ # f"{result.get('Call', '')}, {result.get('Exch1', '')}, {result.get('UserText','...')}"
489
+ # )
490
+ # else:
491
+ # self.history_info.setText("")
492
+
493
+
494
+ # def check_call_history(self):
495
+ # """"""
496
+ # result = self.database.fetch_call_history(self.callsign.text())
497
+ # print(f"{result=}")
498
+ # if result:
499
+ # self.history_info.setText(f"{result.get('UserText','')}")
500
+ # if self.other_2.text() == "":
501
+ # self.other_2.setText(f"{result.get('Exch1', '')}")
502
+
503
+
504
+ def process_esm(self, new_focused_widget=None, with_enter=False):
505
+ """ESM State Machine"""
506
+
507
+ # self.pref["run_state"]
508
+
509
+ # -----===== Assigned F-Keys =====-----
510
+ # self.esm_dict["CQ"]
511
+ # self.esm_dict["EXCH"]
512
+ # self.esm_dict["QRZ"]
513
+ # self.esm_dict["AGN"]
514
+ # self.esm_dict["HISCALL"]
515
+ # self.esm_dict["MYCALL"]
516
+ # self.esm_dict["QSOB4"]
517
+
518
+ # ----==== text fields ====----
519
+ # self.callsign
520
+ # self.sent
521
+ # self.receive
522
+ # self.other_1
523
+ # self.other_2
524
+
525
+ if new_focused_widget is not None:
526
+ self.current_widget = self.inputs_dict.get(new_focused_widget)
527
+
528
+ # print(f"checking esm {self.current_widget=} {with_enter=} {self.pref.get("run_state")=}")
529
+
530
+ for a_button in [
531
+ self.esm_dict["CQ"],
532
+ self.esm_dict["EXCH"],
533
+ self.esm_dict["QRZ"],
534
+ self.esm_dict["AGN"],
535
+ self.esm_dict["HISCALL"],
536
+ self.esm_dict["MYCALL"],
537
+ self.esm_dict["QSOB4"],
538
+ ]:
539
+ if a_button is not None:
540
+ self.restore_button_color(a_button)
541
+
542
+ buttons_to_send = []
543
+
544
+ if self.pref.get("run_state"):
545
+ if self.current_widget == "callsign":
546
+ if len(self.callsign.text()) < 3:
547
+ self.make_button_green(self.esm_dict["CQ"])
548
+ buttons_to_send.append(self.esm_dict["CQ"])
549
+ elif len(self.callsign.text()) > 2:
550
+ self.make_button_green(self.esm_dict["HISCALL"])
551
+ self.make_button_green(self.esm_dict["EXCH"])
552
+ buttons_to_send.append(self.esm_dict["HISCALL"])
553
+ buttons_to_send.append(self.esm_dict["EXCH"])
554
+
555
+ elif self.current_widget == "other_2":
556
+ if self.other_2.text() == "":
557
+ self.make_button_green(self.esm_dict["AGN"])
558
+ buttons_to_send.append(self.esm_dict["AGN"])
559
+ else:
560
+ self.make_button_green(self.esm_dict["QRZ"])
561
+ buttons_to_send.append(self.esm_dict["QRZ"])
562
+ buttons_to_send.append("LOGIT")
563
+
564
+ if with_enter is True and bool(len(buttons_to_send)):
565
+ for button in buttons_to_send:
566
+ if button:
567
+ if button == "LOGIT":
568
+ self.save_contact()
569
+ continue
570
+ self.process_function_key(button)
571
+ else:
572
+ if self.current_widget == "callsign":
573
+ if len(self.callsign.text()) > 2:
574
+ self.make_button_green(self.esm_dict["MYCALL"])
575
+ buttons_to_send.append(self.esm_dict["MYCALL"])
576
+
577
+ elif self.current_widget == "other_2":
578
+ if self.other_2.text() == "":
579
+ self.make_button_green(self.esm_dict["AGN"])
580
+ buttons_to_send.append(self.esm_dict["AGN"])
581
+ else:
582
+ self.make_button_green(self.esm_dict["EXCH"])
583
+ buttons_to_send.append(self.esm_dict["EXCH"])
584
+ buttons_to_send.append("LOGIT")
585
+
586
+ if with_enter is True and bool(len(buttons_to_send)):
587
+ for button in buttons_to_send:
588
+ if button:
589
+ if button == "LOGIT":
590
+ self.save_contact()
591
+ continue
592
+ self.process_function_key(button)
593
+
594
+
595
+ def get_mults(self):
596
+ """Get mults for RTC XML"""
597
+ mults = {}
598
+ mults["country"], mults["state"] = show_mults(self, rtc=True)
599
+ return mults
600
+
601
+
602
+ def just_points(self):
603
+ """Get points for RTC XML"""
604
+ return get_points(self)