not1mm 25.6.2__py3-none-any.whl → 25.6.4__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 +45 -1
- not1mm/data/dxcc_tracker.ui +25 -0
- not1mm/data/main.ui +12 -0
- not1mm/dxcc_tracker.py +135 -0
- not1mm/lib/super_check_partial.py +18 -15
- not1mm/lib/version.py +1 -1
- not1mm/statistics.py +1 -12
- {not1mm-25.6.2.dist-info → not1mm-25.6.4.dist-info}/METADATA +19 -12
- {not1mm-25.6.2.dist-info → not1mm-25.6.4.dist-info}/RECORD +13 -11
- {not1mm-25.6.2.dist-info → not1mm-25.6.4.dist-info}/WHEEL +0 -0
- {not1mm-25.6.2.dist-info → not1mm-25.6.4.dist-info}/entry_points.txt +0 -0
- {not1mm-25.6.2.dist-info → not1mm-25.6.4.dist-info}/licenses/LICENSE +0 -0
- {not1mm-25.6.2.dist-info → not1mm-25.6.4.dist-info}/top_level.txt +0 -0
not1mm/__main__.py
CHANGED
@@ -68,6 +68,7 @@ from not1mm.lib.fldigi_sendstring import FlDigi_Comm
|
|
68
68
|
import not1mm.fsutils as fsutils
|
69
69
|
from not1mm.logwindow import LogWindow
|
70
70
|
from not1mm.checkwindow import CheckWindow
|
71
|
+
from not1mm.dxcc_tracker import DXCCWindow
|
71
72
|
from not1mm.bandmap import BandMapWindow
|
72
73
|
from not1mm.vfo import VfoWindow
|
73
74
|
from not1mm.ratewindow import RateWindow
|
@@ -185,6 +186,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
185
186
|
vfo_window = None
|
186
187
|
rate_window = None
|
187
188
|
statistics_window = None
|
189
|
+
dxcc_window = None
|
188
190
|
settings = None
|
189
191
|
lookup_service = None
|
190
192
|
fldigi_util = None
|
@@ -308,6 +310,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
308
310
|
self.actionRate_Window.triggered.connect(self.launch_rate_window)
|
309
311
|
self.actionStatistics.triggered.connect(self.launch_stats_window)
|
310
312
|
self.actionVFO.triggered.connect(self.launch_vfo)
|
313
|
+
self.actionDXCC.triggered.connect(self.launch_dxcc_window)
|
311
314
|
self.actionRecalculate_Mults.triggered.connect(self.recalculate_mults)
|
312
315
|
self.actionLoad_Call_History_File.triggered.connect(self.load_call_history)
|
313
316
|
|
@@ -738,6 +741,15 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
738
741
|
self.statistics_window.hide()
|
739
742
|
self.statistics_window.message.connect(self.dockwidget_message)
|
740
743
|
|
744
|
+
self.show_splash_msg("Setting up DXCCWindow.")
|
745
|
+
self.dxcc_window = DXCCWindow()
|
746
|
+
self.dxcc_window.setObjectName("dxcc-window")
|
747
|
+
if os.environ.get("WAYLAND_DISPLAY") and old_Qt is True:
|
748
|
+
self.dxcc_window.setFeatures(dockfeatures)
|
749
|
+
self.addDockWidget(Qt.DockWidgetArea.RightDockWidgetArea, self.dxcc_window)
|
750
|
+
self.dxcc_window.hide()
|
751
|
+
self.dxcc_window.message.connect(self.dockwidget_message)
|
752
|
+
|
741
753
|
self.show_splash_msg("Setting up VFOWindow.")
|
742
754
|
self.vfo_window = VfoWindow()
|
743
755
|
self.vfo_window.setObjectName("vfo-window")
|
@@ -807,6 +819,15 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
807
819
|
self.statistics_window.hide()
|
808
820
|
self.statistics_window.setActive(False)
|
809
821
|
|
822
|
+
self.actionDXCC.setChecked(self.pref.get("dxccwindow", False))
|
823
|
+
if self.actionDXCC.isChecked():
|
824
|
+
self.dxcc_window.show()
|
825
|
+
self.dxcc_window.setActive(True)
|
826
|
+
# self.dxcc_window.get_run_and_total_qs()
|
827
|
+
else:
|
828
|
+
self.dxcc_window.hide()
|
829
|
+
self.dxcc_window.setActive(False)
|
830
|
+
|
810
831
|
self.actionVFO.setChecked(self.pref.get("vfowindow", False))
|
811
832
|
if self.actionVFO.isChecked():
|
812
833
|
self.vfo_window.show()
|
@@ -1127,9 +1148,12 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
1127
1148
|
except OSError as err:
|
1128
1149
|
logging.warning("%s", err)
|
1129
1150
|
|
1130
|
-
if msg.get("cmd", "") in ["CONTACTCHANGED", "
|
1151
|
+
if msg.get("cmd", "") in ["CONTACTCHANGED", "DELETED"]:
|
1131
1152
|
if self.statistics_window:
|
1132
1153
|
self.statistics_window.msg_from_main(msg)
|
1154
|
+
if self.dxcc_window:
|
1155
|
+
self.dxcc_window.msg_from_main(msg)
|
1156
|
+
|
1133
1157
|
if msg.get("cmd", "") == "GETCOLUMNS":
|
1134
1158
|
if hasattr(self.contest, "columns"):
|
1135
1159
|
cmd = {}
|
@@ -1618,6 +1642,8 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
1618
1642
|
self.rate_window.msg_from_main(cmd)
|
1619
1643
|
if self.statistics_window:
|
1620
1644
|
self.statistics_window.msg_from_main(cmd)
|
1645
|
+
if self.dxcc_window:
|
1646
|
+
self.dxcc_window.msg_from_main(cmd)
|
1621
1647
|
|
1622
1648
|
self.clearinputs()
|
1623
1649
|
self.edit_station_settings()
|
@@ -1660,6 +1686,8 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
1660
1686
|
self.rate_window.msg_from_main(cmd)
|
1661
1687
|
if self.statistics_window:
|
1662
1688
|
self.statistics_window.msg_from_main(cmd)
|
1689
|
+
if self.dxcc_window:
|
1690
|
+
self.dxcc_window.msg_from_main(cmd)
|
1663
1691
|
|
1664
1692
|
self.clearinputs()
|
1665
1693
|
self.open_contest()
|
@@ -1955,6 +1983,8 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
1955
1983
|
self.rate_window.msg_from_main(cmd)
|
1956
1984
|
if self.statistics_window:
|
1957
1985
|
self.statistics_window.msg_from_main(cmd)
|
1986
|
+
if self.dxcc_window:
|
1987
|
+
self.dxcc_window.msg_from_main(cmd)
|
1958
1988
|
# server
|
1959
1989
|
if self.pref.get("useserver", False) is True:
|
1960
1990
|
cmd = self.contest_settings.copy()
|
@@ -2208,6 +2238,18 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
2208
2238
|
self.statistics_window.hide()
|
2209
2239
|
self.statistics_window.setActive(False)
|
2210
2240
|
|
2241
|
+
def launch_dxcc_window(self) -> None:
|
2242
|
+
"""Launch the dxcc window"""
|
2243
|
+
self.pref["dxccwindow"] = self.actionDXCC.isChecked()
|
2244
|
+
self.write_preference()
|
2245
|
+
if self.actionDXCC.isChecked():
|
2246
|
+
self.dxcc_window.show()
|
2247
|
+
self.dxcc_window.setActive(True)
|
2248
|
+
# self.dxcc_window.get_run_and_total_qs()
|
2249
|
+
else:
|
2250
|
+
self.dxcc_window.hide()
|
2251
|
+
self.dxcc_window.setActive(False)
|
2252
|
+
|
2211
2253
|
def launch_vfo(self) -> None:
|
2212
2254
|
"""Launch the VFO window"""
|
2213
2255
|
self.pref["vfowindow"] = self.actionVFO.isChecked()
|
@@ -2890,6 +2932,8 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
2890
2932
|
self.check_window.msg_from_main(cmd)
|
2891
2933
|
if self.statistics_window:
|
2892
2934
|
self.statistics_window.msg_from_main(cmd)
|
2935
|
+
if self.dxcc_window:
|
2936
|
+
self.dxcc_window.msg_from_main(cmd)
|
2893
2937
|
|
2894
2938
|
def update_rtc_xml(self):
|
2895
2939
|
"""Update RTC XML"""
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<ui version="4.0">
|
3
|
+
<class>DockWidget</class>
|
4
|
+
<widget class="QDockWidget" name="DockWidget">
|
5
|
+
<property name="geometry">
|
6
|
+
<rect>
|
7
|
+
<x>0</x>
|
8
|
+
<y>0</y>
|
9
|
+
<width>800</width>
|
10
|
+
<height>600</height>
|
11
|
+
</rect>
|
12
|
+
</property>
|
13
|
+
<property name="windowTitle">
|
14
|
+
<string>DXCC Multiplier Tracker</string>
|
15
|
+
</property>
|
16
|
+
<widget class="QWidget" name="centralwidget">
|
17
|
+
<layout class="QVBoxLayout" name="verticalLayout">
|
18
|
+
<item>
|
19
|
+
<widget class="QTableView" name="tableView"/>
|
20
|
+
</item>
|
21
|
+
</layout>
|
22
|
+
</widget>
|
23
|
+
</widget>
|
24
|
+
</ui>
|
25
|
+
|
not1mm/data/main.ui
CHANGED
@@ -1572,6 +1572,7 @@
|
|
1572
1572
|
<addaction name="actionRate_Window"/>
|
1573
1573
|
<addaction name="actionStatistics"/>
|
1574
1574
|
<addaction name="actionVFO"/>
|
1575
|
+
<addaction name="actionDXCC"/>
|
1575
1576
|
</widget>
|
1576
1577
|
<widget class="QMenu" name="menuOther">
|
1577
1578
|
<property name="title">
|
@@ -2132,6 +2133,17 @@
|
|
2132
2133
|
<string>Alt+S</string>
|
2133
2134
|
</property>
|
2134
2135
|
</action>
|
2136
|
+
<action name="actionDXCC">
|
2137
|
+
<property name="checkable">
|
2138
|
+
<bool>true</bool>
|
2139
|
+
</property>
|
2140
|
+
<property name="text">
|
2141
|
+
<string>DXCC</string>
|
2142
|
+
</property>
|
2143
|
+
<property name="shortcut">
|
2144
|
+
<string>Alt+D</string>
|
2145
|
+
</property>
|
2146
|
+
</action>
|
2135
2147
|
</widget>
|
2136
2148
|
<resources/>
|
2137
2149
|
<connections/>
|
not1mm/dxcc_tracker.py
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
from PyQt6.QtWidgets import QDockWidget, QTableView
|
2
|
+
from PyQt6.QtSql import QSqlDatabase, QSqlQueryModel, QSqlQuery
|
3
|
+
from PyQt6.QtGui import QBrush, QColor
|
4
|
+
from PyQt6.QtCore import Qt
|
5
|
+
from PyQt6.QtCore import pyqtSignal
|
6
|
+
from PyQt6 import uic
|
7
|
+
import not1mm.fsutils as fsutils
|
8
|
+
import os
|
9
|
+
from json import loads
|
10
|
+
|
11
|
+
import logging
|
12
|
+
|
13
|
+
logger = logging.getLogger(__name__)
|
14
|
+
|
15
|
+
|
16
|
+
class CustomSqlModel(QSqlQueryModel):
|
17
|
+
def data(self, index, role):
|
18
|
+
if role == Qt.ItemDataRole.BackgroundRole:
|
19
|
+
column = index.column()
|
20
|
+
if column < 7: # Columns 0-6 (CountryPrefix and band columns)
|
21
|
+
value = super().data(index, Qt.ItemDataRole.DisplayRole)
|
22
|
+
if value and isinstance(value, (int, float)) and value > 0:
|
23
|
+
return QBrush(QColor(44, 138, 44)) # Light green color
|
24
|
+
elif value == 0:
|
25
|
+
return QBrush(QColor(155, 100, 100)) # Light red color
|
26
|
+
return super().data(index, role)
|
27
|
+
|
28
|
+
|
29
|
+
class DXCCWindow(QDockWidget):
|
30
|
+
message = pyqtSignal(dict)
|
31
|
+
dbname = None
|
32
|
+
db = None
|
33
|
+
model = None
|
34
|
+
pref = {}
|
35
|
+
|
36
|
+
def __init__(self):
|
37
|
+
super().__init__()
|
38
|
+
self.active = False
|
39
|
+
uic.loadUi(fsutils.APP_DATA_PATH / "dxcc_tracker.ui", self)
|
40
|
+
self.setWindowTitle("DXCC Multiplier Tracker")
|
41
|
+
self.load_pref()
|
42
|
+
self.db = QSqlDatabase.addDatabase("QSQLITE")
|
43
|
+
self.tableView.verticalHeader().setVisible(False)
|
44
|
+
|
45
|
+
def setActive(self, mode: bool):
|
46
|
+
self.active = bool(mode)
|
47
|
+
|
48
|
+
def update_model(self):
|
49
|
+
self.model = CustomSqlModel(self)
|
50
|
+
query = QSqlQuery(self.db)
|
51
|
+
query.prepare(
|
52
|
+
"""
|
53
|
+
SELECT CountryPrefix,
|
54
|
+
SUM(CASE WHEN Band = 1.8 THEN 1 ELSE 0 END) AS '160m',
|
55
|
+
SUM(CASE WHEN Band = 3.5 THEN 1 ELSE 0 END) AS '80m',
|
56
|
+
SUM(CASE WHEN Band = 7.0 THEN 1 ELSE 0 END) AS '40m',
|
57
|
+
SUM(CASE WHEN Band = 14.0 THEN 1 ELSE 0 END) AS '20m',
|
58
|
+
SUM(CASE WHEN Band = 21.0 THEN 1 ELSE 0 END) AS '15m',
|
59
|
+
SUM(CASE WHEN Band = 28.0 THEN 1 ELSE 0 END) AS '10m',
|
60
|
+
COUNT(*) AS Total
|
61
|
+
FROM DXLOG
|
62
|
+
GROUP BY CountryPrefix
|
63
|
+
ORDER BY Total DESC
|
64
|
+
"""
|
65
|
+
)
|
66
|
+
if not query.exec():
|
67
|
+
print("Query failed:", query.lastError().text())
|
68
|
+
else:
|
69
|
+
self.model.setQuery(query)
|
70
|
+
headers = ["DXCC", "160m", "80m", "40m", "20m", "15m", "10m", "Total"]
|
71
|
+
for i, header in enumerate(headers):
|
72
|
+
self.model.setHeaderData(i, Qt.Orientation.Horizontal, header)
|
73
|
+
self.tableView.setModel(self.model)
|
74
|
+
self.tableView.resizeColumnsToContents()
|
75
|
+
self.tableView.resizeRowsToContents()
|
76
|
+
|
77
|
+
def load_pref(self) -> None:
|
78
|
+
"""
|
79
|
+
Loads the preferences from the config file into the self.pref dictionary.
|
80
|
+
|
81
|
+
Parameters
|
82
|
+
----------
|
83
|
+
None
|
84
|
+
|
85
|
+
Returns
|
86
|
+
-------
|
87
|
+
None
|
88
|
+
"""
|
89
|
+
try:
|
90
|
+
if os.path.exists(fsutils.CONFIG_FILE):
|
91
|
+
with open(
|
92
|
+
fsutils.CONFIG_FILE, "rt", encoding="utf-8"
|
93
|
+
) as file_descriptor:
|
94
|
+
self.pref = loads(file_descriptor.read())
|
95
|
+
logger.info("%s", self.pref)
|
96
|
+
else:
|
97
|
+
self.pref["current_database"] = "ham.db"
|
98
|
+
|
99
|
+
except IOError as exception:
|
100
|
+
logger.critical("Error: %s", exception)
|
101
|
+
|
102
|
+
def load_new_db(self) -> None:
|
103
|
+
"""
|
104
|
+
If the database changes reload it.
|
105
|
+
|
106
|
+
Parameters
|
107
|
+
----------
|
108
|
+
None
|
109
|
+
|
110
|
+
Returns
|
111
|
+
-------
|
112
|
+
None
|
113
|
+
"""
|
114
|
+
self.load_pref()
|
115
|
+
self.dbname = fsutils.USER_DATA_PATH / self.pref.get(
|
116
|
+
"current_database", "ham.db"
|
117
|
+
)
|
118
|
+
|
119
|
+
self.db.setDatabaseName(f"{self.dbname}")
|
120
|
+
if not self.db.open():
|
121
|
+
print("Error: Could not open database")
|
122
|
+
return
|
123
|
+
self.setWindowTitle(
|
124
|
+
f"Log Display - {self.pref.get('current_database', 'ham.db')}"
|
125
|
+
)
|
126
|
+
|
127
|
+
def msg_from_main(self, msg):
|
128
|
+
""""""
|
129
|
+
if msg.get("cmd", "") in ("UPDATELOG", "CONTACTCHANGED", "DELETED"):
|
130
|
+
...
|
131
|
+
self.update_model()
|
132
|
+
if msg.get("cmd", "") == "NEWDB":
|
133
|
+
...
|
134
|
+
self.load_new_db()
|
135
|
+
self.update_model()
|
@@ -29,14 +29,15 @@ def prefer_prefix_score(query: str, candidate: str, **kwargs) -> int:
|
|
29
29
|
score = 0.8 * score
|
30
30
|
return int(round(score))
|
31
31
|
|
32
|
+
|
32
33
|
@lru_cache(maxsize=1024) # You can adjust this as needed
|
33
34
|
def prefix_bias_score(query: str, candidate: str, **kwargs) -> int:
|
34
35
|
"""Return a score based on the quality of the match."""
|
35
36
|
score = fuzz.QRatio(query, candidate)
|
36
37
|
|
37
|
-
if candidate[:len(query)] == query:
|
38
|
+
if candidate[: len(query)] == query:
|
38
39
|
return score
|
39
|
-
return int(score*0.8)
|
40
|
+
return int(score * 0.8)
|
40
41
|
|
41
42
|
|
42
43
|
class SCP:
|
@@ -53,18 +54,21 @@ class SCP:
|
|
53
54
|
- Returns True if successful
|
54
55
|
- Otherwise False
|
55
56
|
"""
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
57
|
+
try:
|
58
|
+
with requests.Session() as session:
|
59
|
+
the_request = session.get(MASTER_SCP_URL)
|
60
|
+
if the_request.status_code == 200:
|
61
|
+
with open(Path(self.app_data_path) / "MASTER.SCP", "wb+") as file:
|
62
|
+
file.write(the_request.content)
|
63
|
+
return True
|
64
|
+
except requests.exceptions.RequestException as exception:
|
65
|
+
logger.critical("update_masterscp: %s", exception)
|
62
66
|
return False
|
63
67
|
|
64
68
|
def read_scp(self):
|
65
69
|
"""
|
66
70
|
Reads in a list of known contesters into an internal dictionary
|
67
|
-
"""
|
71
|
+
"""
|
68
72
|
try:
|
69
73
|
with open(
|
70
74
|
Path(self.app_data_path) / "MASTER.SCP", "r", encoding="utf-8"
|
@@ -74,22 +78,21 @@ class SCP:
|
|
74
78
|
except IOError as exception:
|
75
79
|
logger.critical("read_scp: read error: %s", exception)
|
76
80
|
|
77
|
-
|
78
81
|
def super_check(self, acall: str) -> list:
|
79
82
|
|
80
83
|
if len(acall) > 1:
|
81
84
|
# Compute similarity scores between `acall` and all items in `self.scp`
|
82
85
|
similarity_scores = process.cdist(
|
83
|
-
[acall], self.scp, scorer=prefix_bias_score, workers=-1,score_cutoff=60
|
86
|
+
[acall], self.scp, scorer=prefix_bias_score, workers=-1, score_cutoff=60
|
84
87
|
)
|
85
88
|
|
86
89
|
# Sort and retrieve the top 20 matches with their indices
|
87
|
-
top_matches = sorted(
|
88
|
-
|
89
|
-
|
90
|
+
top_matches = sorted(enumerate(similarity_scores[0]), key=lambda x: -x[1])[
|
91
|
+
:20
|
92
|
+
]
|
90
93
|
|
91
94
|
# Extract the corresponding strings from `self.scp`
|
92
95
|
matches = [self.scp[idx] for idx, score in top_matches if score > 0]
|
93
96
|
|
94
97
|
return matches
|
95
|
-
return []
|
98
|
+
return []
|
not1mm/lib/version.py
CHANGED
not1mm/statistics.py
CHANGED
@@ -34,12 +34,6 @@ class StatsWindow(QDockWidget):
|
|
34
34
|
)
|
35
35
|
self.database = DataBase(self.dbname, fsutils.APP_DATA_PATH)
|
36
36
|
self.database.current_contest = self.pref.get("contest", 0)
|
37
|
-
self.load_pref()
|
38
|
-
self.dbname = fsutils.USER_DATA_PATH / self.pref.get(
|
39
|
-
"current_database", "ham.db"
|
40
|
-
)
|
41
|
-
self.database = DataBase(self.dbname, fsutils.APP_DATA_PATH)
|
42
|
-
self.database.current_contest = self.pref.get("contest", 0)
|
43
37
|
uic.loadUi(fsutils.APP_DATA_PATH / "statistics.ui", self)
|
44
38
|
|
45
39
|
def msg_from_main(self, packet):
|
@@ -56,12 +50,7 @@ class StatsWindow(QDockWidget):
|
|
56
50
|
if self.active is False:
|
57
51
|
return
|
58
52
|
|
59
|
-
if packet.get("cmd", "")
|
60
|
-
self.get_run_and_total_qs()
|
61
|
-
return
|
62
|
-
|
63
|
-
if packet.get("cmd", "") == "UPDATELOG":
|
64
|
-
logger.debug("External refresh command.")
|
53
|
+
if packet.get("cmd", "") in ("CONTACTCHANGED", "UPDATELOG", "DELETED"):
|
65
54
|
self.get_run_and_total_qs()
|
66
55
|
return
|
67
56
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: not1mm
|
3
|
-
Version: 25.6.
|
3
|
+
Version: 25.6.4
|
4
4
|
Summary: NOT1MM Logger
|
5
5
|
Author-email: Michael Bridak <michael.bridak@gmail.com>
|
6
6
|
License: GPL-3.0-or-later
|
@@ -244,6 +244,8 @@ generated, 'cause I'm lazy, list of those who've submitted PR's.
|
|
244
244
|
|
245
245
|
## Recent Changes
|
246
246
|
|
247
|
+
- [25-6-4] Add a DXCC/Band widget.
|
248
|
+
- [25-6-3] Fix crash caused by SSL cert expiration from supercheckpartial.com.
|
247
249
|
- [25-6-2] Crash Fix. Change initial self.pref from None to a dict.
|
248
250
|
- [25-6-1] Merged changes from @term73, updating ES Field Day.
|
249
251
|
|
@@ -348,7 +350,7 @@ parameters.
|
|
348
350
|
|
349
351
|
## Configuration Settings
|
350
352
|
|
351
|
-
To setup your CAT control, CW keyer,
|
353
|
+
To setup your CAT control, CW keyer, and callsign lookups, select
|
352
354
|
`File` > `Configuration Settings`
|
353
355
|
|
354
356
|
The tabs for groups and n1mm are disabled and are for future expansion.
|
@@ -357,31 +359,36 @@ The tabs for groups and n1mm are disabled and are for future expansion.
|
|
357
359
|
|
358
360
|
### Lookup
|
359
361
|
|
360
|
-
For callsign lookup,
|
361
|
-
username and password
|
362
|
+
For callsign lookup, two services are supported: QRZ and HamQTH. They require a
|
363
|
+
username and password. Enter that information here.
|
362
364
|
|
363
365
|
### Soundcard
|
364
366
|
|
365
|
-
Choose the sound output device for the voice keyer.
|
367
|
+
Choose the appropriate sound output device for the voice keyer.
|
366
368
|
|
367
369
|
### CAT Control
|
368
370
|
|
369
|
-
Under the `CAT`
|
370
|
-
`127.0.0.1` and a port of `4532
|
371
|
+
Under the `CAT` tab, you can choose either: `rigctld` normally with an IP of
|
372
|
+
`127.0.0.1` and a port of `4532` or `flrig` with an IP normally of `127.0.0.1` and a
|
371
373
|
port of `12345`. `None` is always an option, but is it really? There's an
|
372
374
|
onscreen icon for CAT status. Green good, Red bad, Grey neither.
|
373
375
|
|
374
|
-
### CW Keyer
|
376
|
+
### CW Keyer Interface
|
375
377
|
|
376
|
-
Under the `CW`
|
377
|
-
`127.0.0.1`port `6789
|
378
|
-
`CAT`
|
378
|
+
Under the `CW` tab, there are three options: i) `cwdaemon` that normally uses IP address
|
379
|
+
`127.0.0.1`port `6789`, ii) `pywinkeyer` that normally uses IP address `127.0.0.1` port `8000`, and
|
380
|
+
iii) `CAT` that sends Morse characters via rigctld if your radio supports it.
|
381
|
+
|
382
|
+
For contests that require a serial number as part of the exchange, there is an option to pad it with leading zeroes,
|
383
|
+
typically represented by the cut number "T". For example, serial number "001" can be sent as "TT1". The user can
|
384
|
+
configure the `CW Sent Nr Padding` character (default: T) and `CW Sent Nr Padding
|
385
|
+
Length` (default: 3) or specify no padding by entering length "0".
|
379
386
|
|
380
387
|
### Cluster
|
381
388
|
|
382
389
|

