not1mm 25.4.13__py3-none-any.whl → 25.4.14__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
@@ -3705,6 +3705,11 @@ class MainWindow(QtWidgets.QMainWindow):
3705
3705
  result = self.database.check_dupe_on_band_mode(call, band, mode)
3706
3706
  if self.contest.dupe_type == 4:
3707
3707
  result = {"isdupe": False}
3708
+ if self.contest.dupe_type == 5:
3709
+ result = {"isdupe": False} # in case contest has no function.
3710
+ if hasattr(self.contest, "check_dupe"):
3711
+ result = self.contest.specific_contest_check_dupe(self, call)
3712
+
3708
3713
  debugline = f"{result}"
3709
3714
  logger.debug("%s", debugline)
3710
3715
  self.contact_is_dupe = result.get("isdupe", False)
@@ -4095,7 +4100,8 @@ class MainWindow(QtWidgets.QMainWindow):
4095
4100
  """
4096
4101
 
4097
4102
  logger.debug("******EDI*****")
4098
- self.contest.edi(self)
4103
+ if hasattr(self.contest, "edi"):
4104
+ self.contest.edi(self)
4099
4105
 
4100
4106
  def generate_cabrillo(self, file_encoding: str) -> None:
4101
4107
  """
@@ -347,6 +347,11 @@
347
347
  <string>EA RTTY</string>
348
348
  </property>
349
349
  </item>
350
+ <item>
351
+ <property name="text">
352
+ <string>ES OPEN</string>
353
+ </property>
354
+ </item>
350
355
  <item>
351
356
  <property name="text">
352
357
  <string>HELVETIA</string>
not1mm/lib/database.py CHANGED
@@ -1217,3 +1217,63 @@ class DataBase:
1217
1217
  except sqlite3.OperationalError as exception:
1218
1218
  logger.debug("%s", exception)
1219
1219
  return ()
1220
+
1221
+ def check_dupe_on_period_1_mode(
1222
+ self, call, band, mode, contest_start_time, contest_time_period_1
1223
+ ) -> dict:
1224
+ """Checks if a call is dupe on band/mode"""
1225
+ try:
1226
+ with sqlite3.connect(self.database) as conn:
1227
+ conn.row_factory = self.row_factory
1228
+ cursor = conn.cursor()
1229
+ cursor.execute(
1230
+ f"select count(*) as isdupe from dxlog where Call = '{call}' and Mode = '{mode}' and Band = '{band}' and ContestNR = {self.current_contest} AND TS >= '{contest_start_time}' AND TS <= '{contest_time_period_1}';"
1231
+ )
1232
+ return cursor.fetchone()
1233
+ except sqlite3.OperationalError as exception:
1234
+ logger.debug("%s", exception)
1235
+ return {}
1236
+
1237
+ def check_dupe_on_period_2_mode(
1238
+ self,
1239
+ call,
1240
+ band,
1241
+ mode,
1242
+ contest_start_time,
1243
+ contest_time_period_1,
1244
+ contest_time_period_2,
1245
+ ) -> dict:
1246
+ """Checks if a call is dupe on band/mode"""
1247
+ try:
1248
+ with sqlite3.connect(self.database) as conn:
1249
+ conn.row_factory = self.row_factory
1250
+ cursor = conn.cursor()
1251
+ cursor.execute(
1252
+ f"select count(*) as isdupe from dxlog where Call = '{call}' and Mode = '{mode}' and Band = '{band}' and ContestNR = {self.current_contest} AND TS >= '{contest_time_period_1}' AND TS <= '{contest_time_period_2}';"
1253
+ )
1254
+ return cursor.fetchone()
1255
+ except sqlite3.OperationalError as exception:
1256
+ logger.debug("%s", exception)
1257
+ return {}
1258
+
1259
+ def check_dupe_on_period_3_mode(
1260
+ self,
1261
+ call,
1262
+ band,
1263
+ mode,
1264
+ contest_start_time,
1265
+ contest_time_period_2,
1266
+ contest_time_period_3,
1267
+ ) -> dict:
1268
+ """Checks if a call is dupe on band/mode"""
1269
+ try:
1270
+ with sqlite3.connect(self.database) as conn:
1271
+ conn.row_factory = self.row_factory
1272
+ cursor = conn.cursor()
1273
+ cursor.execute(
1274
+ f"select count(*) as isdupe from dxlog where Call = '{call}' and Mode = '{mode}' and Band = '{band}' and ContestNR = {self.current_contest} AND TS >= '{contest_time_period_2}' AND TS <= '{contest_time_period_3}';"
1275
+ )
1276
+ return cursor.fetchone()
1277
+ except sqlite3.OperationalError as exception:
1278
+ logger.debug("%s", exception)
1279
+ return {}
not1mm/lib/version.py CHANGED
@@ -1,3 +1,3 @@
1
1
  """It's the version"""
