not1mm 25.6.8__py3-none-any.whl → 25.6.8.1__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/dxcc_tracker.ui +1 -1
- not1mm/dxcc_tracker.py +75 -56
- not1mm/lib/database.py +28 -0
- not1mm/lib/version.py +1 -1
- {not1mm-25.6.8.dist-info → not1mm-25.6.8.1.dist-info}/METADATA +2 -1
- {not1mm-25.6.8.dist-info → not1mm-25.6.8.1.dist-info}/RECORD +10 -10
- {not1mm-25.6.8.dist-info → not1mm-25.6.8.1.dist-info}/WHEEL +0 -0
- {not1mm-25.6.8.dist-info → not1mm-25.6.8.1.dist-info}/entry_points.txt +0 -0
- {not1mm-25.6.8.dist-info → not1mm-25.6.8.1.dist-info}/licenses/LICENSE +0 -0
- {not1mm-25.6.8.dist-info → not1mm-25.6.8.1.dist-info}/top_level.txt +0 -0
not1mm/data/dxcc_tracker.ui
CHANGED
@@ -16,7 +16,7 @@
|
|
16
16
|
<widget class="QWidget" name="centralwidget">
|
17
17
|
<layout class="QVBoxLayout" name="verticalLayout">
|
18
18
|
<item>
|
19
|
-
<widget class="
|
19
|
+
<widget class="QTableWidget" name="dxcc_table">
|
20
20
|
<property name="focusPolicy">
|
21
21
|
<enum>Qt::FocusPolicy::NoFocus</enum>
|
22
22
|
</property>
|
not1mm/dxcc_tracker.py
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
from PyQt6.QtWidgets import QDockWidget
|
2
|
-
from PyQt6.QtSql import QSqlDatabase, QSqlQueryModel, QSqlQuery
|
1
|
+
from PyQt6.QtWidgets import QDockWidget
|
3
2
|
from PyQt6.QtGui import QBrush, QColor
|
4
3
|
from PyQt6.QtCore import Qt
|
5
4
|
from PyQt6.QtCore import pyqtSignal
|
6
|
-
from PyQt6 import uic
|
5
|
+
from PyQt6 import uic, QtWidgets
|
7
6
|
import not1mm.fsutils as fsutils
|
7
|
+
from not1mm.lib.database import DataBase
|
8
8
|
import os
|
9
9
|
from json import loads
|
10
10
|
|
@@ -13,17 +13,17 @@ import logging
|
|
13
13
|
logger = logging.getLogger(__name__)
|
14
14
|
|
15
15
|
|
16
|
-
class CustomSqlModel(QSqlQueryModel):
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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
27
|
|
28
28
|
|
29
29
|
class DXCCWindow(QDockWidget):
|
@@ -32,47 +32,66 @@ class DXCCWindow(QDockWidget):
|
|
32
32
|
db = None
|
33
33
|
model = None
|
34
34
|
pref = {}
|
35
|
+
columns = {
|
36
|
+
0: "DXCC",
|
37
|
+
1: "160m",
|
38
|
+
2: "80m",
|
39
|
+
3: "40m",
|
40
|
+
4: "20m",
|
41
|
+
5: "15m",
|
42
|
+
6: "10m",
|
43
|
+
7: "Total",
|
44
|
+
}
|
35
45
|
|
36
46
|
def __init__(self):
|
37
47
|
super().__init__()
|
38
48
|
self.active = False
|
39
49
|
uic.loadUi(fsutils.APP_DATA_PATH / "dxcc_tracker.ui", self)
|
50
|
+
self.dxcc_table.setColumnCount(len(self.columns))
|
51
|
+
for column_number, column_name in self.columns.items():
|
52
|
+
self.dxcc_table.setHorizontalHeaderItem(
|
53
|
+
column_number, QtWidgets.QTableWidgetItem(column_name)
|
54
|
+
)
|
40
55
|
self.setWindowTitle("DXCC Tracker")
|
41
56
|
self.load_pref()
|
42
|
-
|
43
|
-
self.
|
57
|
+
|
58
|
+
self.dbname = fsutils.USER_DATA_PATH / self.pref.get(
|
59
|
+
"current_database", "ham.db"
|
60
|
+
)
|
61
|
+
self.database = DataBase(self.dbname, fsutils.USER_DATA_PATH)
|
62
|
+
|
63
|
+
self.database.current_contest = self.pref.get("contest", 0)
|
64
|
+
|
65
|
+
self.get_log()
|
66
|
+
self.dxcc_table.resizeColumnsToContents()
|
67
|
+
self.dxcc_table.resizeRowsToContents()
|
44
68
|
|
45
69
|
def setActive(self, mode: bool):
|
46
70
|
self.active = bool(mode)
|
47
71
|
|
48
|
-
def
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
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()
|
72
|
+
def get_log(self):
|
73
|
+
"""dxcc_table"""
|
74
|
+
|
75
|
+
# result=[
|
76
|
+
# {'CountryPrefix': 'K', '160m': 0, '80m': 0, '40m': 0, '20m': 7, '15m': 0, '10m': 0, 'Total': 7},
|
77
|
+
# {'CountryPrefix': 'XE', '160m': 0, '80m': 0, '40m': 0, '20m': 1, '15m': 0, '10m': 0, 'Total': 1},
|
78
|
+
# {'CountryPrefix': 'G', '160m': 0, '80m': 0, '40m': 0, '20m': 1, '15m': 0, '10m': 0, 'Total': 1}
|
79
|
+
# ]
|
80
|
+
|
81
|
+
result = self.database.fetch_dxcc_by_band_count()
|
82
|
+
self.dxcc_table.setRowCount(0)
|
83
|
+
for row_number, row_data in enumerate(result):
|
84
|
+
self.dxcc_table.insertRow(row_number)
|
85
|
+
for column, data in enumerate(row_data.values()):
|
86
|
+
item = QtWidgets.QTableWidgetItem(str(data))
|
87
|
+
if column > 0 and column < 7:
|
88
|
+
if data == 0:
|
89
|
+
item.setBackground(QBrush(QColor(44, 138, 44)))
|
90
|
+
else:
|
91
|
+
item.setBackground(QBrush(QColor(155, 100, 100)))
|
92
|
+
self.dxcc_table.setItem(row_number, column, item)
|
93
|
+
self.dxcc_table.resizeColumnsToContents()
|
94
|
+
self.dxcc_table.resizeRowsToContents()
|
76
95
|
|
77
96
|
def load_pref(self) -> None:
|
78
97
|
"""
|
@@ -115,18 +134,18 @@ class DXCCWindow(QDockWidget):
|
|
115
134
|
self.dbname = fsutils.USER_DATA_PATH / self.pref.get(
|
116
135
|
"current_database", "ham.db"
|
117
136
|
)
|
118
|
-
|
119
|
-
self.
|
120
|
-
|
121
|
-
|
122
|
-
return
|
137
|
+
self.database = DataBase(self.dbname, fsutils.APP_DATA_PATH)
|
138
|
+
self.database.current_contest = self.pref.get("contest", 0)
|
139
|
+
self.contact = self.database.empty_contact
|
140
|
+
self.get_log()
|
123
141
|
|
124
142
|
def msg_from_main(self, msg):
|
125
143
|
""""""
|
126
|
-
if
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
144
|
+
if self.active is True:
|
145
|
+
if msg.get("cmd", "") in ("UPDATELOG", "CONTACTCHANGED", "DELETED"):
|
146
|
+
...
|
147
|
+
self.get_log()
|
148
|
+
if msg.get("cmd", "") == "NEWDB":
|
149
|
+
...
|
150
|
+
self.load_new_db()
|
151
|
+
self.get_log()
|
not1mm/lib/database.py
CHANGED
@@ -726,6 +726,34 @@ class DataBase:
|
|
726
726
|
logger.debug("%s", exception)
|
727
727
|
return {}
|
728
728
|
|
729
|
+
def fetch_dxcc_by_band_count(self) -> list:
|
730
|
+
"""
|
731
|
+
Fetch list containing count of unique countries by band
|
732
|
+
|
733
|
+
"""
|
734
|
+
try:
|
735
|
+
with sqlite3.connect(self.database) as conn:
|
736
|
+
conn.row_factory = self.row_factory
|
737
|
+
cursor = conn.cursor()
|
738
|
+
query = f"""
|
739
|
+
SELECT CountryPrefix,
|
740
|
+
SUM(CASE WHEN Band = 1.8 THEN 1 ELSE 0 END) AS '160m',
|
741
|
+
SUM(CASE WHEN Band = 3.5 THEN 1 ELSE 0 END) AS '80m',
|
742
|
+
SUM(CASE WHEN Band = 7.0 THEN 1 ELSE 0 END) AS '40m',
|
743
|
+
SUM(CASE WHEN Band = 14.0 THEN 1 ELSE 0 END) AS '20m',
|
744
|
+
SUM(CASE WHEN Band = 21.0 THEN 1 ELSE 0 END) AS '15m',
|
745
|
+
SUM(CASE WHEN Band = 28.0 THEN 1 ELSE 0 END) AS '10m',
|
746
|
+
COUNT(*) AS Total
|
747
|
+
FROM DXLOG where ContestNR = {self.current_contest}
|
748
|
+
GROUP BY CountryPrefix
|
749
|
+
ORDER BY Total DESC
|
750
|
+
"""
|
751
|
+
cursor.execute(query)
|
752
|
+
return cursor.fetchall()
|
753
|
+
except sqlite3.OperationalError as exception:
|
754
|
+
logger.debug("%s", exception)
|
755
|
+
return {}
|
756
|
+
|
729
757
|
def fetch_exchange1_unique_count(self) -> dict:
|
730
758
|
"""
|
731
759
|
Fetch count of unique countries
|
not1mm/lib/version.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: not1mm
|
3
|
-
Version: 25.6.8
|
3
|
+
Version: 25.6.8.1
|
4
4
|
Summary: NOT1MM Logger
|
5
5
|
Author-email: Michael Bridak <michael.bridak@gmail.com>
|
6
6
|
License: GPL-3.0-or-later
|
@@ -246,6 +246,7 @@ generated, 'cause I'm lazy, list of those who've submitted PR's.
|
|
246
246
|
## Recent Changes
|
247
247
|
|
248
248
|
- [25-6-8] Revmoved SQLite WAL mode.
|
249
|
+
- Rewrote DXCC tracker.
|
249
250
|
- [25-6-7] Fix focus issue when dxcc widget is active.
|
250
251
|
- [25-6-4] Add a DXCC/Band widget.
|
251
252
|
- [25-6-3] Fix crash caused by SSL cert expiration from supercheckpartial.com.
|
@@ -2,7 +2,7 @@ not1mm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
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=
|
5
|
+
not1mm/dxcc_tracker.py,sha256=QkcKRzoqmQ3Jle1SM5fFiumieUnRou5fuy-sJseWzsE,4935
|
6
6
|
not1mm/fsutils.py,sha256=ukHKxKTeNKxKwqRaJjtzRShL4X5Xl0jRBbADyy3Ifp8,1701
|
7
7
|
not1mm/logwindow.py,sha256=O2dMaT_BYWsXA_dxsEHN92JwN-qVGy9nmH0MCMaG9gY,42830
|
8
8
|
not1mm/lookupservice.py,sha256=GkY_qHZfrW6XHf8upIoaG4hCFqm0fg6Ganu9ConGrIc,2628
|
@@ -27,7 +27,7 @@ not1mm/data/contests.sql,sha256=4hmJCDvrbxnA_Y5S4T5o52TZieeFk6QUwFerwlFePNA,8930
|
|
27
27
|
not1mm/data/cty.json,sha256=3Nk98AoENvBB4RwJCTheDVCjJ1AvX4ik5kg2R0iU1X0,4948509
|
28
28
|
not1mm/data/cwmacros.txt,sha256=NztufsX6R52gAO7VyJ2AHr7wOh41pJTwHKh5Lcs32ds,468
|
29
29
|
not1mm/data/donors.html,sha256=hxxm23mHP_YUN3PnGwm12CiAutUTl5DQfDpgfyZbimY,370
|
30
|
-
not1mm/data/dxcc_tracker.ui,sha256=
|
30
|
+
not1mm/data/dxcc_tracker.ui,sha256=BzIdljdJ4ZvRe3WwmahrCZzdKWwR5vcC2KAGSnpPZTY,725
|
31
31
|
not1mm/data/editcontact.ui,sha256=ax-pm4TeECpHl3LSb5z4L403WjPWXZ9KV2it_6gIjqk,27404
|
32
32
|
not1mm/data/editmacro.ui,sha256=wbLuNwLsMBd9hEKs_6sH3ir5BynH9Bk-u8nWRjNyQ8w,2689
|
33
33
|
not1mm/data/greendot.png,sha256=El9TomJcGtViRcHOR7kMxGzjzvYs0TSAqOb3tZv0JDA,368
|
@@ -106,7 +106,7 @@ not1mm/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
106
106
|
not1mm/lib/about.py,sha256=sWycfGcruN3SaEe4JmaJ61K6D8Itq0WxpUYT-lEcmYM,416
|
107
107
|
not1mm/lib/cat_interface.py,sha256=jADt45E5AcdEx8FHN4rSDbngeQqVzbtIy43luGWGDK0,27222
|
108
108
|
not1mm/lib/cwinterface.py,sha256=rKUnqljHQC_Iljq4TCmAgSPe49lWbKcfxg58cE8YX5Y,5177
|
109
|
-
not1mm/lib/database.py,sha256=
|
109
|
+
not1mm/lib/database.py,sha256=NYIUoQUPx9zGHATxZ5tQqpQyA2DC2FyJ5spPUGHX3Nw,53441
|
110
110
|
not1mm/lib/edit_contact.py,sha256=Ki9bGPpqyQQBB1cU8VIBDCal3lbXeQ6qxhzklmhE2_w,353
|
111
111
|
not1mm/lib/edit_macro.py,sha256=raKWBwsHInj5EUKmvyLQ6gqc3ZFDlstsD3xqoM4PC8E,517
|
112
112
|
not1mm/lib/edit_opon.py,sha256=j3qJ1aBsQoIOnQ9yiBl3lyeISvKTP0I_rtBYBPAfgeI,359
|
@@ -122,7 +122,7 @@ not1mm/lib/plugin_common.py,sha256=nqiUq11T9Wz8RDrRen4Zvp-KXVWUYcIp5JPZwqmu2Oo,1
|
|
122
122
|
not1mm/lib/select_contest.py,sha256=WsptLuwkouIHeocJL3oZ6-eUfEnhpwdc-x7eMZ_TIVM,359
|
123
123
|
not1mm/lib/settings.py,sha256=5xnsagH48qGeCDhfxPWW9yaXtv8wT13yoIVvYt8h_Qs,16023
|
124
124
|
not1mm/lib/super_check_partial.py,sha256=jX7DjHesEV4KNVQbddJui0wAsYHerikH7W0iPv7PXQw,3110
|
125
|
-
not1mm/lib/version.py,sha256=
|
125
|
+
not1mm/lib/version.py,sha256=QMaYrXzd5DZB-D9ZrAglXgrutCbulW_Z899cFr9Fr90,49
|
126
126
|
not1mm/lib/versiontest.py,sha256=8vDNptuBBunn-1IGkjNaquehqBYUJyjrPSF8Igmd4_Y,1286
|
127
127
|
not1mm/plugins/10_10_fall_cw.py,sha256=oJh3JKqjOpnWElSlZpiQ631UnaOd8qra5s9bl_QoInk,14783
|
128
128
|
not1mm/plugins/10_10_spring_cw.py,sha256=p7dSDtbFK0e6Xouw2V6swYn3VFVgHKyx4IfRWyBjMZY,14786
|
@@ -186,9 +186,9 @@ not1mm/plugins/ukeidx.py,sha256=ZsIFXgOSwjuKNmN4W_C0TAgGqgnabJGNLMHwGkl3_bk,1910
|
|
186
186
|
not1mm/plugins/vhf_sprint.py,sha256=a9QFTpv8XUbZ_GLjdVCh7svykFa-gXOWwKFZ6MD3uQM,19289
|
187
187
|
not1mm/plugins/weekly_rtty.py,sha256=C8Xs3Q5UgSYx-mFFar8BVARWtmqlyrbeC98Ubzb4UN8,20128
|
188
188
|
not1mm/plugins/winter_field_day.py,sha256=hmAMgkdqIXtnCNyUp8J9Bb8liN8wj10wps6ROuG-Bok,15284
|
189
|
-
not1mm-25.6.8.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
190
|
-
not1mm-25.6.8.dist-info/METADATA,sha256=
|
191
|
-
not1mm-25.6.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
192
|
-
not1mm-25.6.8.dist-info/entry_points.txt,sha256=pMcZk_0dxFgLkcUkF0Q874ojpwOmF3OL6EKw9LgvocM,47
|
193
|
-
not1mm-25.6.8.dist-info/top_level.txt,sha256=0YmTxEcDzQlzXub-lXASvoLpg_mt1c2thb5cVkDf5J4,7
|
194
|
-
not1mm-25.6.8.dist-info/RECORD,,
|
189
|
+
not1mm-25.6.8.1.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
190
|
+
not1mm-25.6.8.1.dist-info/METADATA,sha256=jLHID-aQHwUyjF5YEdHD2ASjSg8MZtE-mEDcfNl6oVA,35039
|
191
|
+
not1mm-25.6.8.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
192
|
+
not1mm-25.6.8.1.dist-info/entry_points.txt,sha256=pMcZk_0dxFgLkcUkF0Q874ojpwOmF3OL6EKw9LgvocM,47
|
193
|
+
not1mm-25.6.8.1.dist-info/top_level.txt,sha256=0YmTxEcDzQlzXub-lXASvoLpg_mt1c2thb5cVkDf5J4,7
|
194
|
+
not1mm-25.6.8.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|