55import os
66import subprocess
77from collections import defaultdict
8+ from typing import Any , DefaultDict , List , Optional
89
910from PyQt5 import QtCore
1011from PyQt5 .QtWidgets import QApplication , QSystemTrayIcon , QMessageBox , QMenu , QWidget , QPushButton
1112from PyQt5 .QtGui import QIcon
1213
1314import aw_core
1415
15- from .manager import Manager
16+ from .manager import Manager , Module
1617
1718logger = logging .getLogger (__name__ )
1819
1920
20- def open_webui (root_url ) :
21+ def open_webui (root_url : str ) -> None :
2122 print ("Opening dashboard" )
2223 webbrowser .open (root_url )
2324
2425
25- def open_apibrowser (root_url ) :
26+ def open_apibrowser (root_url : str ) -> None :
2627 print ("Opening api browser" )
2728 webbrowser .open (root_url + "/api" )
2829
2930
30- def open_dir (d ) :
31+ def open_dir (d : str ) -> None :
3132 """From: http://stackoverflow.com/a/1795849/965332"""
3233 if sys .platform == 'win32' :
3334 os .startfile (d )
@@ -38,17 +39,18 @@ def open_dir(d):
3839
3940
4041class TrayIcon (QSystemTrayIcon ):
41- def __init__ (self , manager : Manager , icon , parent = None , testing = False ) -> None :
42+ def __init__ (self , manager : Manager , icon : QIcon , parent : Optional [ QWidget ] = None , testing : bool = False ) -> None :
4243 QSystemTrayIcon .__init__ (self , icon , parent )
44+ self ._parent = parent # QSystemTrayIcon also tries to save parent info but it screws up the type info
4345 self .setToolTip ("ActivityWatch" + (" (testing)" if testing else "" ))
4446
4547 self .manager = manager
4648 self .testing = testing
4749
4850 self ._build_rootmenu ()
4951
50- def _build_rootmenu (self ):
51- menu = QMenu (self .parent () )
52+ def _build_rootmenu (self ) -> None :
53+ menu = QMenu (self ._parent )
5254
5355 root_url = "http://localhost:{port}" .format (port = 5666 if self .testing else 5600 )
5456
@@ -80,8 +82,8 @@ def _build_rootmenu(self):
8082
8183 self .setContextMenu (menu )
8284
83- def show_module_failed_dialog (module ) :
84- box = QMessageBox (self .parent () )
85+ def show_module_failed_dialog (module : Module ) -> None :
86+ box = QMessageBox (self ._parent )
8587 box .setIcon (QMessageBox .Warning )
8688 box .setText ("Module {} quit unexpectedly" .format (module .name ))
8789 box .setDetailedText (module .read_log ())
@@ -93,10 +95,10 @@ def show_module_failed_dialog(module):
9395
9496 box .show ()
9597
96- def rebuild_modules_menu ():
98+ def rebuild_modules_menu () -> None :
9799 for action in modulesMenu .actions ():
98100 if action .isEnabled ():
99- name = action .module .name
101+ name = action .data () .name
100102 alive = self .manager .modules [name ].is_alive ()
101103 action .setChecked (alive )
102104 # print(module.text(), alive)
@@ -105,7 +107,7 @@ def rebuild_modules_menu():
105107 QtCore .QTimer .singleShot (2000 , rebuild_modules_menu )
106108 QtCore .QTimer .singleShot (2000 , rebuild_modules_menu )
107109
108- def check_module_status ():
110+ def check_module_status () -> None :
109111 unexpected_exits = self .manager .get_unexpected_stops ()
110112 if unexpected_exits :
111113 for module in unexpected_exits :
@@ -116,19 +118,19 @@ def check_module_status():
116118 QtCore .QTimer .singleShot (2000 , rebuild_modules_menu )
117119 QtCore .QTimer .singleShot (2000 , check_module_status )
118120
119- def _build_modulemenu (self , moduleMenu ) :
121+ def _build_modulemenu (self , moduleMenu : QMenu ) -> None :
120122 moduleMenu .clear ()
121123
122- def add_module_menuitem (module ) :
124+ def add_module_menuitem (module : Module ) -> None :
123125 title = module .name
124126 ac = moduleMenu .addAction (title , lambda : module .toggle ())
125- # Kind of nasty, but a quick way to affiliate the module to the menu action for when it needs updating
126- ac .module = module
127+
128+ ac .setData ( module )
127129 ac .setCheckable (True )
128130 ac .setChecked (module .is_alive ())
129131
130132 # Merged from branch dev/autodetect-modules, still kind of in progress with making this actually work
131- modules_by_location = defaultdict (lambda : list ())
133+ modules_by_location : DefaultDict [ str , List [ Module ]] = defaultdict (lambda : list ())
132134 for module in sorted (self .manager .modules .values (), key = lambda m : m .name ):
133135 modules_by_location [module .location ].append (module )
134136
@@ -140,7 +142,7 @@ def add_module_menuitem(module):
140142 add_module_menuitem (self .manager .modules [module .name ])
141143
142144
143- def exit (manager : Manager ):
145+ def exit (manager : Manager ) -> None :
144146 # TODO: Do cleanup actions
145147 # TODO: Save state for resume
146148 print ("Shutdown initiated, stopping all services..." )
@@ -151,16 +153,17 @@ def exit(manager: Manager):
151153 QApplication .quit ()
152154
153155
154- def run (manager , testing = False ):
156+ def run (manager : Manager , testing : bool = False ) -> Any :
155157 logger .info ("Creating trayicon..." )
156158 # print(QIcon.themeSearchPaths())
157159
158160 app = QApplication (sys .argv )
159161
162+ # FIXME: remove ignores after https://github.com/python/mypy/issues/2955 has been fixed
160163 # Without this, Ctrl+C will have no effect
161- signal .signal (signal .SIGINT , lambda : exit (manager ))
164+ signal .signal (signal .SIGINT , lambda : exit (manager )) #type: ignore
162165 # Ensure cleanup happens on SIGTERM
163- signal .signal (signal .SIGTERM , lambda : exit (manager ))
166+ signal .signal (signal .SIGTERM , lambda : exit (manager )) #type: ignore
164167
165168 timer = QtCore .QTimer ()
166169 timer .start (100 ) # You may change this if you wish.
0 commit comments