not1mm 24.6.1__py3-none-any.whl → 24.7.12__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
not1mm/data/settings.ui CHANGED
@@ -1255,7 +1255,7 @@
1255
1255
  </palette>
1256
1256
  </property>
1257
1257
  <property name="focusPolicy">
1258
- <enum>Qt::StrongFocus</enum>
1258
+ <enum>Qt::FocusPolicy::StrongFocus</enum>
1259
1259
  </property>
1260
1260
  <property name="accessibleName">
1261
1261
  <string>c q zone</string>
@@ -1374,7 +1374,7 @@
1374
1374
  <item>
1375
1375
  <spacer name="horizontalSpacer_2">
1376
1376
  <property name="orientation">
1377
- <enum>Qt::Horizontal</enum>
1377
+ <enum>Qt::Orientation::Horizontal</enum>
1378
1378
  </property>
1379
1379
  <property name="sizeHint" stdset="0">
1380
1380
  <size>
@@ -1387,10 +1387,10 @@
1387
1387
  <item>
1388
1388
  <widget class="QDialogButtonBox" name="buttonBox">
1389
1389
  <property name="orientation">
1390
- <enum>Qt::Horizontal</enum>
1390
+ <enum>Qt::Orientation::Horizontal</enum>
1391
1391
  </property>
1392
1392
  <property name="standardButtons">
1393
- <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
1393
+ <set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
1394
1394
  </property>
1395
1395
  <property name="centerButtons">
1396
1396
  <bool>true</bool>
@@ -1400,7 +1400,7 @@
1400
1400
  <item>
1401
1401
  <spacer name="horizontalSpacer">
1402
1402
  <property name="orientation">
1403
- <enum>Qt::Horizontal</enum>
1403
+ <enum>Qt::Orientation::Horizontal</enum>
1404
1404
  </property>
1405
1405
  <property name="sizeHint" stdset="0">
1406
1406
  <size>
not1mm/lib/n1mm.py CHANGED
@@ -102,6 +102,21 @@ class N1MM:
102
102
  "ID": "",
103
103
  }
104
104
 