2
2
 
3
- __version__ = "25.4.13"
3
+ __version__ = "25.4.14"
@@ -0,0 +1,568 @@
1
+ """ """
2
+
3
+ import datetime
4
+ import logging
5
+ import platform
6
+
7
+ from pathlib import Path
8
+
9
+ from PyQt6 import QtWidgets
10
+
11
+ from not1mm.lib.plugin_common import gen_adif, get_points
12
+
13
+ from not1mm.lib.ham_utility import calculate_wpx_prefix
14
+ from not1mm.lib.version import __version__
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+ EXCHANGE_HINT = "#"
19
+
20
+ name = "ES OPEN"
21
+ cabrillo_name = "ES-OPEN"
22
+ mode = "BOTH" # CW SSB BOTH RTTY
23
+
24
+ columns = [
25
+ "YYYY-MM-DD HH:MM:SS",
26
+ "Call",
27
+ "Freq",
28
+ "Mode",
29
+ "Snt",
30
+ "Rcv",
31
+ "SentNr",
32
+ "RcvNr",
33
+ "PTS",
34
+ ]
35
+
36
+ advance_on_space = [True, True, True, True, True]
37
+
38
+ # 5 Contest specific dupe check.
39
+ dupe_type = 5
40
+
41
+
42
+ def specific_contest_check_dupe(self, call):
43
+ """"""
44
+
45
+ # constant to split the contest
46
+ contest_length_in_minutes = 60
47
+ split_contest_by_minutes = 20
48
+
49
+ period_count = int(contest_length_in_minutes / split_contest_by_minutes)
50
+
51
+ # think about generic solution by splitting the contest to n different periods
52
+ start_date_init = self.contest_settings.get("StartDate", "")
53
+ self.contest_start_date = start_date_init.split(" ")[0]
54
+ self.contest_start_time = start_date_init.split(" ")[1]
55
+
56
+ start_date_init_date = datetime.strptime(start_date_init, "%Y-%m-%d %H:%M:%S")
57
+
58
+ # Create time periods dynamically based on period count
59
+ time_periods = []
60
+ for i in range(period_count):
61
+ minutes_to_add = split_contest_by_minutes * (i + 1)
62
+ time_period = start_date_init_date + datetime.timedelta(minutes=minutes_to_add)
63
+ time_periods.append(time_period)
64
+
65
+ # Assign to variables for backwards compatibility
66
+ time_period_1 = time_periods[0] if len(time_periods) > 0 else None
67
+ time_period_2 = time_periods[1] if len(time_periods) > 1 else None
68
+ time_period_3 = time_periods[2] if len(time_periods) > 2 else None
69
+
70
+ # get current time in UTC
71
+ iso_current_time = datetime.now(datetime.timezone.utc)
72
+ current_time = iso_current_time.replace(tzinfo=None)
73
+
74
+ if current_time < time_period_1:
75
+ start_date_init = self.contest_start_date + " " + self.contest_start_time
76
+
77
+ result = self.database.check_dupe_on_period_1_mode(
78
+ call,
79
+ self.contact.get("Band", ""),
80
+ mode,
81
+ start_date_init,
82
+ time_period_1.strftime("%Y-%m-%d %H:%M:%S"),
83
+ )
84
+
85
+ if current_time < time_period_2 and current_time >= time_period_1:
86
+ start_date_init = self.contest_start_date + " " + self.contest_start_time
87
+
88
+ result = self.database.check_dupe_on_period_2_mode(
89
+ call,
90
+ self.contact.get("Band", ""),
91
+ mode,
92
+ start_date_init,
93
+ time_period_1.strftime("%Y-%m-%d %H:%M:%S"),
94
+ time_period_2.strftime("%Y-%m-%d %H:%M:%S"),
95
+ )
96
+
97
+ if current_time < time_period_3 and current_time >= time_period_2:
98
+ start_date_init = self.contest_start_date + " " + self.contest_start_time
99
+
100
+ result = self.database.check_dupe_on_period_3_mode(
101
+ call,
102
+ self.contact.get("Band", ""),
103
+ mode,
104
+ start_date_init,
105
+ time_period_2.strftime("%Y-%m-%d %H:%M:%S"),
106
+ time_period_3.strftime("%Y-%m-%d %H:%M:%S"),
107
+ )
108
+ else:
109
+ result = self.database.check_dupe_on_period_mode(
110
+ call, self.contact.get("Band", ""), mode, start_date_init
111
+ )
112
+ return result
113
+
114
+
115
+ def init_contest(self):
116
+ """setup plugin"""
117
+ set_tab_next(self)
118
+ set_tab_prev(self)
119
+ interface(self)
120
+ self.next_field = self.other_2
121
+
122
+
123
+ def interface(self):
124
+ """Setup user interface"""
125
+ self.field1.show()
126
+ self.field2.show()
127
+ self.field3.show()
128
+ self.field4.show()
129
+ self.other_label.setText("Sent")
130
+ self.field3.setAccessibleName("Sent")
131
+ self.exch_label.setText("SN")
132
+ self.field4.setAccessibleName("SN")
133
+
134
+
135
+ def reset_label(self):
136
+ """reset label after field cleared"""
137
+
138
+
139
+ def set_tab_next(self):
140
+ """Set TAB Advances"""
141
+ self.tab_next = {
142
+ self.callsign: self.other_1,
143
+ self.sent: self.other_1,
144
+ self.receive: self.other_1,
145
+ self.other_1: self.other_2,
146
+ self.other_2: self.callsign,
147
+ }
148
+
149
+
150
+ def set_tab_prev(self):
151
+ """Set TAB Advances"""
152
+ self.tab_prev = {
153
+ self.callsign: self.other_2,
154
+ self.sent: self.callsign,
155
+ self.receive: self.callsign,
156
+ self.other_1: self.callsign,
157
+ self.other_2: self.other_1,
158
+ }
159
+
160
+
161
+ def set_contact_vars(self):
162
+ """Contest Specific"""
163
+ self.contact["SNT"] = self.sent.text()
164
+ self.contact["RCV"] = self.receive.text()
165
+ self.contact["SentNr"] = self.other_1.text().upper()
166
+ self.contact["NR"] = self.other_2.text().upper()
167
+
168
+ self.contact["IsMultiplier1"] = 0
169
+ self.contact["IsMultiplier2"] = 0
170
+
171
+
172
+ def predupe(self):
173
+ """called after callsign entered"""
174
+
175
+
176
+ def prefill(self):
177
+ """Fill SentNR"""
178
+ sent_sxchange_setting = self.contest_settings.get("SentExchange", "")
179
+ if sent_sxchange_setting.strip() == "#":
180
+ result = self.database.get_serial()
181
+ serial_nr = str(result.get("serial_nr", "1")).zfill(3)
182
+ if serial_nr == "None":
183
+ serial_nr = "001"
184
+ if len(self.other_1.text()) == 0:
185
+ self.other_1.setText(serial_nr)
186
+ else:
187
+ self.other_1.setText(sent_sxchange_setting)
188
+
189
+
190
+ def points(self):
191
+ """ """
192
+ if self.contact_is_dupe > 0:
193
+ return 0
194
+
195
+ _mode = self.contact.get("Mode", "")
196
+ if _mode in "SSB, USB, LSB, FM, AM":
197
+ return 1
198
+ if _mode in "CW":
199
+ return 2
200
+
201
+ return 0
202
+
203
+
204
+ def show_mults(self, rtc=None):
205
+ """Return display string for mults"""
206
+ our_prefix = calculate_wpx_prefix(self.station.get("Call", ""))
207
+ query = f"SELECT count(DISTINCT(substr(WPXPrefix,3,1) || ':' || Band || ':' || Mode)) as mults from DXLOG where ContestNR = {self.pref.get('contest', '1')} AND CountryPrefix = 'ES' AND WPXPrefix != '{our_prefix}';"
208
+ result = self.database.exec_sql(query)
209
+ if result:
210
+ mult_count = result.get("mults", 0)
211
+ return mult_count
212
+ return 0
213
+
214
+
215
+ def show_qso(self):
216
+ """Return qso count"""
217
+ result = self.database.fetch_qso_count()
218
+ if result:
219
+ return int(result.get("qsos", 0))
220
+ return 0
221
+
222
+
223
+ def calc_score(self):
224
+ """Return calculated score"""
225
+ result = self.database.fetch_points()
226
+ if result is not None:
227
+ score = result.get("Points", "0")
228
+ if score is None:
229
+ score = "0"
230
+ contest_points = int(score)
231
+ mults = show_mults(self)
232
+ return contest_points * (mults + 1)
233
+ return 0
234
+
235
+
236
+ def recalculate_mults(self):
237
+ """Recalculates multipliers after change in logged qso."""
238
+
239
+
240
+ def adif(self):
241
+ """Call the generate ADIF function"""
242
+ gen_adif(self, cabrillo_name, "ES OPEN")
243
+
244
+
245
+ def output_cabrillo_line(line_to_output, ending, file_descriptor, file_encoding):
246
+ """"""
247
+ print(
248
+ line_to_output.encode(file_encoding, errors="ignore").decode(),
249
+ end=ending,
250
+ file=file_descriptor,
251
+ )
252
+
253
+
254
+ def cabrillo(self, file_encoding):
255
+ """Generates Cabrillo file. Maybe."""
256
+ # https://www.cqwpx.com/cabrillo.htm
257
+ logger.debug("******Cabrillo*****")
258
+ logger.debug("Station: %s", f"{self.station}")
259
+ logger.debug("Contest: %s", f"{self.contest_settings}")
260
+ now = datetime.datetime.now()
261
+ date_time = now.strftime("%Y-%m-%d_%H-%M-%S")
262
+ filename = (
263
+ str(Path.home())
264
+ + "/"
265
+ + f"{self.station.get('Call', '').upper()}_{cabrillo_name}_{date_time}.log"
266
+ )
267
+ logger.debug("%s", filename)
268
+ log = self.database.fetch_all_contacts_asc()
269
+ try:
270
+ with open(filename, "w", encoding=file_encoding, newline="") as file_descriptor:
271
+ output_cabrillo_line(
272
+ "START-OF-LOG: 3.0",
273
+ "\r\n",
274
+ file_descriptor,
275
+ file_encoding,
276
+ )
277
+ output_cabrillo_line(
278
+ f"CREATED-BY: Not1MM v{__version__}",
279
+ "\r\n",
280
+ file_descriptor,
281
+ file_encoding,
282
+ )
283
+ output_cabrillo_line(
284
+ f"CONTEST: {cabrillo_name}",
285
+ "\r\n",
286
+ file_descriptor,
287
+ file_encoding,
288
+ )
289
+ if self.station.get("Club", ""):
290
+ output_cabrillo_line(
291
+ f"CLUB: {self.station.get('Club', '').upper()}",
292
+ "\r\n",
293
+ file_descriptor,
294
+ file_encoding,
295
+ )
296
+ output_cabrillo_line(
297
+ f"CALLSIGN: {self.station.get('Call','')}",
298
+ "\r\n",
299
+ file_descriptor,
300
+ file_encoding,
301
+ )
302
+ output_cabrillo_line(
303
+ f"LOCATION: {self.station.get('ARRLSection', '')}",
304
+ "\r\n",
305
+ file_descriptor,
306
+ file_encoding,
307
+ )
308
+ output_cabrillo_line(
309
+ f"CATEGORY-OPERATOR: {self.contest_settings.get('OperatorCategory','')}",
310
+ "\r\n",
311
+ file_descriptor,
312
+ file_encoding,
313
+ )
314
+ output_cabrillo_line(
315
+ f"CATEGORY-ASSISTED: {self.contest_settings.get('AssistedCategory','')}",
316
+ "\r\n",
317
+ file_descriptor,
318
+ file_encoding,
319
+ )
320
+ output_cabrillo_line(
321
+ f"CATEGORY-BAND: {self.contest_settings.get('BandCategory','')}",
322
+ "\r\n",
323
+ file_descriptor,
324
+ file_encoding,
325
+ )
326
+ mode = self.contest_settings.get("ModeCategory", "")
327
+ if mode in ["SSB+CW", "SSB+CW+DIGITAL"]:
328
+ mode = "MIXED"
329
+ output_cabrillo_line(
330
+ f"CATEGORY-MODE: {mode}",
331
+ "\r\n",
332
+ file_descriptor,
333
+ file_encoding,
334
+ )
335
+ output_cabrillo_line(
336
+ f"CATEGORY-TRANSMITTER: {self.contest_settings.get('TransmitterCategory','')}",
337
+ "\r\n",
338
+ file_descriptor,
339
+ file_encoding,
340
+ )
341
+ if self.contest_settings.get("OverlayCategory", "") != "N/A":
342
+ output_cabrillo_line(
343
+ f"CATEGORY-OVERLAY: {self.contest_settings.get('OverlayCategory','')}",
344
+ "\r\n",
345
+ file_descriptor,
346
+ file_encoding,
347
+ )
348
+ output_cabrillo_line(
349
+ f"GRID-LOCATOR: {self.station.get('GridSquare','')}",
350
+ "\r\n",
351
+ file_descriptor,
352
+ file_encoding,
353
+ )
354
+ output_cabrillo_line(
355
+ f"CATEGORY-POWER: {self.contest_settings.get('PowerCategory','')}",
356
+ "\r\n",
357
+ file_descriptor,
358
+ file_encoding,
359
+ )
360
+
361
+ output_cabrillo_line(
362
+ f"CLAIMED-SCORE: {calc_score(self)}",
363
+ "\r\n",
364
+ file_descriptor,
365
+ file_encoding,
366
+ )
367
+ ops = f"@{self.station.get('Call','')}"
368
+ list_of_ops = self.database.get_ops()
369
+ for op in list_of_ops:
370
+ ops += f", {op.get('Operator', '')}"
371
+ output_cabrillo_line(
372
+ f"OPERATORS: {ops}",
373
+ "\r\n",
374
+ file_descriptor,
375
+ file_encoding,
376
+ )
377
+ output_cabrillo_line(
378
+ f"NAME: {self.station.get('Name', '')}",
379
+ "\r\n",
380
+ file_descriptor,
381
+ file_encoding,
382
+ )
383
+ output_cabrillo_line(
384
+ f"ADDRESS: {self.station.get('Street1', '')}",
385
+ "\r\n",
386
+ file_descriptor,
387
+ file_encoding,
388
+ )
389
+ output_cabrillo_line(
390
+ f"ADDRESS-CITY: {self.station.get('City', '')}",
391
+ "\r\n",
392
+ file_descriptor,
393
+ file_encoding,
394
+ )
395
+ output_cabrillo_line(
396
+ f"ADDRESS-STATE-PROVINCE: {self.station.get('State', '')}",
397
+ "\r\n",
398
+ file_descriptor,
399
+ file_encoding,
400
+ )
401
+ output_cabrillo_line(
402
+ f"ADDRESS-POSTALCODE: {self.station.get('Zip', '')}",
403
+ "\r\n",
404
+ file_descriptor,
405
+ file_encoding,
406
+ )
407
+ output_cabrillo_line(
408
+ f"ADDRESS-COUNTRY: {self.station.get('Country', '')}",
409
+ "\r\n",
410
+ file_descriptor,
411
+ file_encoding,
412
+ )
413
+ output_cabrillo_line(
414
+ f"EMAIL: {self.station.get('Email', '')}",
415
+ "\r\n",
416
+ file_descriptor,
417
+ file_encoding,
418
+ )
419
+ for contact in log:
420
+ the_date_and_time = contact.get("TS", "")
421
+ themode = contact.get("Mode", "")
422
+ if themode == "LSB" or themode == "USB":
423
+ themode = "PH"
424
+ frequency = str(int(contact.get("Freq", "0"))).rjust(5)
425
+
426
+ loggeddate = the_date_and_time[:10]
427
+ loggedtime = the_date_and_time[11:13] + the_date_and_time[14:16]
428
+ output_cabrillo_line(
429
+ f"QSO: {frequency} {themode} {loggeddate} {loggedtime} "
430
+ f"{contact.get('StationPrefix', '').ljust(13)} "
431
+ f"{str(contact.get('SNT', '')).ljust(3)} "
432
+ f"{str(contact.get('SentNr', '')).ljust(6)} "
433
+ f"{contact.get('Call', '').ljust(13)} "
434
+ f"{str(contact.get('RCV', '')).ljust(3)} "
435
+ f"{str(contact.get('NR', '')).ljust(6)}",
436
+ "\r\n",
437
+ file_descriptor,
438
+ file_encoding,
439
+ )
440
+ output_cabrillo_line("END-OF-LOG:", "\r\n", file_descriptor, file_encoding)
441
+ self.show_message_box(f"Cabrillo saved to: {filename}")
442
+ except IOError as exception:
443
+ logger.critical("cabrillo: IO error: %s, writing to %s", exception, filename)
444
+ self.show_message_box(f"Error saving Cabrillo: {exception} {filename}")
445
+ return
446
+
447
+
448
+ # def populate_history_info_line(self):
449
+ # result = self.database.fetch_call_history(self.callsign.text())
450
+ # if result:
451
+ # self.history_info.setText(
452
+ # f"{result.get('Call', '')}, {result.get('Exch1', '')}, {result.get('UserText','...')}"
453
+ # )
454
+ # else:
455
+ # self.history_info.setText("")
456
+
457
+
458
+ # def check_call_history(self):
459
+ # """"""
460
+ # result = self.database.fetch_call_history(self.callsign.text())
461
+ # print(f"{result=}")
462
+ # if result:
463
+ # self.history_info.setText(f"{result.get('UserText','')}")
464
+ # if self.other_2.text() == "":
465
+ # self.other_2.setText(f"{result.get('Exch1', '')}")
466
+
467
+
468
+ def process_esm(self, new_focused_widget=None, with_enter=False):
469
+ """ESM State Machine"""
470
+
471
+ # self.pref["run_state"]
472
+
473
+ # -----===== Assigned F-Keys =====-----
474
+ # self.esm_dict["CQ"]
475
+ # self.esm_dict["EXCH"]
476
+ # self.esm_dict["QRZ"]
477
+ # self.esm_dict["AGN"]
478
+ # self.esm_dict["HISCALL"]
479
+ # self.esm_dict["MYCALL"]
480
+ # self.esm_dict["QSOB4"]
481
+
482
+ # ----==== text fields ====----
483
+ # self.callsign
484
+ # self.sent
485
+ # self.receive
486
+ # self.other_1
487
+ # self.other_2
488
+
489
+ if new_focused_widget is not None:
490
+ self.current_widget = self.inputs_dict.get(new_focused_widget)
491
+
492
+ # print(f"checking esm {self.current_widget=} {with_enter=} {self.pref.get("run_state")=}")
493
+
494
+ for a_button in [
495
+ self.esm_dict["CQ"],
496
+ self.esm_dict["EXCH"],
497
+ self.esm_dict["QRZ"],
498
+ self.esm_dict["AGN"],
499
+ self.esm_dict["HISCALL"],
500
+ self.esm_dict["MYCALL"],
501
+ self.esm_dict["QSOB4"],
502
+ ]:
503
+ if a_button is not None:
504
+ self.restore_button_color(a_button)
505
+
506
+ buttons_to_send = []
507
+
508
+ if self.pref.get("run_state"):
509
+ if self.current_widget == "callsign":
510
+ if len(self.callsign.text()) < 3:
511
+ self.make_button_green(self.esm_dict["CQ"])
512
+ buttons_to_send.append(self.esm_dict["CQ"])
513
+ elif len(self.callsign.text()) > 2:
514
+ self.make_button_green(self.esm_dict["HISCALL"])
515
+ self.make_button_green(self.esm_dict["EXCH"])
516
+ buttons_to_send.append(self.esm_dict["HISCALL"])
517
+ buttons_to_send.append(self.esm_dict["EXCH"])
518
+
519
+ elif self.current_widget == "other_2":
520
+ if self.other_2.text() == "":
521
+ self.make_button_green(self.esm_dict["AGN"])
522
+ buttons_to_send.append(self.esm_dict["AGN"])
523
+ else:
524
+ self.make_button_green(self.esm_dict["QRZ"])
525
+ buttons_to_send.append(self.esm_dict["QRZ"])
526
+ buttons_to_send.append("LOGIT")
527
+
528
+ if with_enter is True and bool(len(buttons_to_send)):
529
+ for button in buttons_to_send:
530
+ if button:
531
+ if button == "LOGIT":
532
+ self.save_contact()
533
+ continue
534
+ self.process_function_key(button)
535
+ else:
536
+ if self.current_widget == "callsign":
537
+ if len(self.callsign.text()) > 2:
538
+ self.make_button_green(self.esm_dict["MYCALL"])
539
+ buttons_to_send.append(self.esm_dict["MYCALL"])
540
+
541
+ elif self.current_widget == "other_2":
542
+ if self.other_2.text() == "":
543
+ self.make_button_green(self.esm_dict["AGN"])
544
+ buttons_to_send.append(self.esm_dict["AGN"])
545
+ else:
546
+ self.make_button_green(self.esm_dict["EXCH"])
547
+ buttons_to_send.append(self.esm_dict["EXCH"])
548
+ buttons_to_send.append("LOGIT")
549
+
550
+ if with_enter is True and bool(len(buttons_to_send)):
551
+ for button in buttons_to_send:
552
+ if button:
553
+ if button == "LOGIT":
554
+ self.save_contact()
555
+ continue
556
+ self.process_function_key(button)
557
+
558
+
559
+ def get_mults(self):
560
+ """Get mults for RTC XML"""
561
+ mults = {}
562
+ mults["country"], mults["state"] = show_mults(self, rtc=True)
563
+ return mults
564
+
565
+
566
+ def just_points(self):
567
+ """Get points for RTC XML"""
568
+ return get_points(self)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: not1mm
3
- Version: 25.4.13
3
+ Version: 25.4.14
4
4
  Summary: NOT1MM Logger
