diff --git a/data/interfaces/default/images/logo.ico b/data/interfaces/default/images/logo.ico deleted file mode 100644 index a8ae0772..00000000 Binary files a/data/interfaces/default/images/logo.ico and /dev/null differ diff --git a/data/interfaces/default/images/logo_tray-update.ico b/data/interfaces/default/images/logo_tray-update.ico new file mode 100644 index 00000000..05f4a98c Binary files /dev/null and b/data/interfaces/default/images/logo_tray-update.ico differ diff --git a/data/interfaces/default/images/logo_tray.ico b/data/interfaces/default/images/logo_tray.ico new file mode 100644 index 00000000..71ed8d90 Binary files /dev/null and b/data/interfaces/default/images/logo_tray.ico differ diff --git a/lib/systray/traybar.py b/lib/systray/traybar.py index dd528dff..dd3109f6 100644 --- a/lib/systray/traybar.py +++ b/lib/systray/traybar.py @@ -38,7 +38,7 @@ class SysTrayIcon(object): self._on_quit = on_quit menu_options = menu_options or () - menu_options = menu_options + (('Quit', None, SysTrayIcon.QUIT),) + menu_options = menu_options + (('Quit', None, SysTrayIcon.QUIT, None),) self._next_action_id = SysTrayIcon.FIRST_ID self._menu_actions_by_id = set() self._menu_options = self._add_ids_to_menu_options(list(menu_options)) @@ -134,13 +134,20 @@ class SysTrayIcon(object): def _add_ids_to_menu_options(self, menu_options): result = [] for menu_option in menu_options: - option_text, option_icon, option_action = menu_option + option_text, option_icon, option_action, option_state = menu_option if callable(option_action) or option_action in SysTrayIcon.SPECIAL_ACTIONS: self._menu_actions_by_id.add((self._next_action_id, option_action)) result.append(menu_option + (self._next_action_id,)) + elif option_action == 'separator': + result.append((option_text, + option_icon, + option_action, + option_state, + self._next_action_id)) elif non_string_iterable(option_action): result.append((option_text, option_icon, + option_state, self._add_ids_to_menu_options(option_action), self._next_action_id)) else: @@ -232,22 +239,36 @@ class SysTrayIcon(object): PostMessage(self._hwnd, WM_NULL, 0, 0) def _create_menu(self, menu, menu_options): - for option_text, option_icon, option_action, option_id in menu_options[::-1]: + for option_text, option_icon, option_action, option_state, option_id in menu_options[::-1]: if option_icon: option_icon = self._prep_menu_icon(option_icon) - if option_id in self._menu_actions_by_id: - item = PackMENUITEMINFO(text=option_text, - hbmpItem=option_icon, - wID=option_id) - InsertMenuItem(menu, 0, 1, ctypes.byref(item)) - else: + mi_fstate = 0 + mi_ftype = 0 + + if option_state == 'default': + mi_fstate = mi_fstate | MFS_DEFAULT + if option_state == 'highlight': + mi_fstate = mi_fstate | MFS_HILITE + if option_state == 'disabled': + mi_fstate = mi_fstate | MFS_DISABLED + if option_action == 'separator': + mi_ftype = mi_ftype | MFT_SEPARATOR + + if isinstance(option_action, tuple): submenu = CreatePopupMenu() self._create_menu(submenu, option_action) item = PackMENUITEMINFO(text=option_text, hbmpItem=option_icon, hSubMenu=submenu) InsertMenuItem(menu, 0, 1, ctypes.byref(item)) + else: + item = PackMENUITEMINFO(text=option_text, + hbmpItem=option_icon, + wID=option_id, + fState=mi_fstate, + fType=mi_ftype) + InsertMenuItem(menu, 0, 1, ctypes.byref(item)) def _prep_menu_icon(self, icon): icon = encode_for_locale(icon) diff --git a/lib/systray/win32_adapter.py b/lib/systray/win32_adapter.py index f8924f91..7850b8f9 100644 --- a/lib/systray/win32_adapter.py +++ b/lib/systray/win32_adapter.py @@ -42,10 +42,12 @@ NIM_DELETE = 2 NIF_ICON = 2 NIF_MESSAGE = 1 NIF_TIP = 4 +MIIM_STATE = 1 MIIM_ID = 2 MIIM_SUBMENU = 4 MIIM_STRING = 64 MIIM_BITMAP = 128 +MIIM_FTYPE = 256 WM_DESTROY = 2 WM_CLOSE = 16 WM_COMMAND = 273 @@ -70,6 +72,10 @@ SM_CXSMICON = 49 SM_CYSMICON = 50 COLOR_MENU = 4 DI_NORMAL = 3 +MFS_DISABLED = 3 +MFS_DEFAULT = 4096 +MFS_HILITE = 128 +MFT_SEPARATOR = 2048 WPARAM = ctypes.wintypes.WPARAM LPARAM = ctypes.wintypes.LPARAM @@ -145,7 +151,8 @@ class NOTIFYICONDATA(ctypes.Structure): _fields_.append(("hBalloonIcon", HANDLE)) -def PackMENUITEMINFO(text=None, hbmpItem=None, wID=None, hSubMenu=None): +def PackMENUITEMINFO(text=None, hbmpItem=None, wID=None, hSubMenu=None, + fType=None, fState=None): res = MENUITEMINFO() res.cbSize = ctypes.sizeof(res) res.fMask = 0 @@ -162,6 +169,12 @@ def PackMENUITEMINFO(text=None, hbmpItem=None, wID=None, hSubMenu=None): if hSubMenu is not None: res.fMask |= MIIM_SUBMENU res.hSubMenu = hSubMenu + if fType is not None: + res.fMask |= MIIM_FTYPE + res.fType = fType + if fState is not None: + res.fMask |= MIIM_STATE + res.fState = fState return res def LOWORD(w): diff --git a/plexpy/__init__.py b/plexpy/__init__.py index 1165f2a6..948f53db 100644 --- a/plexpy/__init__.py +++ b/plexpy/__init__.py @@ -386,7 +386,17 @@ def win_system_tray(): from systray import SysTrayIcon def tray_open(sysTrayIcon): - launch_browser(CONFIG.HTTP_HOST, HTTP_PORT, HTTP_ROOT) + launch_browser(plexpy.CONFIG.HTTP_HOST, plexpy.HTTP_PORT, plexpy.HTTP_ROOT) + + def tray_check_update(sysTrayIcon): + versioncheck.check_update() + + def tray_update(sysTrayIcon): + if plexpy.UPDATE_AVAILABLE: + plexpy.SIGNAL = 'update' + else: + hover_text = common.PRODUCT + ' - No Update Available' + plexpy.WIN_SYS_TRAY_ICON.update(hover_text=hover_text) def tray_restart(sysTrayIcon): plexpy.SIGNAL = 'restart' @@ -394,10 +404,18 @@ def win_system_tray(): def tray_quit(sysTrayIcon): plexpy.SIGNAL = 'shutdown' - icon = os.path.join(PROG_DIR, 'data/interfaces/', CONFIG.INTERFACE, 'images/logo.ico') - hover_text = common.PRODUCT - menu_options = (('Open Tautulli', None, tray_open), - ('Restart', None, tray_restart)) + if plexpy.UPDATE_AVAILABLE: + icon = os.path.join(plexpy.PROG_DIR, 'data/interfaces/', plexpy.CONFIG.INTERFACE, 'images/logo_tray-update.ico') + hover_text = common.PRODUCT + ' - Update Available!' + else: + icon = os.path.join(plexpy.PROG_DIR, 'data/interfaces/', plexpy.CONFIG.INTERFACE, 'images/logo_tray.ico') + hover_text = common.PRODUCT + + menu_options = (('Open Tautulli', None, tray_open, 'default'), + ('', None, 'separator', None), + ('Check for Updates', None, tray_check_update, None), + ('Update', None, tray_update, None), + ('Restart', None, tray_restart, None)) logger.info(u"Launching system tray icon.") diff --git a/plexpy/versioncheck.py b/plexpy/versioncheck.py index 52d19289..bc8a8000 100644 --- a/plexpy/versioncheck.py +++ b/plexpy/versioncheck.py @@ -145,6 +145,15 @@ def check_update(auto_update=False, notify=False): else: plexpy.UPDATE_AVAILABLE = False + if plexpy.WIN_SYS_TRAY_ICON: + if plexpy.UPDATE_AVAILABLE: + icon = os.path.join(plexpy.PROG_DIR, 'data/interfaces/', plexpy.CONFIG.INTERFACE, 'images/logo-update.ico') + hover_text = common.PRODUCT + ' - Update Available!' + else: + icon = os.path.join(plexpy.PROG_DIR, 'data/interfaces/', plexpy.CONFIG.INTERFACE, 'images/logo.ico') + hover_text = common.PRODUCT + ' - No Update Available' + plexpy.WIN_SYS_TRAY_ICON.update(icon=icon, hover_text=hover_text) + def check_github(auto_update=False, notify=False): plexpy.COMMITS_BEHIND = 0