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 +7 -1
- not1mm/data/new_contest.ui +5 -0
- not1mm/lib/database.py +60 -0
- not1mm/lib/version.py +1 -1
- not1mm/plugins/es_ll_kv.py +568 -0
- {not1mm-25.4.13.dist-info → not1mm-25.4.14.dist-info}/METADATA +3 -1
- {not1mm-25.4.13.dist-info → not1mm-25.4.14.dist-info}/RECORD +11 -10
- {not1mm-25.4.13.dist-info → not1mm-25.4.14.dist-info}/WHEEL +0 -0
- {not1mm-25.4.13.dist-info → not1mm-25.4.14.dist-info}/entry_points.txt +0 -0
- {not1mm-25.4.13.dist-info → not1mm-25.4.14.dist-info}/licenses/LICENSE +0 -0
- {not1mm-25.4.13.dist-info → not1mm-25.4.14.dist-info}/top_level.txt +0 -0
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
|
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
|
"""
|
not1mm/data/new_contest.ui
CHANGED
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
@@ -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.
|
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=
|
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=
|
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
|
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=
|
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.
|
182
|
-
not1mm-25.4.
|
183
|
-
not1mm-25.4.
|
184
|
-
not1mm-25.4.
|
185
|
-
not1mm-25.4.
|
186
|
-
not1mm-25.4.
|
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,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|