5
5
  Author-email: Michael Bridak <michael.bridak@gmail.com>
6
6
  License: GPL-3.0-or-later
@@ -230,6 +230,7 @@ generated, 'cause I'm lazy, list of those who've submitted PR's.
230
230
  - EA Majistad CW
231
231
  - EA Majistad SSB
232
232
  - EA RTTY
233
+ - ES OPEN HF
233
234
  - Helvetia
234
235
  - IARU Fieldday R1 CW, SSB
235
236
  - IARU HF
@@ -253,6 +254,7 @@ generated, 'cause I'm lazy, list of those who've submitted PR's.
253
254
 
254
255
  ## Recent Changes
255
256
 
257
+ - [25-4-14] Add ES Open HF Chanmpionship.
256
258
  - [25-4-13] Fix crash in JIDX Cabrillo output.
257
259
  - [25-4-12] Added an Auto CQ time to fire progress bar.
258
260
  - [25-4-11-3] Fixed issue with winkeyer not sending multiple macros in ESM mode.
@@ -1,5 +1,5 @@
1
1
  not1mm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- not1mm/__main__.py,sha256=_sobv7fOxQw5gIM1Q2-fLSMn2EXSdOgki0PnZ2xTFGo,153631
2
+ not1mm/__main__.py,sha256=T03w3kUEWO4gy1oiDYG7GnqxhN4P5MH4ZB1u6SWB7pQ,153922
3
3
  not1mm/bandmap.py,sha256=-zu5slsuAm2GmeW8g3yvURzsuQxemwIQfw1HEq8xKHM,29920