|
383
390
|
|
384
|
-
Under the `Cluster`
|
391
|
+
Under the `Cluster` tab you can change the default AR Cluster server, port, and
|
385
392
|
filter settings used for the bandmap window.
|
386
393
|
|
387
394
|
### N1MM Packets
|
@@ -1,14 +1,15 @@
|
|
1
1
|
not1mm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
not1mm/__main__.py,sha256=
|
2
|
+
not1mm/__main__.py,sha256=IHFJFKGAgKyPZUdi-aRDFIS--XJPdoPiV6utXx31_-I,172631
|
3
3
|
not1mm/bandmap.py,sha256=0JmZ32UvkaPjXs2xTgowX1GLvZo5zHU_Zo9y_GL-On4,31139
|
4
4
|
not1mm/checkwindow.py,sha256=zEHlw40j6Wr3rvKbCQf2lcezCoiZqaBqEvBjQU5aKW0,7630
|
5
|
+
not1mm/dxcc_tracker.py,sha256=shhH0rgiBL2gOINu9yVPoVj2hAI-oBkubb_sAbRJ-6E,4377
|
5
6
|
not1mm/fsutils.py,sha256=ukHKxKTeNKxKwqRaJjtzRShL4X5Xl0jRBbADyy3Ifp8,1701
|
6
7
|
not1mm/logwindow.py,sha256=O2dMaT_BYWsXA_dxsEHN92JwN-qVGy9nmH0MCMaG9gY,42830
|
7
8
|
not1mm/lookupservice.py,sha256=GkY_qHZfrW6XHf8upIoaG4hCFqm0fg6Ganu9ConGrIc,2628
|
8
9
|
not1mm/radio.py,sha256=4Lysf9BY3vdtYCHwKfzO5WN7IGyh4_lKSVuQ6F4Z08g,5536
|
9
10
|
not1mm/ratewindow.py,sha256=iBjqdOetIEX0wSwdGM89Ibt4gVlFdE-K8HQPnkVPVOg,6965
|
10
11
|
not1mm/rtc_service.py,sha256=axAwnCBuTr-QL0YwXtWvg9tjwhcFsiiEZFgFjOofX6k,2816
|
11
|
-
not1mm/statistics.py,sha256=
|
12
|
+
not1mm/statistics.py,sha256=yvEHCDtz4VHEg1gJ5CHAoB9lhZOevBxbeMo5WsCii2w,7355
|
12
13
|
not1mm/test.py,sha256=BNhsSvLnNG5hN4pywIWnj4pUBI-wQYY4Ejfbl97knmw,1198
|
13
14
|
not1mm/vfo.py,sha256=SsqinokSd8BqVp6l-_DGRKcNN9Uc9JiFYXDl9Ycep1o,10111
|
14
15
|
not1mm/voice_keying.py,sha256=HZImqC5NgnyW2nknNYQ3b7I8-6S_hxpq5G4RcIRXn_k,3005
|
@@ -26,6 +27,7 @@ not1mm/data/contests.sql,sha256=4hmJCDvrbxnA_Y5S4T5o52TZieeFk6QUwFerwlFePNA,8930
|
|
26
27
|
not1mm/data/cty.json,sha256=3Nk98AoENvBB4RwJCTheDVCjJ1AvX4ik5kg2R0iU1X0,4948509
|
27
28
|
not1mm/data/cwmacros.txt,sha256=NztufsX6R52gAO7VyJ2AHr7wOh41pJTwHKh5Lcs32ds,468
|
28
29
|
not1mm/data/donors.html,sha256=alw5wpOdAX4hcJLx7NyhNRdSdmWOiTlD-CQXVWcULXU,333
|
30
|
+
not1mm/data/dxcc_tracker.ui,sha256=1tDkNG4Q2IaFlE-5yAq0eAI3hYkrWQ6NAMp5DD8TvCU,580
|
29
31
|
not1mm/data/editcontact.ui,sha256=ax-pm4TeECpHl3LSb5z4L403WjPWXZ9KV2it_6gIjqk,27404
|
30
32
|
not1mm/data/editmacro.ui,sha256=wbLuNwLsMBd9hEKs_6sH3ir5BynH9Bk-u8nWRjNyQ8w,2689
|
31
33
|
not1mm/data/greendot.png,sha256=El9TomJcGtViRcHOR7kMxGzjzvYs0TSAqOb3tZv0JDA,368
|
@@ -35,7 +37,7 @@ not1mm/data/k6gte.not1mm-32.png,sha256=XdTsCa3xqwTfn26Ga7RwO_Vlbg_77RKkSc8bMxVcC
|
|
35
37
|
not1mm/data/k6gte.not1mm-64.png,sha256=6ku45Gq1g5ezh04F07osoKRtanb3e4kbx5XdIEh3N90,2925
|
36
38
|
not1mm/data/logwindow.ui,sha256=vfkNdzJgFs3tTOBKLDavF2zVMvNHWOZ82fAErRi6pQY,1436
|
37
39
|
not1mm/data/logwindowx.ui,sha256=9FzDJtLRpagvAWcDjFdB9NnvNZ4bVxdTNHy1Jit2ido,1610
|
38
|
-
not1mm/data/main.ui,sha256=
|
40
|
+
not1mm/data/main.ui,sha256=lr3_rwmyywfYQtw9GNf1leeJ0fe6Y2Xy3-cdV4kmKi4,65425
|
39
41
|
not1mm/data/new_contest.ui,sha256=i-WThxa9IBstyAMCRtNMB4NVPpV3fekUIX1YDYPyuOQ,25521
|
40
42
|
not1mm/data/not1mm.html,sha256=c9-mfjMwDt4f5pySUruz2gREW33CQ2_rCddM2z5CZQo,23273
|
41
43
|
not1mm/data/opon.ui,sha256=mC4OhoVIfR1H9IqHAKXliPMm8VOVmxSEadpsFQ7XnS4,2247
|
@@ -119,8 +121,8 @@ not1mm/lib/new_contest.py,sha256=IznTDMq7yXHB6zBoGUEC_WDYPCPpsSZW4wwMJi16zK0,816
|
|
119
121
|
not1mm/lib/plugin_common.py,sha256=nqiUq11T9Wz8RDrRen4Zvp-KXVWUYcIp5JPZwqmu2Oo,13913
|
120
122
|
not1mm/lib/select_contest.py,sha256=WsptLuwkouIHeocJL3oZ6-eUfEnhpwdc-x7eMZ_TIVM,359
|
121
123
|
not1mm/lib/settings.py,sha256=5xnsagH48qGeCDhfxPWW9yaXtv8wT13yoIVvYt8h_Qs,16023
|
122
|
-
not1mm/lib/super_check_partial.py,sha256=
|
123
|
-
not1mm/lib/version.py,sha256=
|
124
|
+
not1mm/lib/super_check_partial.py,sha256=jX7DjHesEV4KNVQbddJui0wAsYHerikH7W0iPv7PXQw,3110
|
125
|
+
not1mm/lib/version.py,sha256=iOQDkhN7eZvJIMmdRhXwA0HD1relkhKvEjCRTD0YPXk,47
|
124
126
|
not1mm/lib/versiontest.py,sha256=8vDNptuBBunn-1IGkjNaquehqBYUJyjrPSF8Igmd4_Y,1286
|
125
127
|
not1mm/plugins/10_10_fall_cw.py,sha256=oJh3JKqjOpnWElSlZpiQ631UnaOd8qra5s9bl_QoInk,14783
|
126
128
|
not1mm/plugins/10_10_spring_cw.py,sha256=p7dSDtbFK0e6Xouw2V6swYn3VFVgHKyx4IfRWyBjMZY,14786
|
@@ -184,9 +186,9 @@ not1mm/plugins/ukeidx.py,sha256=ZsIFXgOSwjuKNmN4W_C0TAgGqgnabJGNLMHwGkl3_bk,1910
|
|
184
186
|
not1mm/plugins/vhf_sprint.py,sha256=a9QFTpv8XUbZ_GLjdVCh7svykFa-gXOWwKFZ6MD3uQM,19289
|
185
187
|
not1mm/plugins/weekly_rtty.py,sha256=C8Xs3Q5UgSYx-mFFar8BVARWtmqlyrbeC98Ubzb4UN8,20128
|
186
188
|
not1mm/plugins/winter_field_day.py,sha256=hmAMgkdqIXtnCNyUp8J9Bb8liN8wj10wps6ROuG-Bok,15284
|
187
|
-
not1mm-25.6.
|
188
|
-
not1mm-25.6.
|
189
|
-
not1mm-25.6.
|
190
|
-
not1mm-25.6.
|
191
|
-
not1mm-25.6.
|
192
|
-
not1mm-25.6.
|
189
|
+
not1mm-25.6.4.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
190
|
+
not1mm-25.6.4.dist-info/METADATA,sha256=67UQJHHsXjGWX5IQ2ZW3P-n84rUv8V3qh2gGvX3ese0,34676
|
191
|
+
not1mm-25.6.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
192
|
+
not1mm-25.6.4.dist-info/entry_points.txt,sha256=pMcZk_0dxFgLkcUkF0Q874ojpwOmF3OL6EKw9LgvocM,47
|
193
|
+
not1mm-25.6.4.dist-info/top_level.txt,sha256=0YmTxEcDzQlzXub-lXASvoLpg_mt1c2thb5cVkDf5J4,7
|
194
|
+
not1mm-25.6.4.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|