44import threading
55import shutil
66import sys
7- from typing import Any , ClassVar , Final
7+ from typing import TYPE_CHECKING , Any , ClassVar , Final , cast
88from abc import ABCMeta
99from datetime import datetime , timedelta
1010from queue import Queue
1111import requests
1212
13- if "PyQt6" in sys .modules :
13+ if TYPE_CHECKING :
14+ from PyQt6 import QtCore , QtGui , QtWidgets
15+ elif "PyQt6" in sys .modules :
1416 from PyQt6 import QtCore , QtGui , QtWidgets
1517elif "PyQt5" in sys .modules :
1618 from PyQt5 import QtCore , QtGui , QtWidgets
2022 except Exception :
2123 from PyQt5 import QtCore , QtGui , QtWidgets
2224
23- try :
24- from opensnitch .dialogs .events import StatsDialog
25- except ImportError :
26- from opensnitch .dialogs .stats import StatsDialog # type: ignore
25+ from opensnitch .plugins .list_subscriptions ._compat import StatsDialog
26+ from opensnitch .plugins .list_subscriptions ._annotations import StatsDialogProto
27+ if TYPE_CHECKING :
28+ from opensnitch .plugins .list_subscriptions .ui .views .list_subscriptions_dialog import (
29+ ListSubscriptionsDialog ,
30+ )
2731
2832from opensnitch .plugins .list_subscriptions .io .lock import FileLock
2933from opensnitch .plugins .list_subscriptions .io .storage import read_json_locked
3438)
3539from opensnitch .plugins .list_subscriptions .models .metadata import ListMetadata
3640from opensnitch .plugins .list_subscriptions .models .subscriptions import SubscriptionSpec
37- from opensnitch .proto import ui_pb2
3841from opensnitch .config import Config
3942from opensnitch .nodes import Nodes
4043from opensnitch .notifications import DesktopNotifications
5760from opensnitch .plugins .list_subscriptions .io .storage import (
5861 write_json_atomic_locked ,
5962)
63+ from opensnitch .proto import ui_pb2 as ui_pb2
64+
6065
6166ch : Final [logging .StreamHandler ] = logging .StreamHandler ()
6267# ch.setLevel(logging.ERROR)
@@ -139,8 +144,8 @@ def __init__(self, config: dict[str, Any] | None = None):
139144 self ._app_icon = os .path .join (
140145 os .path .abspath (os .path .dirname (__file__ )), "../../res/icon-white.svg"
141146 )
142- self ._cfg_dialog : Any = None
143- self ._cfg_action : Any = None
147+ self ._cfg_dialog : ListSubscriptionsDialog | None = None
148+ self ._cfg_action : QtGui . QAction | None = None
144149 self ._cfg_toolbar_button : QtWidgets .QPushButton | None = None
145150 self .scheduled_tasks = {}
146151 self ._startup_recheck_lock = threading .Lock ()
@@ -583,7 +588,7 @@ def _reload_rules_for_updated_subscription(self, sub: SubscriptionSpec):
583588 continue
584589 matched = False
585590 while records .next ():
586- rule = Rule .new_from_records (records )
591+ rule = cast ( ui_pb2 . Rule , Rule .new_from_records (records ) )
587592 if rule .operator .operand == Config .OPERAND_LIST_DOMAINS :
588593 direct_dir = os .path .normpath (
589594 str (rule .operator .data or "" ).strip ()
@@ -603,8 +608,8 @@ def _reload_rules_for_updated_subscription(self, sub: SubscriptionSpec):
603608 if not matched :
604609 continue
605610
606- notification = ui_pb2 .Notification ( # type: ignore
607- type = ui_pb2 .CHANGE_RULE , # type: ignore
611+ notification = ui_pb2 .Notification (
612+ type = ui_pb2 .CHANGE_RULE ,
608613 rules = [rule ],
609614 )
610615 self ._nodes .send_notification (addr , notification , None )
@@ -633,7 +638,7 @@ def _sub_key(self, sub: SubscriptionSpec):
633638 base = f"{ sub .url } |{ sub .filename } "
634639 return hashlib .sha1 (base .encode ("utf-8" )).hexdigest ()[:16 ]
635640
636- def configure (self , parent : Any = None ):
641+ def configure (self , parent : StatsDialogProto | None = None ):
637642 if isinstance (parent , StatsDialog ):
638643 if self ._cfg_action is not None or self ._cfg_toolbar_button is not None :
639644 return
@@ -649,7 +654,7 @@ def configure(self, parent: Any = None):
649654 return
650655 self ._install_menu_action (parent , icon )
651656
652- def _install_toolbar_button (self , parent : StatsDialog , icon : QtGui .QIcon ):
657+ def _install_toolbar_button (self , parent : StatsDialogProto , icon : QtGui .QIcon ):
653658 actions_button = getattr (parent , "actionsButton" , None )
654659 if not isinstance (actions_button , QtWidgets .QPushButton ):
655660 return False
@@ -686,7 +691,7 @@ def _install_toolbar_button(self, parent: StatsDialog, icon: QtGui.QIcon):
686691 button .setStatusTip ("Open list subscriptions" )
687692 button .setFlat (True )
688693 if not icon .isNull ():
689- button .setIcon (icon ) # type: ignore[arg-type]
694+ button .setIcon (icon )
690695 button .setCursor (reference_button .cursor ()) # pyright: ignore[reportArgumentType]
691696 button .setFocusPolicy (reference_button .focusPolicy ()) # pyright: ignore[reportArgumentType]
692697 button .setSizePolicy (reference_button .sizePolicy ()) # pyright: ignore[reportArgumentType]
@@ -724,7 +729,7 @@ def _find_layout_containing_widget(
724729 return found
725730 return None
726731
727- def _install_menu_action (self , parent : StatsDialog , icon : QtGui .QIcon ):
732+ def _install_menu_action (self , parent : StatsDialogProto , icon : QtGui .QIcon ):
728733 menu = parent .actionsButton .menu ()
729734 if menu is None :
730735 return
@@ -745,9 +750,10 @@ def _install_menu_action(self, parent: StatsDialog, icon: QtGui.QIcon):
745750 else :
746751 self ._cfg_action = menu .addAction ("List subscriptions" )
747752
748- self ._cfg_action .triggered .connect (lambda * _ : self ._open_config_dialog (parent ))
753+ if self ._cfg_action is not None :
754+ self ._cfg_action .triggered .connect (lambda * _ : self ._open_config_dialog (parent ))
749755
750- def _remove_menu_action (self , parent : StatsDialog ):
756+ def _remove_menu_action (self , parent : StatsDialogProto ):
751757 menu = parent .actionsButton .menu ()
752758 if menu is None :
753759 return
@@ -759,7 +765,7 @@ def _remove_menu_action(self, parent: StatsDialog):
759765 self ._cfg_action = None
760766 break
761767
762- def _find_quit_action (self , menu : Any ) :
768+ def _find_quit_action (self , menu : QtWidgets . QMenu ) -> QtGui . QAction | None :
763769 qt_key = getattr (getattr (QtCore , "Qt" , object ()), "Key" , None )
764770 key_q = getattr (qt_key , "Key_Q" , None ) if qt_key is not None else None
765771 for act in menu .actions ():
@@ -781,8 +787,10 @@ def _find_quit_action(self, menu: Any):
781787 return acts [- 1 ]
782788 return None
783789
784- def _open_config_dialog (self , parent : Any ):
785- from opensnitch .plugins .list_subscriptions .ui .list_subscriptions_dialog import ListSubscriptionsDialog
790+ def _open_config_dialog (self , parent : StatsDialogProto ):
791+ from opensnitch .plugins .list_subscriptions .ui .views .list_subscriptions_dialog import (
792+ ListSubscriptionsDialog ,
793+ )
786794
787795 appicon = None
788796 try :
@@ -843,7 +851,7 @@ def compile(self):
843851 self ._sync_sources_dirs ()
844852 self ._sync_global_symlinks ()
845853
846- def run (self , parent : Any = None , args : tuple [Any , ...] = ()): # type: ignore[override]
854+ def run (self , parent : StatsDialogProto | None = None , args : tuple [Any , ...] = ()): # type: ignore[override]
847855 """
848856 Start timers.
849857 """
0 commit comments