4
4
  not1mm/checkwindow.py,sha256=zEHlw40j6Wr3rvKbCQf2lcezCoiZqaBqEvBjQU5aKW0,7630
5
5
  not1mm/fsutils.py,sha256=ukHKxKTeNKxKwqRaJjtzRShL4X5Xl0jRBbADyy3Ifp8,1701
@@ -34,7 +34,7 @@ not1mm/data/k6gte.not1mm-64.png,sha256=6ku45Gq1g5ezh04F07osoKRtanb3e4kbx5XdIEh3N
34
34
  not1mm/data/logwindow.ui,sha256=f7vULj96tHIQuR1nJMyvPHHcmVgzkhv9D1isyojsnFU,1458
35
35
  not1mm/data/logwindowx.ui,sha256=CwpI-h7cI1yqyldH9quKftsdHL5lTyL9ABOcf80nfqc,1632
36
36
  not1mm/data/main.ui,sha256=-JDQXOaxj8_7Wda9KT2rEM4YUjBs31CiT1Rjc_DBobM,64907
37
- not1mm/data/new_contest.ui,sha256=Q8ZORq_9iRls5AJTroh1HAhEkTCOu02nBv9e9xXMOCU,25119
37
+ not1mm/data/new_contest.ui,sha256=glqsmFGF5gh-JB-zuEVxAWrOR7-Hok5ibvZYCMcDCWE,25223
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
@@ -102,7 +102,7 @@ not1mm/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
102
102
  not1mm/lib/about.py,sha256=sWycfGcruN3SaEe4JmaJ61K6D8Itq0WxpUYT-lEcmYM,416
