diff --git a/gui/tray.py b/gui/tray.py new file mode 100644 --- /dev/null +++ b/gui/tray.py @@ -0,0 +1,143 @@ +from PyQt5 import QtCore, QtWidgets, QtGui + +from gui.settings import SettingsForm +from .device_menu import QDeviceMenu + +class TrayManager: + def __init__(self, cdemu, config, dropper): + """ + + :type cdemu: cdemu.CDEmu + :type config: config.config.ConfigFile + :type dropper: gui.dropper.KCDEmuDropperWidget + """ + self.cdemu = cdemu + self.config = config + self.dropper = dropper + self.dropper.changed.connect(self.on_dropper_changed) + self.cdemu.add_handler('devices_changed', self.on_devices_changed) + self.cdemu.add_handler('daemon_stopped', self.on_daemon_stopped) + self.cdemu.add_handler('daemon_started', self.on_daemon_started) + + self.act_device_sep = QtWidgets.QAction(None) + self.act_device_sep.setSeparator(True) + self.act_add = QtWidgets.QAction('Add device', None) + self.act_add.triggered.connect(self.on_act_add) + self.act_remove = QtWidgets.QAction('Remove device', None) + self.act_remove.triggered.connect(self.on_act_remove) + self.act_dropper_show = QtWidgets.QAction('Toggle dropper', None) + self.act_dropper_show.triggered.connect(self.on_act_dropper_show) + self.act_settings = QtWidgets.QAction('Settings', None) + self.act_settings.triggered.connect(self.on_act_settings) + self.act_about = QtWidgets.QAction('About', None) + self.act_about.triggered.connect(self.on_act_about) + self.act_quit = QtWidgets.QAction('Quit', None) + self.act_quit.triggered.connect(self.on_act_quit) + + self.menus = {} + self.ctx_menu = QtWidgets.QMenu() + + icon = QtGui.QIcon(self.config.get_tray_icon()) + self.tray_icon = QtWidgets.QSystemTrayIcon(icon) + self.tray_icon.setIcon(icon) + self.tray_icon.setContextMenu(self.ctx_menu) + self.tray_icon.activated.connect(self.on_tray_icon_activated) + self.tray_icon.setToolTip('KCDEmu') + self.tray_icon.show() + self.update_menu() + + def update_menu(self): + self.ctx_menu.clear() + self.ctx_menu.addAction(self.act_device_sep) + self.ctx_menu.addAction(self.act_add) + self.ctx_menu.addAction(self.act_remove) + self.ctx_menu.addSeparator() + self.ctx_menu.addAction(self.act_dropper_show) + self.ctx_menu.addAction(self.act_settings) + self.ctx_menu.addAction(self.act_about) + self.ctx_menu.addAction(self.act_quit) + if self.cdemu.is_daemon_ready(): + self.on_devices_changed() + + def toggle_dropper_visibility(self): + # TODO move to dropper object + if self.dropper.isVisible(): + self.dropper.hide() + else: + self.dropper.show() + geo = QtWidgets.QApplication.desktop().availableGeometry() + position = self.config.get_position() + offset = self.config.get_offset() + if position == self.config.POSITION_TOP_LEFT: + self.dropper.move(offset[0], offset[1]) + elif position == self.config.POSITION_TOP_RIGHT: + self.dropper.move(geo.width() - self.dropper.width() - offset[0], offset[1]) + elif position == self.config.POSITION_BOTTOM_LEFT: + self.dropper.move(offset[0], geo.height() - self.dropper.height() - offset[1]) + elif position == self.config.POSITION_BOTTOM_RIGHT: + self.dropper.move( + geo.width() - self.dropper.width() - offset[0], geo.height() - self.dropper.height() - offset[1] + ) + + def on_tray_icon_activated(self, reason): + if reason == QtWidgets.QSystemTrayIcon.Trigger: + self.toggle_dropper_visibility() + + def on_dropper_changed(self): + if self.dropper.isVisible(): + geo = QtWidgets.QApplication.desktop().availableGeometry() + self.dropper.move(geo.width() - self.dropper.width() - 16, geo.height() - self.dropper.height() - 16) + + def on_act_quit(self): + QtCore.QCoreApplication.exit(0) + + def on_act_dropper_show(self): + self.toggle_dropper_visibility() + + def on_act_settings(self): + settings_form = SettingsForm(self.config) + settings_form.exec_() + + def on_act_about(self): + print(self.cdemu.daemon.get_daemon_version()) + settings_form = SettingsForm(1) + settings_form.exec_() + + def on_act_add(self): + self.cdemu.add_device() + + def on_act_remove(self): + self.cdemu.remove_device() + + def get_menu_for_device(self, number, device): + if number in self.menus: + return self.menus[number] + else: + self.menus[number] = QDeviceMenu(device) + for k in sorted(self.menus.keys()): + if k > number: + self.ctx_menu.insertMenu(self.menus[number], self.menus[k]) + self.ctx_menu.insertMenu(self.act_device_sep, self.menus[number]) + + def on_devices_changed(self, number=None): + devices = self.cdemu.get_devices() + for key in list(self.menus.keys()): + if key >= len(devices): + self.ctx_menu.removeAction(self.menus[key].menuAction()) + del self.menus[key] + + if number is None: + for number, device in enumerate(devices): + self.on_device_changed(device, self.get_menu_for_device(number, device)) + else: + device = self.cdemu.get_devices()[number] + self.on_device_changed(device, self.get_menu_for_device(number, device)) + + def on_device_changed(self, device, menu): + pass + + def on_daemon_started(self): + self.tray_icon.showMessage('KCDEmu', 'cdemu-daemon is ready') + + def on_daemon_stopped(self): + self.tray_icon.showMessage('KCDEmu', 'cdemu-daemon has stopped')