105
+ score_report = {
106
+ "app": "NOT1MM",
107
+ "contest": "",
108
+ "call": "",
109
+ "class": {
110
+ "ops": "SINGLE-OP",
111
+ "mode": "MIXED",
112
+ "power": "LOW",
113
+ "bands": "ALL",
114
+ "transmitter": "ONE",
115
+ },
116
+ "score": 0,
117
+ "timestamp": "",
118
+ }
119
+
105
120
  def __init__(
106
121
  self,
107
122
  radioport="127.0.0.1:12060",
@@ -159,6 +174,14 @@ class N1MM:
159
174
  """Send lookup request"""
160
175
  self._send(self.lookup_port, self.contact_info, "lookupinfo")
161
176
 
177
+ def send_score(self):
178
+ """Send score"""
179
+ self._send(self.score_port, self.score_report, "scoreinfo")
180
+
181
+ def send_realtime_score(self):
182
+ """Send score"""
183
+ self._send(self.score_port, self.score_report, "dynamicresults")
184
+
162
185
  def _send(self, port_list, payload, package_name):
163
186
  """Send XML data"""
164
187
  # bytes_to_send = dicttoxml(
not1mm/lib/version.py CHANGED
@@ -1,3 +1,3 @@
1
1
  """It's the version"""
2
2
 
3
- __version__ = "24.6.1"
3
+ __version__ = "24.7.12"
@@ -21,4 +21,347 @@
21
21
  # Find rules at: http://www.k1usn.com/sst.html
22
22
 
23
23
  import datetime
24
+ import logging
25
+ import platform
24
26
 
27
+ from pathlib import Path
28
+
29
+ from PyQt6 import QtWidgets
30
+
31
+ from not1mm.lib.plugin_common import gen_adif, get_points
32
+ from not1mm.lib.version import __version__
33
+
34
+ logger = logging.getLogger(__name__)
35
+
36
+ EXCHANGE_HINT = "Name or Name + SPC"
37
+
38
+ name = "PHONE WEEKLY TEST"
39
+ cabrillo_name = "PHONE-WEEKLY-TEST"
40
+ mode = "SSB" # CW SSB BOTH RTTY
41
+ # columns = [0, 1, 2, 3, 4, 10, 11, 14, 15]
42
+ columns = [
43
+ "YYYY-MM-DD HH:MM:SS",
44
+ "Call",
45
+ "Freq",
46
+ "Name",
47
+ "Sect",
48
+ "M1",
49
+ "PTS",
50
+ ]
51
+
52
+ advance_on_space = [True, True, True, True, True]
53
+
54
+ # 1 once per contest, 2 work each band, 3 each band/mode, 4 no dupe checking
55
+ dupe_type = 2
56
+
57
+
58
+ def init_contest(self):
59
+ """setup plugin"""
60
+ set_tab_next(self)
61
+ set_tab_prev(self)
62
+ interface(self)
63
+ self.next_field = self.other_1
64
+
65
+
66
+ def interface(self):
67
+ """Setup user interface"""
68
+ self.field1.hide()
69
+ self.field2.hide()
70
+ self.field3.show()
71
+ self.field4.show()
72
+ namefield = self.field3.findChild(QtWidgets.QLabel)
73
+ namefield.setText("Name")
74
+ self.field3.setAccessibleName("Name")
75
+ spc = self.field4.findChild(QtWidgets.QLabel)
76
+ spc.setText("State")
77
+ self.field4.setAccessibleName("State")
78
+
79
+
80
+ def reset_label(self):
81
+ """reset label after field cleared"""
82
+
83
+
84
+ def set_tab_next(self):
85
+ """Set TAB Advances"""
86
+ self.tab_next = {
87
+ self.callsign: self.field3.findChild(QtWidgets.QLineEdit),
88
+ self.field3.findChild(QtWidgets.QLineEdit): self.field4.findChild(
89
+ QtWidgets.QLineEdit
90
+ ),
91
+ self.field4.findChild(QtWidgets.QLineEdit): self.callsign,
92
+ }
93
+
94
+
95
+ def set_tab_prev(self):
96
+ """Set TAB Advances"""
97
+ self.tab_prev = {
98
+ self.callsign: self.field4.findChild(QtWidgets.QLineEdit),
99
+ self.field3.findChild(QtWidgets.QLineEdit): self.callsign,
100
+ self.field4.findChild(QtWidgets.QLineEdit): self.field3.findChild(
101
+ QtWidgets.QLineEdit
102
+ ),
103
+ }
104
+
105
+
106
+ def set_contact_vars(self):
107
+ """Contest Specific"""
108
+ self.contact["SNT"] = self.sent.text()
109
+ self.contact["RCV"] = self.receive.text()
110
+ self.contact["Name"] = self.other_1.text().upper()
111
+ self.contact["Sect"] = self.other_2.text().upper()
112
+ self.contact["SentNr"] = self.contest_settings.get("SentExchange", 0)
113
+
114
+ if self.contact.get("Sect", ""):
115
+ result = self.database.fetch_sect_band_exists(
116
+ self.contact.get("Sect", ""), self.contact.get("Band", "")
117
+ )
118
+ if result.get("sect_count", ""):
119
+ self.contact["IsMultiplier1"] = 0
120
+ else:
121
+ self.contact["IsMultiplier1"] = 1
122
+
123
+
124
+ def predupe(self):
125
+ """called after callsign entered"""
126
+
127
+
128
+ def prefill(self):
129
+ """Fill sentnr"""
130
+
131
+
132
+ def points(self):
133
+ """Calc point"""
134
+ return 1
135
+
136
+
137
+ def show_mults(self):
138
+ """Return display string for mults"""
139
+ result = self.database.fetch_section_band_count_nodx()
140
+ if result:
141
+ return int(result.get("sb_count", 0))
142
+ return 0
143
+
144
+
145
+ def show_qso(self):
146
+ """Return qso count"""
147
+ result = self.database.fetch_qso_count()
148
+ if result:
149
+ return int(result.get("qsos", 0))
150
+ return 0
151
+
152
+
153
+ def calc_score(self):
154
+ """Return calculated score"""
155
+ result = self.database.fetch_points()
156
+ if result is not None:
157
+ score = result.get("Points", "0")
158
+ if score is None:
159
+ score = "0"
160
+ contest_points = int(score)
161
+ mults = show_mults(self)
162
+ return contest_points * mults
163
+ return 0
164
+
165
+
166
+ def adif(self):
167
+ """Call the generate ADIF function"""
168
+ gen_adif(self, cabrillo_name, "K1USN-SST")
169
+
170
+
171
+ def cabrillo(self):
172
+ """Generates Cabrillo file. Maybe."""
173
+ # https://www.cqwpx.com/cabrillo.htm
174
+ logger.debug("******Cabrillo*****")
175
+ logger.debug("Station: %s", f"{self.station}")
176
+ logger.debug("Contest: %s", f"{self.contest_settings}")
177
+ now = datetime.datetime.now()
178
+ date_time = now.strftime("%Y-%m-%d_%H-%M-%S")
179
+ filename = (
180
+ str(Path.home())
181
+ + "/"
182
+ + f"{self.station.get('Call','').upper()}_{cabrillo_name}_{date_time}.log"
183
+ )
184
+ logger.debug("%s", filename)
185
+ log = self.database.fetch_all_contacts_asc()
186
+ try:
187
+ with open(filename, "w", encoding="ascii") as file_descriptor:
188
+ print("START-OF-LOG: 3.0", end="\r\n", file=file_descriptor)
189
+ print(
190
+ f"CREATED-BY: Not1MM v{__version__}",
191
+ end="\r\n",
192
+ file=file_descriptor,
193
+ )
194
+ print(
195
+ f"CONTEST: {cabrillo_name}",
196
+ end="\r\n",
197
+ file=file_descriptor,
198
+ )
199
+ if self.station.get("Club", ""):
200
+ print(
201
+ f"CLUB: {self.station.get('Club', '').upper()}",
202
+ end="\r\n",
203
+ file=file_descriptor,
204
+ )
205
+ print(
206
+ f"CALLSIGN: {self.station.get('Call','')}",
207
+ end="\r\n",
208
+ file=file_descriptor,
209
+ )
210
+ print(
211
+ f"LOCATION: {self.station.get('ARRLSection', '')}",
212
+ end="\r\n",
213
+ file=file_descriptor,
214
+ )
215
+ # print(
216
+ # f"ARRL-SECTION: {self.pref.get('section', '')}",
217
+ # end="\r\n",
218
+ # file=file_descriptor,
219
+ # )
220
+ print(
221
+ f"CATEGORY-OPERATOR: {self.contest_settings.get('OperatorCategory','')}",
222
+ end="\r\n",
223
+ file=file_descriptor,
224
+ )
225
+ print(
226
+ f"CATEGORY-ASSISTED: {self.contest_settings.get('AssistedCategory','')}",
227
+ end="\r\n",
228
+ file=file_descriptor,
229
+ )
230
+ print(
231
+ f"CATEGORY-BAND: {self.contest_settings.get('BandCategory','')}",
232
+ end="\r\n",
233
+ file=file_descriptor,
234
+ )
235
+ print(
236
+ f"CATEGORY-MODE: {self.contest_settings.get('ModeCategory','')}",
237
+ end="\r\n",
238
+ file=file_descriptor,
239
+ )
240
+ print(
241
+ f"CATEGORY-TRANSMITTER: {self.contest_settings.get('TransmitterCategory','')}",
242
+ end="\r\n",
243
+ file=file_descriptor,
244
+ )
245
+ if self.contest_settings.get("OverlayCategory", "") != "N/A":
246
+ print(
247
+ f"CATEGORY-OVERLAY: {self.contest_settings.get('OverlayCategory','')}",
248
+ end="\r\n",
249
+ file=file_descriptor,
250
+ )
251
+ print(
252
+ f"GRID-LOCATOR: {self.station.get('GridSquare','')}",
253
+ end="\r\n",
254
+ file=file_descriptor,
255
+ )
256
+ # print(
257
+ # f"CATEGORY: {None}",
258
+ # end="\r\n",
259
+ # file=file_descriptor,
260
+ # )
261
+ print(
262
+ f"CATEGORY-POWER: {self.contest_settings.get('PowerCategory','')}",
263
+ end="\r\n",
264
+ file=file_descriptor,
265
+ )
266
+
267
+ print(
268
+ f"CLAIMED-SCORE: {calc_score(self)}",
269
+ end="\r\n",
270
+ file=file_descriptor,
271
+ )
272
+ ops = f"@{self.station.get('Call','')}"
273
+ list_of_ops = self.database.get_ops()
274
+ for op in list_of_ops:
275
+ ops += f", {op.get('Operator', '')}"
276
+ print(
277
+ f"OPERATORS: {ops}",
278
+ end="\r\n",
279
+ file=file_descriptor,
280
+ )
281
+ print(
282
+ f"NAME: {self.station.get('Name', '')}",
283
+ end="\r\n",
284
+ file=file_descriptor,
285
+ )
286
+ print(
287
+ f"ADDRESS: {self.station.get('Street1', '')}",
288
+ end="\r\n",
289
+ file=file_descriptor,
290
+ )
291
+ print(
292
+ f"ADDRESS-CITY: {self.station.get('City', '')}",
293
+ end="\r\n",
294
+ file=file_descriptor,
295
+ )
296
+ print(
297
+ f"ADDRESS-STATE-PROVINCE: {self.station.get('State', '')}",
298
+ end="\r\n",
299
+ file=file_descriptor,
300
+ )
301
+ print(
302
+ f"ADDRESS-POSTALCODE: {self.station.get('Zip', '')}",
303
+ end="\r\n",
304
+ file=file_descriptor,
305
+ )
306
+ print(
307
+ f"ADDRESS-COUNTRY: {self.station.get('Country', '')}",
308
+ end="\r\n",
309
+ file=file_descriptor,
310
+ )
311
+ print(
312
+ f"EMAIL: {self.station.get('Email', '')}",
313
+ end="\r\n",
314
+ file=file_descriptor,
315
+ )
316
+ for contact in log:
317
+ the_date_and_time = contact.get("TS", "")
318
+ themode = contact.get("Mode", "")
319
+ if themode == "LSB" or themode == "USB":
320
+ themode = "PH"
321
+ frequency = str(int(contact.get("Freq", "0"))).rjust(5)
322
+
323
+ loggeddate = the_date_and_time[:10]
324
+ loggedtime = the_date_and_time[11:13] + the_date_and_time[14:16]
325
+ print(
326
+ f"QSO: {frequency} {themode} {loggeddate} {loggedtime} "
327
+ f"{contact.get('StationPrefix', '').ljust(13)} "
328
+ f"{str(contact.get('SentNr', '')).upper()} "
329
+ f"{contact.get('Call', '').ljust(13)} "
330
+ f"{str(contact.get('Name', '')).ljust(11)} "
331
+ f"{str(contact.get('Sect', '')).ljust(5)}",
332
+ end="\r\n",
333
+ file=file_descriptor,
334
+ )
335
+ print("END-OF-LOG:", end="\r\n", file=file_descriptor)
336
+ self.show_message_box(f"Cabrillo saved to: {filename}")
337
+ except IOError as exception:
338
+ logger.critical("cabrillo: IO error: %s, writing to %s", exception, filename)
339
+ self.show_message_box(f"Error saving Cabrillo: {exception} {filename}")
340
+ return
341
+
342
+
343
+ def recalculate_mults(self):
344
+ """Recalculates multipliers after change in logged qso."""
345
+
346
+ all_contacts = self.database.fetch_all_contacts_asc()
347
+ for contact in all_contacts:
348
+ time_stamp = contact.get("TS", "")
349
+ sect = contact.get("Sect", "")
350
+ band = contact.get("Band", "")
351
+ query = (
352
+ f"select count(*) as sect_count from dxlog where TS < '{time_stamp}' "
353
+ f"and Sect = '{sect}' "
354
+ f"and Band = '{band}' "
355
+ f"and ContestNR = {self.pref.get('contest', '1')};"
356
+ )
357
+ result = self.database.exec_sql(query)
358
+ count = result.get("sect_count", 1)
359
+ if count == 0 and contact.get("Points", 0) == 1 and sect != "DX":
360
+ contact["IsMultiplier1"] = 1
361
+ else:
362
+ contact["IsMultiplier1"] = 0
363
+ self.database.change_contact(contact)
364
+ cmd = {}
365
+ cmd["cmd"] = "UPDATELOG"
366
+ cmd["station"] = platform.node()
367
+ self.multicast_interface.send_as_json(cmd)
@@ -181,7 +181,7 @@ def calc_score(self):
181
181
 
182
182
  def adif(self):
183
183
  """Call the generate ADIF function"""
184
- gen_adif(self, cabrillo_name, "NAQP-SSB")
184
+ gen_adif(self, cabrillo_name, "WEEKLY-PHONE-TEST")
185
185
 
186
186
 
187
187
  def cabrillo(self):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: not1mm
3
- Version: 24.6.1
3
+ Version: 24.7.12
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
@@ -44,9 +44,19 @@ Requires-Dist: Levenshtein
44
44
  [![Code Maturity:Snot Nosed](https://img.shields.io/badge/Code%20Maturity-Snot%20Nosed-red)](https://xkcd.com/1695/)
45
45
  [![PyPI - Downloads](https://img.shields.io/pypi/dm/not1mm)](https://pypi.org/project/not1mm/)
46
46
 
47
+ ![main screen](https://github.com/mbridak/not1mm/raw/master/pic/main.png)
48
+
47
49
  - [Not1MM](#not1mm)
48
50
  - [What and why is Not1MM](#what-and-why-is-not1mm)
51
+ - [The elephant in the room](#the-elephant-in-the-room)
52
+ - [The What](#the-what)
53
+ - [Target Environment](#target-environment)
54
+ - [The Why](#the-why)
55
+ - [General logging](#general-logging)
49
56
  - [Current state](#current-state)
57
+ - [Code maturity](#code-maturity)
58
+ - [Data and RTTY](#data-and-rtty)
59
+ - [Other not so supported contests](#other-not-so-supported-contests)
50
60
  - [Our Code Contributors ✨](#our-code-contributors-)
51
61
  - [List of should be working contests](#list-of-should-be-working-contests)
52
62
  - [Recent Changes](#recent-changes)
@@ -67,17 +77,18 @@ Requires-Dist: Levenshtein
67
77
  - [After the install](#after-the-install)
68
78
  - [You may or may not get a warning message like](#you-may-or-may-not-get-a-warning-message-like)
69
79
  - [Or this fan favorite](#or-this-fan-favorite)
80
+ - [Update your CTY and SCP files](#update-your-cty-and-scp-files)
70
81
  - [Various data file locations](#various-data-file-locations)
71
82
  - [Data](#data)
72
83
  - [Config](#config)
73
- - [The database](#the-database)
84
+ - [The Database](#the-database)
74
85
  - [Why](#why)
75
- - [The first one](#the-first-one)
86
+ - [The first one is free](#the-first-one-is-free)
76
87
  - [Why limit yourself](#why-limit-yourself)
77
88
  - [Revisiting an old friend](#revisiting-an-old-friend)
78
- - [Station Settings dialog (REQUIRED)](#station-settings-dialog-required)
89
+ - [Station Settings dialog (It's REQUIRED Russ)](#station-settings-dialog-its-required-russ)
79
90
  - [Changing station information](#changing-station-information)
80
- - [Selecting a contest (REQUIRED)](#selecting-a-contest-required)
91
+ - [Selecting a contest (It's REQUIRED Russ)](#selecting-a-contest-its-required-russ)
81
92
  - [Selecting a new contest](#selecting-a-new-contest)
82
93
  - [Selecting an existing contest as the current contest](#selecting-an-existing-contest-as-the-current-contest)
83
94
  - [Editing existing contest parameters](#editing-existing-contest-parameters)
@@ -113,34 +124,64 @@ Requires-Dist: Levenshtein
113
124
 
114
125
  ## What and why is Not1MM
115
126
 
127
+ ### The elephant in the room
128
+
116
129
  Not1MM's interface is a blatant ripoff of N1MM. It is NOT N1MM and any problem
117
130
  you have with this software should in no way reflect on their software.
118
131
 
119
- If you use Windows(tm), you should run away from Not1MM and use someother
120
- program.
132
+ ### The What
133
+
134
+ Not1MM attempts to be a useable amateur radio, or HAM, contest logger. It's
135
+ written in Python, 3.9+, and uses Qt6 framework for the graphical interface
136
+ and SQLite for the database.
137
+
138
+ ### Target Environment
121
139
 
122
- I personally don't use Windows(tm). While it may be possible to get N1MM working
123
- under Wine, I haven't checked. I'd rather not have to jump thru the hoops.
140
+ The primary target for this application is Linux. It may be able to run on other
141
+ platforms, BSD, Mac and Windows. But I don't have a way, or desire, to directly
142
+ support them.
124
143
 
125
- **Currently this exists for my own personal amusement**. Something to do in my
126
- free time. While I'm not watching TV, Right vs Left political 'News' programs,
127
- mind numbing 'Reality' shows etc...
144
+ ### The Why
145
+
146
+ **Currently this exists for my own personal amusement**. I've recently retired
147
+ after 35+ years working for 'The Phone Company', GTE -> Verizon -> Frontier.
148
+ And being a Gentleman of Leisure, needed something to do in my free time.
149
+ I'm a casual contester and could not find any contesting software for Linux that
150
+ I wanted to use. There is [Tucnak](http://tucnak.nagano.cz/) which is very robust
151
+ and mature. It just wasn't for me.
152
+
153
+ ### General logging
154
+
155
+ In short... Don't. There are much better general purpose QSO logging programs.
156
+ Try QLog or CQRLog.
128
157
 
129
158
  ## Current state
130
159
 
131
- The current state is "**BETA**". I've used it for a few contests, and was able
132
- to work contacts and submit a cabrillo at the end. I'm not a "Contester". So
133
- I'll add contests as/if I work them. I'm only one guy, so if you see a bug let
134
- me know. I don't do much of any Data or RTTY operating. This is why you don't
135
- see RTTY in the list of working contests. The Lord helps those who burn people
136
- at the... I mean who help themselves. Feel free to fill in that hole with a pull
137
- request.
160
+ ### Code maturity
138
161
 
139
- ![main screen](https://github.com/mbridak/not1mm/raw/master/pic/main.png)
162
+ The current state is "**BETA**".
163
+
164
+ I've used it for quite a few contests, and was able to work contacts and submit
165
+ cabrillos at the end. There are still quite a few features I'd like to implement.
166
+ And "BETA" is a sort of get out of jail free badge for coders. A safety net for
167
+ when the program craps the bed. I'm only one guy, so if you see a bug let me know.
168
+
169
+ ### Data and RTTY
170
+
171
+ I don't do much of any digital or RTTY operating. This is why you don't see RTTY in
172
+ the list of working contests. The Lord helps those who burn people at the... I
173
+ mean, who help themselves. Feel free to fill in that hole with a pull request.
174
+
175
+ ### Other not so supported contests
176
+
177
+ Of note, state QSO parties. I haven't worked any yet. And no one has submitted a PR
178
+ adding one... So there you go. In the near future I'll probably add California, guess
179
+ where I live, and the 4 states QSO party.
140
180
 
141
181
  ## Our Code Contributors ✨
142
182
 
143
- I wish to thank those who've contributed to the project.
183
+ I wish to thank those who've contributed to the project. Below is an automatically
184
+ generated, 'cause I'm lazy, list of those who've submitted PR's.
144
185
 
145
186
  <a href="https://github.com/mbridak/not1mm/graphs/contributors">
146
187
  <img src="https://contrib.rocks/image?repo=mbridak/not1mm" alt="Avatar icons for code contributors." />
@@ -182,6 +223,7 @@ I wish to thank those who've contributed to the project.
182
223
 
183
224
  ## Recent Changes
184
225
 
226
+ - [24-6-27] Corrected ADIF contest_id for the Phone Weekly Test.
185
227
  - [24-6-1] Added leading zeros to S/N's less than 100.
186
228
 
187
229
  See [CHANGELOG.md](CHANGELOG.md) for prior changes.
@@ -243,7 +285,7 @@ source .profile
243
285
 
244
286
  </details>
245
287
 
246
- <details>
288
+ <details>REQUIRED
247
289
 
248
290
  <summary><b>Fedora 38, 39 and 40</b></summary>
249
291
 
@@ -394,6 +436,11 @@ For a more permanent solution you can place the line
394
436
  `export QT_QPA_PLATFORM=wayland` in your home directories .bashrc file. Then
395
437
  after logging out and back in you should be able to launch it normally.
396
438
 
439
+ ### Update your CTY and SCP files
440
+
441
+ After all the configuration stuff below and before operating in a contest, you
442
+ might want to update the CTY and SCP files. You can do this by choosing FILE->Update CTY and FILE->Update MASTER.SCP
443
+
397
444
  ## Various data file locations
398
445
 
399
446
  ### Data
@@ -407,7 +454,7 @@ CW macro files can be found there. Otherwise they will be found at
407
454
  Configuration file(s) can be found at the location defined by `XDG_CONFIG_HOME`.
408
455
  Otherwise they will be found at `yourhome/.config/not1mm`
409
456
 
410
- ## The database
457
+ ## The Database
411
458
 
412
459
  ### Why
413
460
 
@@ -417,7 +464,7 @@ everything shown in the Station Settings dialog. You can have one database for
417
464
  the rest of your life. Filled with hundreds of contests you've logged. Or, you
418
465
  can create a new database to hold just one contest. You do You Boo.
419
466
 
420
- ### The first one
467
+ ### The first one is free
421
468
 
422
469
  On the initial running, a database is created for you called `ham.db`. This, and
423
470
  all future databases, are located in the data directory mentioned above.
@@ -433,7 +480,7 @@ day for all I care. You can manage your own digital disaster.
433
480
  You can select a previously created databases for use by selecting
434
481
  `File` > `Open Database`.
435
482
 
436
- ## Station Settings dialog (REQUIRED)
483
+ ## Station Settings dialog (It's REQUIRED Russ)
437
484
 
438
485
  After initial run of the program or creating a new database you will need to
439
486
  fill out the Station Settings dialog that will pop up.
@@ -453,7 +500,7 @@ You can fill. You can fill. Everyone look at your keys.
453
500
  Station information can be changed any time by going to
454
501
  `File` > `Station Settings` and editing the information.
455
502
 
456
- ## Selecting a contest (REQUIRED)
503
+ ## Selecting a contest (It's REQUIRED Russ)
457
504
 
458
505
  ### Selecting a new contest
459
506