103
103
  not1mm/lib/cat_interface.py,sha256=BJvy-34ZyiN73kKNQcCzE4w6ll2O6Ue0uz01T_3sf1E,25204
104
104
  not1mm/lib/cwinterface.py,sha256=rKUnqljHQC_Iljq4TCmAgSPe49lWbKcfxg58cE8YX5Y,5177
105
- not1mm/lib/database.py,sha256=-9iAPTXDGVUc3OfnZNZCaWRxg3u-qdJyO5jvSvrJQSk,49203
105
+ not1mm/lib/database.py,sha256=fykyaQaTa_Pwde51f09Odbexy1mlUqObv0fjZ7hf3E0,51693
106
106
  not1mm/lib/edit_contact.py,sha256=Ki9bGPpqyQQBB1cU8VIBDCal3lbXeQ6qxhzklmhE2_w,353
107
107
  not1mm/lib/edit_macro.py,sha256=raKWBwsHInj5EUKmvyLQ6gqc3ZFDlstsD3xqoM4PC8E,517
108
108
  not1mm/lib/edit_opon.py,sha256=j3qJ1aBsQoIOnQ9yiBl3lyeISvKTP0I_rtBYBPAfgeI,359
@@ -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=hOoF1ZyaAAamS-LKleT-dA1ko_GY_a0UwQ-ix9bxrT4,48
121
+ not1mm/lib/version.py,sha256=VF2ECEwHJr0MWw2BVQtIHH1HDZfZCrSeIks7YLhW7iU,48
122
122
  not1mm/lib/versiontest.py,sha256=8vDNptuBBunn-1IGkjNaquehqBYUJyjrPSF8Igmd4_Y,1286
