def __init__(self, parent=None): super().__init__(parent) self.setupUi(self) self._tempsModel = TemperaturesModel(self) self._fanModel = FanModel(self._tempsModel, self) # Connect the temperatures table to the temperatures model self.tempsTable.setModel(self._tempsModel) self.tempsTable.verticalHeader().setSectionResizeMode(QHeaderView.ResizeToContents) # Update the icons when the temperatures change self._tempsModel.modelReset.connect(self.updateTemperatureIcons) # Connect the fan speed and level labels to the fan model. self._fanModel.modelReset.connect(self.updateFanLabels) self.activeButton.toggled.connect(self.toggleTempSensorsVisibility) self.toggleTempSensorsVisibility() self.biosModeButton.toggled.connect(self.enableBIOSMode) self.smartModeButton.toggled.connect(self.enableSmartMode) self.manualModeButton.toggled.connect(self.enableManualMode) for speed in sorted(Fan.FIRMWARE_TO_HWMON): self.manualModeCombo.addItem(FanModel.LEVEL_DISPLAY_STRINGS[speed], speed) self.manualModeCombo.addItem(FanModel.LEVEL_DISPLAY_STRINGS['full-speed'], 'full-speed') self.manualModeCombo.setCurrentIndex(len(Fan.FIRMWARE_TO_HWMON)) # Changing the selected level changes the fan level immediately if manual mode is enabled self.manualModeCombo.currentIndexChanged.connect(self.enableManualMode) # Start off the application in smart mode if Fan.isWritable(): self.smartModeButton.setChecked(True) else: self.biosModeButton.setChecked(True) self.show() # The icon engine and icon object self._iconEngine = TPFCIconEngine(self._tempsModel) icon = QIcon(self._iconEngine) # The system tray icon self._systemTrayIcon = QSystemTrayIcon(icon, self) self._systemTrayIcon.activated.connect(self.systemTrayIconActivated) self._systemTrayIcon.setVisible(True) # The window icon self.setWindowIcon(icon) # The context menu for the system tray icon trayIconMenu = QMenu(self) self._systemTrayIcon.setContextMenu(trayIconMenu) # The first entry in the context menu hides or shows the main window self._restoreHideAction = QAction('Hide', self, triggered=self.toggleVisibility) trayIconMenu.addAction(self._restoreHideAction) # The second entry in the context menu resets the system tray icon trayIconMenu.addAction(QAction('Reset icon', self, triggered=self.resetSystemTrayIcon)) # The third entry in the context menu quits the program trayIconMenu.addAction(QAction('Quit', self, triggered=self.quit)) # If the fan level is not modificable, show a warning notification balloon from the system tray icon and disable the fan level controls if not Fan.isWritable(): title = 'Warning' message = 'PyTPFanControl does not have write access to the ACPI interface. Fan speed will be read-only.' dbusAvailable = True try: import dbus try: notifications = dbus.SessionBus().get_object("org.freedesktop.Notifications", '/org/freedesktop/Notifications') notifications.Notify('PyTPFanControl', dbus.UInt32(0), 'dialog-warning', title, message, dbus.Array(signature='s'), dbus.Dictionary(signature='sv'), 0) except dbus.exceptions.DBusException: dbusAvailable = False except ImportError: dbusAvailable = False if not dbusAvailable: QTimer.singleShot(1000, lambda: self._systemTrayIcon.showMessage(title, message, QSystemTrayIcon.Warning)) for control in (self.biosModeButton, self.smartModeButton, self.manualModeButton, self.manualModeCombo): control.setEnabled(False)
class TPFCWindow(CustomClass, WidgetClass): """ Main window of application. """ def __init__(self, parent=None): super().__init__(parent) self.setupUi(self) self._tempsModel = TemperaturesModel(self) self._fanModel = FanModel(self._tempsModel, self) # Connect the temperatures table to the temperatures model self.tempsTable.setModel(self._tempsModel) self.tempsTable.verticalHeader().setSectionResizeMode(QHeaderView.ResizeToContents) # Update the icons when the temperatures change self._tempsModel.modelReset.connect(self.updateTemperatureIcons) # Connect the fan speed and level labels to the fan model. self._fanModel.modelReset.connect(self.updateFanLabels) self.activeButton.toggled.connect(self.toggleTempSensorsVisibility) self.toggleTempSensorsVisibility() self.biosModeButton.toggled.connect(self.enableBIOSMode) self.smartModeButton.toggled.connect(self.enableSmartMode) self.manualModeButton.toggled.connect(self.enableManualMode) for speed in sorted(Fan.FIRMWARE_TO_HWMON): self.manualModeCombo.addItem(FanModel.LEVEL_DISPLAY_STRINGS[speed], speed) self.manualModeCombo.addItem(FanModel.LEVEL_DISPLAY_STRINGS['full-speed'], 'full-speed') self.manualModeCombo.setCurrentIndex(len(Fan.FIRMWARE_TO_HWMON)) # Changing the selected level changes the fan level immediately if manual mode is enabled self.manualModeCombo.currentIndexChanged.connect(self.enableManualMode) # Start off the application in smart mode if Fan.isWritable(): self.smartModeButton.setChecked(True) else: self.biosModeButton.setChecked(True) self.show() # The icon engine and icon object self._iconEngine = TPFCIconEngine(self._tempsModel) icon = QIcon(self._iconEngine) # The system tray icon self._systemTrayIcon = QSystemTrayIcon(icon, self) self._systemTrayIcon.activated.connect(self.systemTrayIconActivated) self._systemTrayIcon.setVisible(True) # The window icon self.setWindowIcon(icon) # The context menu for the system tray icon trayIconMenu = QMenu(self) self._systemTrayIcon.setContextMenu(trayIconMenu) # The first entry in the context menu hides or shows the main window self._restoreHideAction = QAction('Hide', self, triggered=self.toggleVisibility) trayIconMenu.addAction(self._restoreHideAction) # The second entry in the context menu resets the system tray icon trayIconMenu.addAction(QAction('Reset icon', self, triggered=self.resetSystemTrayIcon)) # The third entry in the context menu quits the program trayIconMenu.addAction(QAction('Quit', self, triggered=self.quit)) # If the fan level is not modificable, show a warning notification balloon from the system tray icon and disable the fan level controls if not Fan.isWritable(): title = 'Warning' message = 'PyTPFanControl does not have write access to the ACPI interface. Fan speed will be read-only.' dbusAvailable = True try: import dbus try: notifications = dbus.SessionBus().get_object("org.freedesktop.Notifications", '/org/freedesktop/Notifications') notifications.Notify('PyTPFanControl', dbus.UInt32(0), 'dialog-warning', title, message, dbus.Array(signature='s'), dbus.Dictionary(signature='sv'), 0) except dbus.exceptions.DBusException: dbusAvailable = False except ImportError: dbusAvailable = False if not dbusAvailable: QTimer.singleShot(1000, lambda: self._systemTrayIcon.showMessage(title, message, QSystemTrayIcon.Warning)) for control in (self.biosModeButton, self.smartModeButton, self.manualModeButton, self.manualModeCombo): control.setEnabled(False) def toggleTempSensorsVisibility(self): for name in Settings.HIDDEN_TEMPS: self.tempsTable.setRowHidden(Settings.SENSOR_NAMES.index(name), self.activeButton.isChecked()) def enableBIOSMode(self): """ Enable BIOS mode if the BIOS mode button is checked. """ if self.biosModeButton.isChecked(): self._fanModel.setBIOSMode() def enableSmartMode(self): """ Enable smart mode if the smart mode button is checked. """ if self.smartModeButton.isChecked(): self._fanModel.setSmartMode() def enableManualMode(self): """ Enable manual mode if the manual mode button is checked. """ if self.manualModeButton.isChecked(): self._fanModel.setManualMode(self.manualModeCombo.itemData(self.manualModeCombo.currentIndex())) def updateTemperatureIcons(self): """ Update the system tray icon and the window icon to display the name and temperature of the hottest sensor. """ # Only re-compute the icons if the icon has changed if self._iconEngine.update(): self._systemTrayIcon.setIcon(self._systemTrayIcon.icon()) self.setWindowIcon(self.windowIcon()) def updateFanLabels(self): """ Update the fan speed and level labels. """ self.fanLevelLabel.setText(FanModel.LEVEL_DISPLAY_STRINGS[self._fanModel.level()]) self.fanSpeedLabel.setText(self._fanModel.speed()) def systemTrayIconActivated(self, reason): if reason == QSystemTrayIcon.Trigger: self.toggleVisibility() elif reason == QSystemTrayIcon.Context: # Set the text of the 'Restore'/'Hide' system tray context menu entry self._restoreHideAction.setText('Hide' if self.isVisible() else 'Restore') def toggleVisibility(self): """ Toggle the visibility of the main window. """ self.setVisible(not self.isVisible()) def quit(self): """ Set the fan back into BIOS mode and quit the application. """ self._fanModel.setBIOSMode() QCoreApplication.instance().quit() def resetSystemTrayIcon(self): """ Reset the system tray icon. """ self._systemTrayIcon.setVisible(False) self._systemTrayIcon.setVisible(True) def showEvent(self, event): # If the window is being restored, force it to not be minimized if self.windowState() == Qt.WindowMinimized: self.setWindowState(Qt.WindowNoState) def closeEvent(self, event): """ Suppress the window's close event and hide it instead. The application only quits when the 'Quit' system tray context menu entry is selected. """ self.hide() event.ignore()