diff -r 60cb9d784005 -r 5b635dc8895f PluginExtensionIrc.py --- a/PluginExtensionIrc.py Fri Apr 18 12:57:19 2025 +0200 +++ b/PluginExtensionIrc.py Fri Apr 18 18:36:48 2025 +0200 @@ -0,0 +1,360 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2025 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a plug-in providing IRC communication capability. +""" + +import logging +import os + +from PyQt6.QtCore import QCoreApplication, QObject, Qt, QTranslator +from PyQt6.QtGui import QIcon, QKeySequence, QPixmap + +from eric7 import EricUtilities, Preferences +from eric7.EricGui import EricPixmapCache +from eric7.EricGui.EricAction import EricAction +from eric7.EricWidgets.EricApplication import ericApp +from eric7.UI.UserInterface import UserInterfaceSide + +# Start-Of-Header +__header__ = { + "name": "IRC Extension Plugin", + "author": "Detlev Offenbach <detlev@die-offenbachs.de>", + "autoactivate": True, + "deactivateable": True, + "version": "10.x", + "className": "IrcExtensionPlugin", + "packageName": "ExtensionIrc", + "shortDescription": "This plug-in adds a widget to communicate via IRC messa", + "longDescription": ( + "This plug-in adds a widget to communicate via IRC messages. It replaces" + " the formerly integrated variant." + ), + "needsRestart": False, + "hasCompiledForms": True, + "pyqtApi": 2, +} +# End-Of-Header + +error = "" # noqa: U-200 + +ircExtensionPluginObject = None + + +def createIrcPage(configDlg): # noqa: U-100 + """ + Function to create the IRC configuration page. + + @param configDlg reference to the configuration dialog + @type ConfigurationWidget + @return reference to the configuration page + @rtype TranslatorPage + """ + global ircExtensionPluginObject + from ExtensionIrc.ConfigurationPage.IrcPage import IrcPage # noqa: I-101, I-102 + + page = IrcPage(ircExtensionPluginObject) + return page + + +def getConfigData(): + """ + Function returning data as required by the configuration dialog. + + @return dictionary containing the relevant data + @rtype dict + """ + return { + "ircPage": [ + QCoreApplication.translate("IrcExtensionPlugin", "IRC"), + os.path.join("ExtensionIrc", "icons", "irc"), + createIrcPage, + None, + None, + ], + } + + +def prepareUninstall(): + """ + Function to prepare for an un-installation. + """ + Preferences.getSettings().remove(IrcExtensionPlugin.PreferencesKey) + + +class IrcExtensionPlugin(QObject): + """ + Class documentation goes here. + """ + + PreferencesKey = "IRC" + + def __init__(self, ui): + """ + Constructor + + @param ui reference to the user interface object + @type UI.UserInterface + """ + super().__init__(ui) + self.__ui = ui + self.__initialize() + + self.__defaults = { + "ShowTimestamps": True, + "TimestampIncludeDate": False, + "TimeFormat": "hh:mm", + "DateFormat": "yyyy-MM-dd", + "NetworkMessageColour": "#000055", + "ServerMessageColour": "#91640A", + "ErrorMessageColour": "#FF0000", + "TimestampColour": "#709070", + "HyperlinkColour": "#0000FF", + "ChannelMessageColour": "#000000", + "OwnNickColour": "#000000", + "NickColour": "#18B33C", + "JoinChannelColour": "#72D672", + "LeaveChannelColour": "#B00000", + "ChannelInfoColour": "#9E54B3", + "EnableIrcColours": True, + "IrcColor0": "#FFFF00", + "IrcColor1": "#000000", + "IrcColor2": "#000080", + "IrcColor3": "#008000", + "IrcColor4": "#FF0000", + "IrcColor5": "#A52A2A", + "IrcColor6": "#800080", + "IrcColor7": "#FF8000", + "IrcColor8": "#808000", + "IrcColor9": "#00FF00", + "IrcColor10": "#008080", + "IrcColor11": "#00FFFF", + "IrcColor12": "#0000FF", + "IrcColor13": "#FFC0CB", + "IrcColor14": "#A0A0A0", + "IrcColor15": "#C0C0C0", + "ShowNotifications": True, + "NotifyJoinPart": True, + "NotifyMessage": False, + "NotifyNick": False, + "AutoUserInfoLookup": True, + "AutoUserInfoMax": 200, + "AutoUserInfoInterval": 90, + "MarkPositionWhenHidden": True, + "MarkerLineForegroundColour": "#000000", # Black on + "MarkerLineBackgroundColour": "#ffff00", # Yellow + } + + self.__translator = None + self.__loadTranslator() + + def __initialize(self): + """ + Private slot to (re)initialize the plugin. + """ + self.__irc = None + + def activate(self): + """ + Public method to activate this plug-in. + + @return tuple of None and activation status + @rtype bool + """ + global error, ircExtensionPluginObject + error = "" # clear previous error + ircExtensionPluginObject = self + + # Create the IRC user interface + logging.getLogger(__name__).debug("Creating IRC Widget...") + from ExtensionIrc.IrcWidget import IrcWidget # noqa: I-101, I-102 + + usesDarkPalette = ericApp().usesDarkPalette() + self.__iconType = "dark" if usesDarkPalette else "light" + + self.__irc = IrcWidget(plugin=self) + iconName = "sbIrc96" if self.__ui.getLayoutType() == "Sidebars" else "irc" + self.__ui.addSideWidget( + UserInterfaceSide.Right, + self.__irc, + self.getIcon(iconName), + self.tr("IRC"), + ) + + self.__activateAct = EricAction( + self.tr("IRC"), + self.tr("&IRC"), + QKeySequence(self.tr("Ctrl+Alt+Shift+I")), + 0, + self, + "irc_widget_activate", + ) + self.__activateAct.setStatusTip( + self.tr("Switch the input focus to the IRC window.") + ) + self.__activateAct.setWhatsThis( + self.tr( + """<b>Activate IRC</b>""" + """<p>This switches the input focus to the IRC window.</p>""" + ) + ) + self.__activateAct.triggered.connect(self.__activateWidget) + + self.__ui.addEricActions([self.__activateAct], "ui") + menu = self.__ui.getMenu("subwindow") + menu.addAction(self.__activateAct) + + ericApp().getObject("PluginManager").shutdown.connect(self.__irc.shutdown) + + self.__irc.autoConnected.connect(self.__activateWidget) + self.__irc.autoConnect() + + return None, True + + def deactivate(self): + """ + Public method to deactivate this plug-in. + """ + menu = self.__ui.getMenu("subwindow") + menu.removeAction(self.__activateAct) + self.__ui.removeEricActions([self.__activateAct], "ui") + self.__ui.removeSideWidget(self.__irc) + + self.__initialize() + + def __getIconPaths(self, iconName): + """ + Private method to generate a list of paths to check for the requested icon name. + + @param iconName name of the icon + @type str + @return list of icon path names + @rtype list of str + """ + return [ + os.path.join("ExtensionIrc", "icons", self.__iconType, iconName), + os.path.join("ExtensionIrc", "icons", iconName), # without icon type + ] + + def getIcon(self, iconName): + """ + Public method to get a named icon. + + @param iconName name of the icon + @type str + @return requested icon + @rtype QIcon + """ + icon = QIcon() + + for iconPath in self.__getIconPaths(iconName): + icon = EricPixmapCache.getIcon(iconPath) + if not icon.isNull(): + break + + return icon + + def getPixmap(self, pixmapName): + """ + Public method to get a named pixmap. + + @param pixmapName name of the pixmap + @type str + @return requested pixmap + @rtype QPixmap + """ + pixmap = QPixmap() + + for pixPath in self.__getIconPaths(pixmapName): + pixmap = EricPixmapCache.getPixmap(pixPath) + if not pixmap.isNull(): + break + + return pixmap + + def __loadTranslator(self): + """ + Private method to load the translation file. + """ + if self.__ui is not None: + loc = self.__ui.getLocale() + if loc and loc != "C": + locale_dir = os.path.join( + os.path.dirname(__file__), "ExtensionIrc", "i18n" + ) + translation = "icr_{0}".format(loc) + translator = QTranslator(None) + loaded = translator.load(translation, locale_dir) + if loaded: + self.__translator = translator + ericApp().installTranslator(self.__translator) + else: + print( # noqa: M-801 + "Warning: translation file '{0}' could not be" + " loaded.".format(translation) + ) + print("Using default.") # noqa: M-801 + + def __activateWidget(self): + """ + Private slot to handle the activation of the MQTT Monitor. + """ + uiLayoutType = self.__ui.getLayoutType() + + if uiLayoutType == "Toolboxes": + self.__ui.rToolboxDock.show() + self.__ui.rToolbox.setCurrentWidget(self.irc) + elif uiLayoutType == "Sidebars": + self.__ui.activateLeftRightSidebarWidget(self.__irc) + self.__irc.setFocus(Qt.FocusReason.ActiveWindowFocusReason) + + def getPreferences(self, key): + """ + Public method to retrieve the various settings values. + + @param key the key of the value to get + @type str + @return the requested setting value + @rtype Any + """ + if key in [ + "TimestampIncludeDate", + "ShowTimestamps", + "ShowNotifications", + "NotifyJoinPart", + "NotifyMessage", + "NotifyNick", + "EnableIrcColours", + "AutoUserInfoLookup", + "MarkPositionWhenHidden", + ]: + return EricUtilities.toBool( + Preferences.Prefs.settings.value( + self.PreferencesKey + "/" + key, self.__defaults[key] + ) + ) + elif key in ["AutoUserInfoMax", "AutoUserInfoInterval"]: + return int( + Preferences.Prefs.settings.value( + self.PreferencesKey + "/" + key, self.__defaults[key] + ) + ) + else: + return Preferences.Prefs.settings.value( + self.PreferencesKey + "/" + key, self.__defaults[key] + ) + return None + + def setPreferences(self, key, value): + """ + Public method to store the various settings values. + + @param key the key of the setting to be set + @type str + @param value the value to be set + @type Any + """ + Preferences.Prefs.settings.setValue(self.PreferencesKey + "/" + key, value)