not1mm 25.6.7__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.
@@ -16,7 +16,7 @@
16
16
  <widget class="QWidget" name="centralwidget">
17
17
  <layout class="QVBoxLayout" name="verticalLayout">
18
18
  <item>
19
- <widget class="QTableView" name="tableView">
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, QTableView
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
- 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)
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
- self.db = QSqlDatabase.addDatabase("QSQLITE")
43
- self.tableView.verticalHeader().setVisible(False)
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 update_model(self):
49
- self.model = CustomSqlModel(self)
50
- query = QSqlQuery(self.db)
51
- query.prepare(
52
- f"""
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 where ContestNR = {self.pref.get('contest', 1)}
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()
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.db.setDatabaseName(f"{self.dbname}")
120
- if not self.db.open():
121
- print("Error: Could not open database")
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 msg.get("cmd", "") in ("UPDATELOG", "CONTACTCHANGED", "DELETED"):
127
- ...
128
- self.update_model()
129
- if msg.get("cmd", "") == "NEWDB":
130
- ...
131
- self.load_new_db()
132
- self.update_model()
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
@@ -179,7 +179,7 @@ class DataBase:
179
179
  ");"
180
180
  )
181
181
  cursor.execute(sql_command)
182
- cursor.execute("PRAGMA journal_mode=WAL")
182
+ cursor.execute("PRAGMA journal_mode=DELETE")
183
183
  conn.commit()
184
184
  except sqlite3.OperationalError as exception:
185
185
  logger.debug("%s", exception)
@@ -223,7 +223,7 @@ class DataBase:
223
223
  ");"
224
224
  )
225
225
  cursor.execute(sql_command)
226
- cursor.execute("PRAGMA journal_mode=WAL")
226
+ cursor.execute("PRAGMA journal_mode=DELETE")
227
227
  conn.commit()
228
228
 
229
229
  sql_command = "select * from Contest;"
@@ -273,7 +273,7 @@ class DataBase:
273
273
  "TimeCategory NVARCHAR(20));"
274
274
  )
275
275
  cursor.execute(sql_command)
276
- cursor.execute("PRAGMA journal_mode=WAL")
276
+ cursor.execute("PRAGMA journal_mode=DELETE")
277
277
  conn.commit()
278
278
  except sqlite3.OperationalError as exception:
279
279
  logger.debug("%s", exception)
@@ -313,7 +313,7 @@ class DataBase:
313
313
  "PRIMARY KEY([Call]));"
314
314
  )
315
315
  cursor.execute(sql_command)
316
- cursor.execute("PRAGMA journal_mode=WAL")
316
+ cursor.execute("PRAGMA journal_mode=DELETE")
317
317
  conn.commit()
318
318
  except sqlite3.OperationalError as exception:
319
319
  logger.debug("%s", exception)
@@ -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
@@ -1234,7 +1262,7 @@ class DataBase:
1234
1262
  except sqlite3.OperationalError as exception:
1235
1263
  logger.debug("%s", exception)
1236
1264
  return {}
1237
-
1265
+
1238
1266
  def exec_sql_params_mult(self, query: str, params=None) -> dict:
1239
1267
  """Exec one off queries returning one dict"""
1240
1268
  try:
@@ -1271,9 +1299,7 @@ class DataBase:
1271
1299
  logger.debug("%s", exception)
1272
1300
  return []
1273
1301
 
1274
- def check_dupe_on_period_mode(
1275
- self, call, band, mode, period_1, period_2
1276
- ) -> dict:
1302
+ def check_dupe_on_period_mode(self, call, band, mode, period_1, period_2) -> dict:
1277
1303
  """Checks if a call is dupe on band/mode"""
1278
1304
  try:
1279
1305
  with sqlite3.connect(self.database) as conn:
@@ -1286,4 +1312,3 @@ class DataBase:
1286
1312
  except sqlite3.OperationalError as exception:
1287
1313
  logger.debug("%s", exception)
1288
1314
  return {}
1289
-
not1mm/lib/version.py CHANGED
@@ -1,3 +1,3 @@
1
1
  """It's the version"""
2
2
 
3
- __version__ = "25.6.7"
3
+ __version__ = "25.6.8.1"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: not1mm
3
- Version: 25.6.7
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
@@ -245,6 +245,8 @@ generated, 'cause I'm lazy, list of those who've submitted PR's.
245
245
 
246
246
  ## Recent Changes
247
247
 
248
+ - [25-6-8] Revmoved SQLite WAL mode.
249
+ - Rewrote DXCC tracker.
248
250
  - [25-6-7] Fix focus issue when dxcc widget is active.
249
251
  - [25-6-4] Add a DXCC/Band widget.
250
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=v3ctEyiB9CbA8l70T0ANS-kymo2DXpLIPEp2rj84Bjg,4302
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=0TUK2yQfsSUBGrlCIAJ-jEquXN-7Ey5-qlTOLhhUthA,722
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=4PLLKwzeOR6SkaUtUiZ4DBC44VS5q_HFo5XqzkwgfSg,52099
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=mIAVfHe6QqNBsLnXzYiMx0-RygAnLi7Tt0D0HU_nv08,47
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.7.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
190
- not1mm-25.6.7.dist-info/METADATA,sha256=fiI55-39nf16sTdcSQRAp5AxKeZ1VtL8AwdjquZmAZk,34974
191
- not1mm-25.6.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
192
- not1mm-25.6.7.dist-info/entry_points.txt,sha256=pMcZk_0dxFgLkcUkF0Q874ojpwOmF3OL6EKw9LgvocM,47
193
- not1mm-25.6.7.dist-info/top_level.txt,sha256=0YmTxEcDzQlzXub-lXASvoLpg_mt1c2thb5cVkDf5J4,7
194
- not1mm-25.6.7.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,,