123
123
  not1mm/plugins/10_10_fall_cw.py,sha256=oJh3JKqjOpnWElSlZpiQ631UnaOd8qra5s9bl_QoInk,14783
124
124
  not1mm/plugins/10_10_spring_cw.py,sha256=p7dSDtbFK0e6Xouw2V6swYn3VFVgHKyx4IfRWyBjMZY,14786
@@ -152,6 +152,7 @@ not1mm/plugins/darc_xmas.py,sha256=p5UNYLdtylsC_sSlxT8NvXXL1oSW0KyUhIN-rJonHgI,1
152
152
  not1mm/plugins/ea_majistad_cw.py,sha256=tl9y92Oz4NTch4H-SrBnZND2tHGqWQvtgl3emXfU8og,23352
153
153
  not1mm/plugins/ea_majistad_ssb.py,sha256=TwZLHwgybpIgA4ECXzV3bIeP89MLr3vXa4_O99-mgxQ,22946
154
154
  not1mm/plugins/ea_rtty.py,sha256=JvszWdtUqC_Sn2sJAlMhMp2AdlLyAIj-6nWT-yFkihw,23229
155
+ not1mm/plugins/es_ll_kv.py,sha256=A0zW59A6DYzPTM6Q_zBGKM3zeDr9DXlS9oaAPdxKt5k,18384
155
156
  not1mm/plugins/general_logging.py,sha256=eQuna-LnrWpf93LmHTTo6956GWoGocVfeYnzY5cyTmw,9600
