not1mm 24.3.16__py3-none-any.whl → 24.3.24__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 +288 -124
- not1mm/bandmap.py +207 -191
- not1mm/checkwindow.py +62 -109
- not1mm/data/MASTER.SCP +1077 -749
- not1mm/data/bandmap.ui +4 -4
- not1mm/data/checkwindow.ui +9 -16
- not1mm/data/cty.json +1 -1
- not1mm/data/logwindow.ui +16 -11
- not1mm/data/main.ui +16 -6
- not1mm/data/vfo.ui +64 -52
- not1mm/fsutils.py +63 -0
- not1mm/lib/about.py +4 -2
- not1mm/lib/cat_interface.py +1 -1
- not1mm/lib/cwinterface.py +1 -1
- not1mm/lib/database.py +4 -4
- not1mm/lib/edit_contact.py +2 -2
- not1mm/lib/edit_macro.py +2 -3
- not1mm/lib/edit_opon.py +2 -2
- not1mm/lib/edit_station.py +3 -3
- not1mm/lib/ham_utility.py +1 -1
- not1mm/lib/lookup.py +1 -1
- not1mm/lib/multicast.py +9 -4
- not1mm/lib/n1mm.py +1 -1
- not1mm/lib/new_contest.py +2 -2
- not1mm/lib/select_contest.py +2 -2
- not1mm/lib/settings.py +3 -4
- not1mm/lib/super_check_partial.py +8 -5
- not1mm/lib/version.py +1 -1
- not1mm/logwindow.py +62 -105
- not1mm/plugins/10_10_fall_cw.py +1 -1
- not1mm/plugins/10_10_spring_cw.py +1 -1
- not1mm/plugins/10_10_summer_phone.py +1 -1
- not1mm/plugins/10_10_winter_phone.py +1 -1
- not1mm/plugins/arrl_10m.py +1 -1
- not1mm/plugins/arrl_dx_cw.py +1 -1
- not1mm/plugins/arrl_dx_ssb.py +1 -1
- not1mm/plugins/arrl_field_day.py +1 -1
- not1mm/plugins/arrl_ss_cw.py +1 -1
- not1mm/plugins/arrl_ss_phone.py +1 -1
- not1mm/plugins/arrl_vhf_jan.py +1 -1
- not1mm/plugins/arrl_vhf_jun.py +1 -1
- not1mm/plugins/arrl_vhf_sep.py +1 -1
- not1mm/plugins/canada_day.py +1 -1
- not1mm/plugins/cq_160_cw.py +1 -1
- not1mm/plugins/cq_160_ssb.py +1 -1
- not1mm/plugins/cq_wpx_cw.py +1 -1
- not1mm/plugins/cq_wpx_ssb.py +1 -1
- not1mm/plugins/cq_ww_cw.py +1 -1
- not1mm/plugins/cq_ww_ssb.py +1 -1
- not1mm/plugins/cwt.py +1 -1
- not1mm/plugins/general_logging.py +1 -1
- not1mm/plugins/iaru_hf.py +1 -1
- not1mm/plugins/jidx_cw.py +1 -1
- not1mm/plugins/jidx_ph.py +1 -1
- not1mm/plugins/naqp_cw.py +1 -1
- not1mm/plugins/naqp_ssb.py +1 -1
- not1mm/plugins/phone_weekly_test.py +1 -1
- not1mm/plugins/stew_perry_topband.py +1 -1
- not1mm/plugins/winter_field_day.py +1 -1
- not1mm/vfo.py +78 -98
- {not1mm-24.3.16.dist-info → not1mm-24.3.24.dist-info}/METADATA +67 -55
- {not1mm-24.3.16.dist-info → not1mm-24.3.24.dist-info}/RECORD +68 -66
- testing/detectdark.py +35 -0
- testing/test.py +13 -11
- {not1mm-24.3.16.dist-info → not1mm-24.3.24.dist-info}/LICENSE +0 -0
- {not1mm-24.3.16.dist-info → not1mm-24.3.24.dist-info}/WHEEL +0 -0
- {not1mm-24.3.16.dist-info → not1mm-24.3.24.dist-info}/entry_points.txt +0 -0
- {not1mm-24.3.16.dist-info → not1mm-24.3.24.dist-info}/top_level.txt +0 -0
not1mm/bandmap.py
CHANGED
@@ -6,56 +6,27 @@ GPL V3
|
|
6
6
|
"""
|
7
7
|
|
8
8
|
# pylint: disable=unused-import, c-extension-no-member, no-member, invalid-name, too-many-lines
|
9
|
-
# pylint: disable=logging-fstring-interpolation, line-too-long
|
10
|
-
|
11
|
-
from datetime import datetime, timezone
|
12
|
-
from decimal import Decimal
|
13
|
-
from json import loads
|
14
|
-
from pathlib import Path
|
9
|
+
# pylint: disable=logging-fstring-interpolation, line-too-long, no-name-in-module
|
15
10
|
|
16
11
|
import logging
|
17
12
|
import os
|
18
|
-
|
19
|
-
# import pkgutil
|
20
13
|
import platform
|
21
|
-
import sys
|
22
14
|
import sqlite3
|
15
|
+
from datetime import datetime, timezone
|
16
|
+
from decimal import Decimal
|
17
|
+
from json import loads
|
23
18
|
|
24
|
-
from PyQt5 import QtCore, QtGui
|
25
|
-
from PyQt5 import
|
26
|
-
from PyQt5 import QtWidgets, uic
|
19
|
+
from PyQt5 import QtCore, QtGui, QtWidgets, uic, QtNetwork
|
20
|
+
from PyQt5.QtCore import Qt
|
27
21
|
|
22
|
+
import not1mm.fsutils as fsutils
|
28
23
|
from not1mm.lib.multicast import Multicast
|
29
24
|
|
30
|
-
|
25
|
+
logger = logging.getLogger(__name__)
|
31
26
|
|
32
27
|
PIXELSPERSTEP = 10
|
33
28
|
UPDATE_INTERVAL = 2000
|
34
29
|
|
35
|
-
# DeprecationWarning: 'pkgutil.get_loader' is deprecated and slated for removal in Python 3.14
|
36
|
-
# loader = pkgutil.get_loader("not1mm")
|
37
|
-
# WORKING_PATH = os.path.dirname(loader.get_filename())
|
38
|
-
WORKING_PATH = os.path.dirname(__loader__.get_filename())
|
39
|
-
|
40
|
-
if "XDG_DATA_HOME" in os.environ:
|
41
|
-
DATA_PATH = os.environ.get("XDG_DATA_HOME")
|
42
|
-
else:
|
43
|
-
DATA_PATH = str(Path.home() / ".local" / "share")
|
44
|
-
DATA_PATH += "/not1mm"
|
45
|
-
|
46
|
-
if "XDG_CONFIG_HOME" in os.environ:
|
47
|
-
CONFIG_PATH = os.environ.get("XDG_CONFIG_HOME")
|
48
|
-
else:
|
49
|
-
CONFIG_PATH = str(Path.home() / ".config")
|
50
|
-
CONFIG_PATH += "/not1mm"
|
51
|
-
|
52
|
-
DARK_STYLESHEET = ""
|
53
|
-
|
54
|
-
PREF = {}
|
55
|
-
if os.path.exists(CONFIG_PATH + "/not1mm.json"):
|
56
|
-
with open(CONFIG_PATH + "/not1mm.json", "rt", encoding="utf-8") as file_descriptor:
|
57
|
-
PREF = loads(file_descriptor.read())
|
58
|
-
|
59
30
|
|
60
31
|
class Band:
|
61
32
|
"""the band"""
|
@@ -108,16 +79,20 @@ class Database:
|
|
108
79
|
self.db.row_factory = self.row_factory
|
109
80
|
self.cursor = self.db.cursor()
|
110
81
|
sql_command = (
|
111
|
-
"create table spots("
|
112
|
-
"ts DATETIME NOT NULL, "
|
82
|
+
"create table spots ("
|
113
83
|
"callsign VARCHAR(15) NOT NULL, "
|
84
|
+
"ts DATETIME NOT NULL, "
|
114
85
|
"freq DOUBLE NOT NULL, "
|
115
|
-
"band VARCHAR(6), "
|
116
86
|
"mode VARCHAR(6), "
|
117
87
|
"spotter VARCHAR(15) NOT NULL, "
|
118
88
|
"comment VARCHAR(45));"
|
119
89
|
)
|
120
90
|
self.cursor.execute(sql_command)
|
91
|
+
|
92
|
+
self.cursor.execute("CREATE INDEX spot_call_index ON spots (callsign);")
|
93
|
+
self.cursor.execute("CREATE INDEX spot_freq_index ON spots (freq);")
|
94
|
+
self.cursor.execute("CREATE INDEX spot_ts_index ON spots (ts);")
|
95
|
+
|
121
96
|
self.db.commit()
|
122
97
|
|
123
98
|
@staticmethod
|
@@ -175,31 +150,27 @@ class Database:
|
|
175
150
|
If False, do not delete any previous spots with the same callsign.
|
176
151
|
Default is True.
|
177
152
|
|
178
|
-
|
179
153
|
Returns
|
180
154
|
-------
|
181
155
|
Nothing.
|
182
156
|
"""
|
183
157
|
try:
|
184
158
|
if erase:
|
185
|
-
delete_call =
|
186
|
-
|
187
|
-
)
|
188
|
-
self.cursor.execute(delete_call)
|
159
|
+
delete_call = "delete from spots where callsign = ?;"
|
160
|
+
self.cursor.execute(delete_call, (spot.get("callsign"),))
|
189
161
|
self.db.commit()
|
190
162
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
self.cursor.execute(sql, tuple(values))
|
163
|
+
self.cursor.execute(
|
164
|
+
"INSERT INTO spots(callsign, ts, freq, mode, spotter, comment) VALUES(?, ?, ?, ?, ?, ?)",
|
165
|
+
(
|
166
|
+
spot["callsign"],
|
167
|
+
spot["ts"],
|
168
|
+
spot["freq"],
|
169
|
+
spot.get("mode", None),
|
170
|
+
spot["spotter"],
|
171
|
+
spot.get("comment", None),
|
172
|
+
),
|
173
|
+
)
|
203
174
|
self.db.commit()
|
204
175
|
except sqlite3.IntegrityError:
|
205
176
|
...
|
@@ -239,7 +210,8 @@ class Database:
|
|
239
210
|
A list of dicts.
|
240
211
|
"""
|
241
212
|
self.cursor.execute(
|
242
|
-
|
213
|
+
"select * from spots where freq >= ? and freq <= ? order by freq ASC;",
|
214
|
+
(start, end),
|
243
215
|
)
|
244
216
|
return self.cursor.fetchall()
|
245
217
|
|
@@ -261,7 +233,8 @@ class Database:
|
|
261
233
|
"""
|
262
234
|
|
263
235
|
self.cursor.execute(
|
264
|
-
|
236
|
+
"select * from spots where freq > ? and freq <= ? order by freq ASC;",
|
237
|
+
({current}, limit),
|
265
238
|
)
|
266
239
|
return self.cursor.fetchone()
|
267
240
|
|
@@ -284,8 +257,8 @@ class Database:
|
|
284
257
|
"""
|
285
258
|
|
286
259
|
self.cursor.execute(
|
287
|
-
|
288
|
-
|
260
|
+
"select * from spots where freq >= ? and freq <= ? and callsign like ?;",
|
261
|
+
(start, end, f"%{dx}%"),
|
289
262
|
)
|
290
263
|
return self.cursor.fetchone()
|
291
264
|
|
@@ -305,7 +278,8 @@ class Database:
|
|
305
278
|
A list of dicts.
|
306
279
|
"""
|
307
280
|
self.cursor.execute(
|
308
|
-
|
281
|
+
"select * from spots where freq < ? and freq >= ? order by freq DESC;",
|
282
|
+
(current, limit),
|
309
283
|
)
|
310
284
|
return self.cursor.fetchone()
|
311
285
|
|
@@ -323,14 +297,13 @@ class Database:
|
|
323
297
|
None
|
324
298
|
"""
|
325
299
|
self.cursor.execute(
|
326
|
-
|
300
|
+
"delete from spots where ts < datetime('now', ?);",
|
301
|
+
(f"-{minutes} minutes",),
|
327
302
|
)
|
328
303
|
|
329
304
|
|
330
|
-
class
|
331
|
-
"""
|
332
|
-
The main window
|
333
|
-
"""
|
305
|
+
class BandMapWindow(QtWidgets.QDockWidget):
|
306
|
+
"""The BandMapWindow class."""
|
334
307
|
|
335
308
|
zoom = 5
|
336
309
|
currentBand = Band("20m")
|
@@ -346,14 +319,14 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
346
319
|
bandwidth_mark = []
|
347
320
|
worked_list = {}
|
348
321
|
multicast_interface = None
|
322
|
+
text_color = QtGui.QColor(45, 45, 45)
|
349
323
|
|
350
324
|
def __init__(self, *args, **kwargs):
|
351
325
|
super().__init__(*args, **kwargs)
|
352
326
|
self._udpwatch = None
|
353
|
-
|
354
|
-
uic.loadUi(
|
355
|
-
|
356
|
-
self.setStyleSheet(DARK_STYLESHEET)
|
327
|
+
|
328
|
+
uic.loadUi(fsutils.APP_DATA_PATH / "bandmap.ui", self)
|
329
|
+
self.settings = self.get_settings()
|
357
330
|
self.agetime = self.clear_spot_olderSpinBox.value()
|
358
331
|
self.clear_spot_olderSpinBox.valueChanged.connect(self.spot_aging_changed)
|
359
332
|
self.clearButton.clicked.connect(self.clear_spots)
|
@@ -375,35 +348,75 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
375
348
|
self.update_timer = QtCore.QTimer()
|
376
349
|
self.update_timer.timeout.connect(self.update_station_timer)
|
377
350
|
self.update_timer.start(UPDATE_INTERVAL)
|
351
|
+
self.setDarkMode(self.settings.get("darkmode", False))
|
378
352
|
self.update()
|
379
353
|
self.multicast_interface = Multicast(
|
380
|
-
|
381
|
-
|
382
|
-
|
354
|
+
self.settings.get("multicast_group", "239.1.1.1"),
|
355
|
+
self.settings.get("multicast_port", 2239),
|
356
|
+
self.settings.get("interface_ip", "0.0.0.0"),
|
383
357
|
)
|
384
358
|
self.multicast_interface.ready_read_connect(self.watch_udp)
|
385
359
|
self.request_workedlist()
|
360
|
+
self.request_contest()
|
361
|
+
|
362
|
+
def get_settings(self) -> dict:
|
363
|
+
"""Get the settings."""
|
364
|
+
if os.path.exists(fsutils.CONFIG_FILE):
|
365
|
+
with open(fsutils.CONFIG_FILE, "rt", encoding="utf-8") as file_descriptor:
|
366
|
+
return loads(file_descriptor.read())
|
367
|
+
|
368
|
+
def setDarkMode(self, setdarkmode=False):
|
369
|
+
"""testing"""
|
370
|
+
|
371
|
+
if setdarkmode:
|
372
|
+
darkPalette = QtGui.QPalette()
|
373
|
+
darkColor = QtGui.QColor(45, 45, 45)
|
374
|
+
self.text_color = Qt.white
|
375
|
+
disabledColor = QtGui.QColor(127, 127, 127)
|
376
|
+
darkPalette.setColor(QtGui.QPalette.Window, darkColor)
|
377
|
+
darkPalette.setColor(QtGui.QPalette.WindowText, Qt.white)
|
378
|
+
darkPalette.setColor(QtGui.QPalette.Base, QtGui.QColor(18, 18, 18))
|
379
|
+
darkPalette.setColor(QtGui.QPalette.AlternateBase, darkColor)
|
380
|
+
darkPalette.setColor(QtGui.QPalette.Text, Qt.white)
|
381
|
+
darkPalette.setColor(
|
382
|
+
QtGui.QPalette.Disabled, QtGui.QPalette.Text, disabledColor
|
383
|
+
)
|
384
|
+
darkPalette.setColor(QtGui.QPalette.Button, darkColor)
|
385
|
+
darkPalette.setColor(QtGui.QPalette.ButtonText, Qt.white)
|
386
|
+
darkPalette.setColor(
|
387
|
+
QtGui.QPalette.Disabled, QtGui.QPalette.ButtonText, disabledColor
|
388
|
+
)
|
389
|
+
darkPalette.setColor(QtGui.QPalette.BrightText, Qt.red)
|
390
|
+
darkPalette.setColor(QtGui.QPalette.Link, QtGui.QColor(42, 130, 218))
|
391
|
+
darkPalette.setColor(QtGui.QPalette.Highlight, QtGui.QColor(42, 130, 218))
|
392
|
+
darkPalette.setColor(QtGui.QPalette.HighlightedText, Qt.black)
|
393
|
+
darkPalette.setColor(
|
394
|
+
QtGui.QPalette.Disabled, QtGui.QPalette.HighlightedText, disabledColor
|
395
|
+
)
|
386
396
|
|
387
|
-
|
388
|
-
|
389
|
-
|
397
|
+
self.setPalette(darkPalette)
|
398
|
+
self.callsignField.setPalette(darkPalette)
|
399
|
+
self.update()
|
400
|
+
else:
|
401
|
+
palette = self.style().standardPalette()
|
402
|
+
self.setPalette(palette)
|
403
|
+
self.callsignField.setPalette(palette)
|
404
|
+
self.text_color = Qt.black
|
405
|
+
self.update()
|
390
406
|
|
391
407
|
def connect(self):
|
392
|
-
"""
|
408
|
+
"""Connect to the cluster."""
|
409
|
+
if not self.callsignField.text():
|
410
|
+
self.callsignField.setFocus()
|
411
|
+
return
|
393
412
|
if self.connected is True:
|
394
|
-
self.
|
395
|
-
self.connected = False
|
396
|
-
self.connectButton.setStyleSheet("color: red;")
|
397
|
-
self.connectButton.setText("Closed")
|
413
|
+
self.close_cluster()
|
398
414
|
return
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
server = PREF.get("cluster_server", "dxc.nc7j.com")
|
405
|
-
port = PREF.get("cluster_port", 7373)
|
406
|
-
logger.debug("%s", f"{server} {port}")
|
415
|
+
# refresh settings
|
416
|
+
self.settings = self.get_settings()
|
417
|
+
server = self.settings.get("cluster_server", "dxc.nc7j.com")
|
418
|
+
port = self.settings.get("cluster_port", 7373)
|
419
|
+
logger.info(f"connecting to dx cluster {server} {port}")
|
407
420
|
self.socket.connectToHost(server, port)
|
408
421
|
self.connectButton.setStyleSheet("color: white;")
|
409
422
|
self.connectButton.setText("Connecting")
|
@@ -514,8 +527,13 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
514
527
|
cmd["spots"] = []
|
515
528
|
self.multicast_interface.send_as_json(cmd)
|
516
529
|
continue
|
517
|
-
if packet.get("cmd", "") == "
|
518
|
-
self.
|
530
|
+
if packet.get("cmd", "") == "CONTESTSTATUS":
|
531
|
+
if not self.callsignField.text():
|
532
|
+
self.callsignField.setText(packet.get("operator", "").upper())
|
533
|
+
self.callsignField.selectAll()
|
534
|
+
continue
|
535
|
+
if packet.get("cmd", "") == "DARKMODE":
|
536
|
+
self.setDarkMode(packet.get("state", False))
|
519
537
|
|
520
538
|
def spot_clicked(self):
|
521
539
|
"""dunno"""
|
@@ -536,13 +554,23 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
536
554
|
cmd["station"] = platform.node()
|
537
555
|
self.multicast_interface.send_as_json(cmd)
|
538
556
|
|
557
|
+
def request_contest(self):
|
558
|
+
"""Request active contest from logger"""
|
559
|
+
cmd = {}
|
560
|
+
cmd["cmd"] = "GETCONTESTSTATUS"
|
561
|
+
cmd["station"] = platform.node()
|
562
|
+
self.multicast_interface.send_as_json(cmd)
|
563
|
+
|
539
564
|
def update_station_timer(self):
|
540
565
|
"""doc"""
|
541
566
|
self.update_stations()
|
542
567
|
|
543
568
|
def update(self):
|
544
569
|
"""doc"""
|
545
|
-
|
570
|
+
try:
|
571
|
+
self.update_timer.setInterval(UPDATE_INTERVAL)
|
572
|
+
except AttributeError:
|
573
|
+
...
|
546
574
|
self.clear_all_callsign_from_scene()
|
547
575
|
self.clear_freq_mark(self.rxMark)
|
548
576
|
self.clear_freq_mark(self.txMark)
|
@@ -562,12 +590,13 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
562
590
|
i * PIXELSPERSTEP,
|
563
591
|
length + 10,
|
564
592
|
i * PIXELSPERSTEP,
|
565
|
-
QtGui.QPen(
|
593
|
+
QtGui.QPen(self.text_color),
|
566
594
|
)
|
567
595
|
if i % 5 == 0: # Add Frequency
|
568
596
|
freq = self.currentBand.start + step * i
|
569
597
|
text = f"{freq:.3f}"
|
570
598
|
self.something = self.bandmap_scene.addText(text)
|
599
|
+
self.something.setDefaultTextColor(self.text_color)
|
571
600
|
self.something.setPos(
|
572
601
|
-(self.something.boundingRect().width()) + 10,
|
573
602
|
i * PIXELSPERSTEP - (self.something.boundingRect().height() / 2),
|
@@ -610,7 +639,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
610
639
|
|
611
640
|
def Freq2ScenePos(self, freq: float):
|
612
641
|
"""doc"""
|
613
|
-
if freq < self.currentBand.start or freq > self.currentBand.end:
|
642
|
+
if not freq or freq < self.currentBand.start or freq > self.currentBand.end:
|
614
643
|
return QtCore.QPointF()
|
615
644
|
step, _digits = self.determine_step_digits()
|
616
645
|
ret = QtCore.QPointF(
|
@@ -641,7 +670,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
641
670
|
# anim.setEndValue(int(freq_pos - (self.height() / 2) + 80))
|
642
671
|
# anim.start(QtCore.QAbstractAnimation.DeletionPolicy.DeleteWhenStopped)
|
643
672
|
|
644
|
-
def drawfreqmark(self, freq, _step, color, currentPolygon):
|
673
|
+
def drawfreqmark(self, freq, _step, color, currentPolygon) -> None:
|
645
674
|
"""doc"""
|
646
675
|
|
647
676
|
self.clear_freq_mark(currentPolygon)
|
@@ -660,7 +689,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
660
689
|
brush = QtGui.QBrush(color)
|
661
690
|
currentPolygon.append(self.bandmap_scene.addPolygon(poly, pen, brush))
|
662
691
|
|
663
|
-
def draw_bandwidth(self, freq, _step, color, currentPolygon):
|
692
|
+
def draw_bandwidth(self, freq, _step, color, currentPolygon) -> None:
|
664
693
|
"""bandwidth"""
|
665
694
|
logger.debug("%s", f"mark:{currentPolygon} f:{freq} b:{self.bandwidth}")
|
666
695
|
self.clear_freq_mark(currentPolygon)
|
@@ -687,16 +716,23 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
687
716
|
def update_stations(self):
|
688
717
|
"""doc"""
|
689
718
|
self.update_timer.setInterval(UPDATE_INTERVAL)
|
719
|
+
if not self.connected:
|
720
|
+
return
|
721
|
+
|
690
722
|
self.clear_all_callsign_from_scene()
|
691
723
|
self.spot_aging()
|
692
724
|
step, _digits = self.determine_step_digits()
|
693
725
|
|
694
726
|
result = self.spots.getspotsinband(self.currentBand.start, self.currentBand.end)
|
727
|
+
logger.debug(
|
728
|
+
f"{len(result)} spots in range {self.currentBand.start} - {self.currentBand.end}"
|
729
|
+
)
|
730
|
+
|
695
731
|
entity = ""
|
696
732
|
if result:
|
697
733
|
min_y = 0.0
|
698
734
|
for items in result:
|
699
|
-
pen_color =
|
735
|
+
pen_color = self.text_color
|
700
736
|
if items.get("comment") == "MARKED":
|
701
737
|
pen_color = QtGui.QColor(47, 47, 255)
|
702
738
|
if items.get("callsign") in self.worked_list:
|
@@ -754,23 +790,22 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
754
790
|
|
755
791
|
return (step, digits)
|
756
792
|
|
757
|
-
def set_band(self, band: str, savePrevBandZoom: bool):
|
758
|
-
"""
|
793
|
+
def set_band(self, band: str, savePrevBandZoom: bool) -> None:
|
794
|
+
"""Change band being shown."""
|
759
795
|
logger.debug("%s", f"{band} {savePrevBandZoom}")
|
760
796
|
if band != self.currentBand.name:
|
761
797
|
if savePrevBandZoom:
|
762
798
|
self.saveCurrentZoom()
|
763
799
|
self.currentBand = Band(band)
|
764
|
-
# self.zoom = self.savedZoom(band)
|
765
800
|
self.update()
|
766
801
|
|
767
|
-
def spot_aging(self):
|
768
|
-
"""
|
802
|
+
def spot_aging(self) -> None:
|
803
|
+
"""Delete spots older than age time."""
|
769
804
|
if self.agetime:
|
770
805
|
self.spots.delete_spots(self.agetime)
|
771
806
|
|
772
|
-
def clear_all_callsign_from_scene(self):
|
773
|
-
"""
|
807
|
+
def clear_all_callsign_from_scene(self) -> None:
|
808
|
+
"""Remove callsigns from the scene."""
|
774
809
|
for items in self.textItemList:
|
775
810
|
self.bandmap_scene.removeItem(items)
|
776
811
|
self.textItemList.clear()
|
@@ -778,70 +813,69 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
778
813
|
self.bandmap_scene.removeItem(items)
|
779
814
|
self.lineitemlist.clear()
|
780
815
|
|
781
|
-
def clear_freq_mark(self, currentPolygon):
|
782
|
-
"""
|
816
|
+
def clear_freq_mark(self, currentPolygon) -> None:
|
817
|
+
"""Remove frequency marks from the scene."""
|
783
818
|
if currentPolygon:
|
784
819
|
for mark in currentPolygon:
|
785
820
|
self.bandmap_scene.removeItem(mark)
|
786
821
|
currentPolygon.clear()
|
787
822
|
|
788
|
-
def receive(self):
|
789
|
-
"""
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
"""doc"""
|
823
|
+
def receive(self) -> None:
|
824
|
+
"""Process waiting bytes"""
|
825
|
+
while self.socket.bytesAvailable():
|
826
|
+
data = self.socket.readLine(1000)
|
827
|
+
data = str(data, "utf-8").strip()
|
828
|
+
|
829
|
+
if "login:" in data or "call:" in data or "callsign:" in data:
|
830
|
+
self.send_command(self.callsignField.text())
|
831
|
+
self.send_command(self.settings.get("cluster_filter", ""))
|
832
|
+
self.send_command("set dx extension Section")
|
833
|
+
self.send_command(
|
834
|
+
"set dx mode " + self.settings.get("cluster_mode", "OPEN")
|
835
|
+
)
|
836
|
+
return
|
837
|
+
if "DX de" in data:
|
838
|
+
parts = data.split()
|
839
|
+
spotter = parts[2]
|
840
|
+
freq = parts[3]
|
841
|
+
dx = parts[4]
|
842
|
+
_time = parts[-1]
|
843
|
+
comment = " ".join(parts[5:-1])
|
844
|
+
# spot = DxSpot()
|
845
|
+
spot = {}
|
846
|
+
spot["ts"] = datetime.now(timezone.utc).isoformat(" ")[:19]
|
847
|
+
spot["callsign"] = dx
|
848
|
+
spot["spotter"] = spotter
|
849
|
+
spot["comment"] = comment
|
850
|
+
logger.debug(f"{spot}")
|
851
|
+
try:
|
852
|
+
spot["freq"] = float(freq) / 1000
|
853
|
+
self.spots.addspot(spot)
|
854
|
+
except ValueError:
|
855
|
+
logger.debug(f"couldn't parse freq from datablock {data}")
|
856
|
+
return
|
857
|
+
if self.callsignField.text().upper() in data:
|
858
|
+
self.connectButton.setStyleSheet("color: green;")
|
859
|
+
self.connectButton.setText("Connected")
|
860
|
+
logger.debug(f"callsign login acknowledged {data}")
|
861
|
+
|
862
|
+
def maybeconnected(self) -> None:
|
863
|
+
"""Update visual state of the connect button."""
|
830
864
|
self.connectButton.setStyleSheet("color: yellow;")
|
831
865
|
self.connectButton.setText("Connecting")
|
832
866
|
|
833
|
-
def socket_error(self):
|
834
|
-
"""
|
835
|
-
|
867
|
+
def socket_error(self) -> None:
|
868
|
+
"""Oopsie"""
|
869
|
+
logger.warning("An Error occurred.")
|
836
870
|
|
837
|
-
def disconnected(self):
|
838
|
-
"""
|
871
|
+
def disconnected(self) -> None:
|
872
|
+
"""Called when socket is disconnected."""
|
839
873
|
self.connected = False
|
840
874
|
self.connectButton.setStyleSheet("color: red;")
|
841
875
|
self.connectButton.setText("Closed")
|
842
876
|
|
843
|
-
def send_command(self, cmd: str):
|
844
|
-
"""
|
877
|
+
def send_command(self, cmd: str) -> None:
|
878
|
+
"""Send a command to the cluster."""
|
845
879
|
cmd += "\r\n"
|
846
880
|
tosend = bytes(cmd, encoding="ascii")
|
847
881
|
logger.debug("%s", f"{tosend}")
|
@@ -849,44 +883,26 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
849
883
|
if self.socket.isOpen():
|
850
884
|
self.socket.write(tosend)
|
851
885
|
|
852
|
-
def clear_spots(self):
|
853
|
-
"""
|
886
|
+
def clear_spots(self) -> None:
|
887
|
+
"""Delete all spots from the database."""
|
854
888
|
self.spots.delete_spots(0)
|
855
889
|
|
856
|
-
def spot_aging_changed(self):
|
857
|
-
"""
|
890
|
+
def spot_aging_changed(self) -> None:
|
891
|
+
"""Called when spot aging spinbox is changed."""
|
858
892
|
self.agetime = self.clear_spot_olderSpinBox.value()
|
859
893
|
|
860
|
-
def showContextMenu(self):
|
861
|
-
"""doc"""
|
862
|
-
|
863
|
-
|
864
|
-
def run():
|
865
|
-
"""doc"""
|
866
|
-
sys.exit(app.exec())
|
867
|
-
|
868
|
-
|
869
|
-
logger = logging.getLogger("__main__")
|
870
|
-
handler = logging.StreamHandler()
|
871
|
-
formatter = logging.Formatter(
|
872
|
-
datefmt="%H:%M:%S",
|
873
|
-
fmt="[%(asctime)s] %(levelname)s %(module)s - %(funcName)s Line %(lineno)d:\n%(message)s",
|
874
|
-
)
|
875
|
-
handler.setFormatter(formatter)
|
876
|
-
logger.addHandler(handler)
|
877
|
-
|
878
|
-
if Path("./debug").exists():
|
879
|
-
logger.setLevel(logging.DEBUG)
|
880
|
-
logger.debug("debugging on")
|
881
|
-
else:
|
882
|
-
logger.setLevel(logging.WARNING)
|
883
|
-
logger.warning("debugging off")
|
884
|
-
|
885
|
-
app = QtWidgets.QApplication(sys.argv)
|
894
|
+
def showContextMenu(self) -> None:
|
895
|
+
"""doc string for the linter"""
|
886
896
|
|
897
|
+
def close_cluster(self) -> None:
|
898
|
+
"""Close socket connection"""
|
899
|
+
if self.socket and self.socket.isOpen():
|
900
|
+
logger.info("Closing dx cluster connection")
|
901
|
+
self.socket.close()
|
902
|
+
self.connected = False
|
903
|
+
self.connectButton.setStyleSheet("color: red;")
|
904
|
+
self.connectButton.setText("Closed")
|
887
905
|
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
if __name__ == "__main__":
|
892
|
-
run()
|
906
|
+
def closeEvent(self, _event: QtGui.QCloseEvent) -> None:
|
907
|
+
"""Triggered when instance closes."""
|
908
|
+
self.close_cluster()
|