156
157
  not1mm/plugins/helvetia.py,sha256=fDKhvjDh5PxxLxmxvqTHzt-u0cMjHOjlF6JWBu3qB20,20079
157
158
  not1mm/plugins/iaru_fieldday_r1_cw.py,sha256=1AVyZFi3ri2zqaNJY181Wtyz74fai8QLoi7PoyXpfaY,17218
@@ -178,9 +179,9 @@ not1mm/plugins/stew_perry_topband.py,sha256=3U-Dr28haBTqTaZWLiC1qHQBmLsLENDL-ihy
178
179
  not1mm/plugins/ukeidx.py,sha256=0ABGW7_9Ui0Rgr8mkPBxOJokAIerM1a4-HWnl6VsnV8,19105
179
180
  not1mm/plugins/weekly_rtty.py,sha256=C8Xs3Q5UgSYx-mFFar8BVARWtmqlyrbeC98Ubzb4UN8,20128
180
181
  not1mm/plugins/winter_field_day.py,sha256=hmAMgkdqIXtnCNyUp8J9Bb8liN8wj10wps6ROuG-Bok,15284
181
- not1mm-25.4.13.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
182
- not1mm-25.4.13.dist-info/METADATA,sha256=Lu2tPf_duFIuTsuF_Jfwwin9tcBvsjWGTm_SnV1CHWU,39339
183
- not1mm-25.4.13.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
184
- not1mm-25.4.13.dist-info/entry_points.txt,sha256=pMcZk_0dxFgLkcUkF0Q874ojpwOmF3OL6EKw9LgvocM,47
185
- not1mm-25.4.13.dist-info/top_level.txt,sha256=0YmTxEcDzQlzXub-lXASvoLpg_mt1c2thb5cVkDf5J4,7
186
- not1mm-25.4.13.dist-info/RECORD,,
182
+ not1mm-25.4.14.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
183
+ not1mm-25.4.14.dist-info/METADATA,sha256=zEUjyqIWcZk19fufgQqtY-OwoWxDYPuoZ9y0gdbxYEc,39394
184
+ not1mm-25.4.14.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
185
+ not1mm-25.4.14.dist-info/entry_points.txt,sha256=pMcZk_0dxFgLkcUkF0Q874ojpwOmF3OL6EKw9LgvocM,47
186
+ not1mm-25.4.14.dist-info/top_level.txt,sha256=0YmTxEcDzQlzXub-lXASvoLpg_mt1c2thb5cVkDf5J4,7
187
+ not1mm-25.4.14.dist-info/RECORD,,