|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2025 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing a plug-in providing IRC communication capability. |
|
8 """ |
|
9 |
|
10 import logging |
|
11 import os |
|
12 |
|
13 from PyQt6.QtCore import QCoreApplication, QObject, Qt, QTranslator |
|
14 from PyQt6.QtGui import QIcon, QKeySequence, QPixmap |
|
15 |
|
16 from eric7 import EricUtilities, Preferences |
|
17 from eric7.EricGui import EricPixmapCache |
|
18 from eric7.EricGui.EricAction import EricAction |
|
19 from eric7.EricWidgets.EricApplication import ericApp |
|
20 from eric7.UI.UserInterface import UserInterfaceSide |
|
21 |
|
22 # Start-Of-Header |
|
23 __header__ = { |
|
24 "name": "IRC Extension Plugin", |
|
25 "author": "Detlev Offenbach <detlev@die-offenbachs.de>", |
|
26 "autoactivate": True, |
|
27 "deactivateable": True, |
|
28 "version": "10.x", |
|
29 "className": "IrcExtensionPlugin", |
|
30 "packageName": "ExtensionIrc", |
|
31 "shortDescription": "This plug-in adds a widget to communicate via IRC messa", |
|
32 "longDescription": ( |
|
33 "This plug-in adds a widget to communicate via IRC messages. It replaces" |
|
34 " the formerly integrated variant." |
|
35 ), |
|
36 "needsRestart": False, |
|
37 "hasCompiledForms": True, |
|
38 "pyqtApi": 2, |
|
39 } |
|
40 # End-Of-Header |
|
41 |
|
42 error = "" # noqa: U-200 |
|
43 |
|
44 ircExtensionPluginObject = None |
|
45 |
|
46 |
|
47 def createIrcPage(configDlg): # noqa: U-100 |
|
48 """ |
|
49 Function to create the IRC configuration page. |
|
50 |
|
51 @param configDlg reference to the configuration dialog |
|
52 @type ConfigurationWidget |
|
53 @return reference to the configuration page |
|
54 @rtype TranslatorPage |
|
55 """ |
|
56 global ircExtensionPluginObject |
|
57 from ExtensionIrc.ConfigurationPage.IrcPage import IrcPage # noqa: I-101, I-102 |
|
58 |
|
59 page = IrcPage(ircExtensionPluginObject) |
|
60 return page |
|
61 |
|
62 |
|
63 def getConfigData(): |
|
64 """ |
|
65 Function returning data as required by the configuration dialog. |
|
66 |
|
67 @return dictionary containing the relevant data |
|
68 @rtype dict |
|
69 """ |
|
70 return { |
|
71 "ircPage": [ |
|
72 QCoreApplication.translate("IrcExtensionPlugin", "IRC"), |
|
73 os.path.join("ExtensionIrc", "icons", "irc"), |
|
74 createIrcPage, |
|
75 None, |
|
76 None, |
|
77 ], |
|
78 } |
|
79 |
|
80 |
|
81 def prepareUninstall(): |
|
82 """ |
|
83 Function to prepare for an un-installation. |
|
84 """ |
|
85 Preferences.getSettings().remove(IrcExtensionPlugin.PreferencesKey) |
|
86 |
|
87 |
|
88 class IrcExtensionPlugin(QObject): |
|
89 """ |
|
90 Class documentation goes here. |
|
91 """ |
|
92 |
|
93 PreferencesKey = "IRC" |
|
94 |
|
95 def __init__(self, ui): |
|
96 """ |
|
97 Constructor |
|
98 |
|
99 @param ui reference to the user interface object |
|
100 @type UI.UserInterface |
|
101 """ |
|
102 super().__init__(ui) |
|
103 self.__ui = ui |
|
104 self.__initialize() |
|
105 |
|
106 self.__defaults = { |
|
107 "ShowTimestamps": True, |
|
108 "TimestampIncludeDate": False, |
|
109 "TimeFormat": "hh:mm", |
|
110 "DateFormat": "yyyy-MM-dd", |
|
111 "NetworkMessageColour": "#000055", |
|
112 "ServerMessageColour": "#91640A", |
|
113 "ErrorMessageColour": "#FF0000", |
|
114 "TimestampColour": "#709070", |
|
115 "HyperlinkColour": "#0000FF", |
|
116 "ChannelMessageColour": "#000000", |
|
117 "OwnNickColour": "#000000", |
|
118 "NickColour": "#18B33C", |
|
119 "JoinChannelColour": "#72D672", |
|
120 "LeaveChannelColour": "#B00000", |
|
121 "ChannelInfoColour": "#9E54B3", |
|
122 "EnableIrcColours": True, |
|
123 "IrcColor0": "#FFFF00", |
|
124 "IrcColor1": "#000000", |
|
125 "IrcColor2": "#000080", |
|
126 "IrcColor3": "#008000", |
|
127 "IrcColor4": "#FF0000", |
|
128 "IrcColor5": "#A52A2A", |
|
129 "IrcColor6": "#800080", |
|
130 "IrcColor7": "#FF8000", |
|
131 "IrcColor8": "#808000", |
|
132 "IrcColor9": "#00FF00", |
|
133 "IrcColor10": "#008080", |
|
134 "IrcColor11": "#00FFFF", |
|
135 "IrcColor12": "#0000FF", |
|
136 "IrcColor13": "#FFC0CB", |
|
137 "IrcColor14": "#A0A0A0", |
|
138 "IrcColor15": "#C0C0C0", |
|
139 "ShowNotifications": True, |
|
140 "NotifyJoinPart": True, |
|
141 "NotifyMessage": False, |
|
142 "NotifyNick": False, |
|
143 "AutoUserInfoLookup": True, |
|
144 "AutoUserInfoMax": 200, |
|
145 "AutoUserInfoInterval": 90, |
|
146 "MarkPositionWhenHidden": True, |
|
147 "MarkerLineForegroundColour": "#000000", # Black on |
|
148 "MarkerLineBackgroundColour": "#ffff00", # Yellow |
|
149 } |
|
150 |
|
151 self.__translator = None |
|
152 self.__loadTranslator() |
|
153 |
|
154 def __initialize(self): |
|
155 """ |
|
156 Private slot to (re)initialize the plugin. |
|
157 """ |
|
158 self.__irc = None |
|
159 |
|
160 def activate(self): |
|
161 """ |
|
162 Public method to activate this plug-in. |
|
163 |
|
164 @return tuple of None and activation status |
|
165 @rtype bool |
|
166 """ |
|
167 global error, ircExtensionPluginObject |
|
168 error = "" # clear previous error |
|
169 ircExtensionPluginObject = self |
|
170 |
|
171 # Create the IRC user interface |
|
172 logging.getLogger(__name__).debug("Creating IRC Widget...") |
|
173 from ExtensionIrc.IrcWidget import IrcWidget # noqa: I-101, I-102 |
|
174 |
|
175 usesDarkPalette = ericApp().usesDarkPalette() |
|
176 self.__iconType = "dark" if usesDarkPalette else "light" |
|
177 |
|
178 self.__irc = IrcWidget(plugin=self) |
|
179 iconName = "sbIrc96" if self.__ui.getLayoutType() == "Sidebars" else "irc" |
|
180 self.__ui.addSideWidget( |
|
181 UserInterfaceSide.Right, |
|
182 self.__irc, |
|
183 self.getIcon(iconName), |
|
184 self.tr("IRC"), |
|
185 ) |
|
186 |
|
187 self.__activateAct = EricAction( |
|
188 self.tr("IRC"), |
|
189 self.tr("&IRC"), |
|
190 QKeySequence(self.tr("Ctrl+Alt+Shift+I")), |
|
191 0, |
|
192 self, |
|
193 "irc_widget_activate", |
|
194 ) |
|
195 self.__activateAct.setStatusTip( |
|
196 self.tr("Switch the input focus to the IRC window.") |
|
197 ) |
|
198 self.__activateAct.setWhatsThis( |
|
199 self.tr( |
|
200 """<b>Activate IRC</b>""" |
|
201 """<p>This switches the input focus to the IRC window.</p>""" |
|
202 ) |
|
203 ) |
|
204 self.__activateAct.triggered.connect(self.__activateWidget) |
|
205 |
|
206 self.__ui.addEricActions([self.__activateAct], "ui") |
|
207 menu = self.__ui.getMenu("subwindow") |
|
208 menu.addAction(self.__activateAct) |
|
209 |
|
210 ericApp().getObject("PluginManager").shutdown.connect(self.__irc.shutdown) |
|
211 |
|
212 self.__irc.autoConnected.connect(self.__activateWidget) |
|
213 self.__irc.autoConnect() |
|
214 |
|
215 return None, True |
|
216 |
|
217 def deactivate(self): |
|
218 """ |
|
219 Public method to deactivate this plug-in. |
|
220 """ |
|
221 menu = self.__ui.getMenu("subwindow") |
|
222 menu.removeAction(self.__activateAct) |
|
223 self.__ui.removeEricActions([self.__activateAct], "ui") |
|
224 self.__ui.removeSideWidget(self.__irc) |
|
225 |
|
226 self.__initialize() |
|
227 |
|
228 def __getIconPaths(self, iconName): |
|
229 """ |
|
230 Private method to generate a list of paths to check for the requested icon name. |
|
231 |
|
232 @param iconName name of the icon |
|
233 @type str |
|
234 @return list of icon path names |
|
235 @rtype list of str |
|
236 """ |
|
237 return [ |
|
238 os.path.join("ExtensionIrc", "icons", self.__iconType, iconName), |
|
239 os.path.join("ExtensionIrc", "icons", iconName), # without icon type |
|
240 ] |
|
241 |
|
242 def getIcon(self, iconName): |
|
243 """ |
|
244 Public method to get a named icon. |
|
245 |
|
246 @param iconName name of the icon |
|
247 @type str |
|
248 @return requested icon |
|
249 @rtype QIcon |
|
250 """ |
|
251 icon = QIcon() |
|
252 |
|
253 for iconPath in self.__getIconPaths(iconName): |
|
254 icon = EricPixmapCache.getIcon(iconPath) |
|
255 if not icon.isNull(): |
|
256 break |
|
257 |
|
258 return icon |
|
259 |
|
260 def getPixmap(self, pixmapName): |
|
261 """ |
|
262 Public method to get a named pixmap. |
|
263 |
|
264 @param pixmapName name of the pixmap |
|
265 @type str |
|
266 @return requested pixmap |
|
267 @rtype QPixmap |
|
268 """ |
|
269 pixmap = QPixmap() |
|
270 |
|
271 for pixPath in self.__getIconPaths(pixmapName): |
|
272 pixmap = EricPixmapCache.getPixmap(pixPath) |
|
273 if not pixmap.isNull(): |
|
274 break |
|
275 |
|
276 return pixmap |
|
277 |
|
278 def __loadTranslator(self): |
|
279 """ |
|
280 Private method to load the translation file. |
|
281 """ |
|
282 if self.__ui is not None: |
|
283 loc = self.__ui.getLocale() |
|
284 if loc and loc != "C": |
|
285 locale_dir = os.path.join( |
|
286 os.path.dirname(__file__), "ExtensionIrc", "i18n" |
|
287 ) |
|
288 translation = "icr_{0}".format(loc) |
|
289 translator = QTranslator(None) |
|
290 loaded = translator.load(translation, locale_dir) |
|
291 if loaded: |
|
292 self.__translator = translator |
|
293 ericApp().installTranslator(self.__translator) |
|
294 else: |
|
295 print( # noqa: M-801 |
|
296 "Warning: translation file '{0}' could not be" |
|
297 " loaded.".format(translation) |
|
298 ) |
|
299 print("Using default.") # noqa: M-801 |
|
300 |
|
301 def __activateWidget(self): |
|
302 """ |
|
303 Private slot to handle the activation of the MQTT Monitor. |
|
304 """ |
|
305 uiLayoutType = self.__ui.getLayoutType() |
|
306 |
|
307 if uiLayoutType == "Toolboxes": |
|
308 self.__ui.rToolboxDock.show() |
|
309 self.__ui.rToolbox.setCurrentWidget(self.irc) |
|
310 elif uiLayoutType == "Sidebars": |
|
311 self.__ui.activateLeftRightSidebarWidget(self.__irc) |
|
312 self.__irc.setFocus(Qt.FocusReason.ActiveWindowFocusReason) |
|
313 |
|
314 def getPreferences(self, key): |
|
315 """ |
|
316 Public method to retrieve the various settings values. |
|
317 |
|
318 @param key the key of the value to get |
|
319 @type str |
|
320 @return the requested setting value |
|
321 @rtype Any |
|
322 """ |
|
323 if key in [ |
|
324 "TimestampIncludeDate", |
|
325 "ShowTimestamps", |
|
326 "ShowNotifications", |
|
327 "NotifyJoinPart", |
|
328 "NotifyMessage", |
|
329 "NotifyNick", |
|
330 "EnableIrcColours", |
|
331 "AutoUserInfoLookup", |
|
332 "MarkPositionWhenHidden", |
|
333 ]: |
|
334 return EricUtilities.toBool( |
|
335 Preferences.Prefs.settings.value( |
|
336 self.PreferencesKey + "/" + key, self.__defaults[key] |
|
337 ) |
|
338 ) |
|
339 elif key in ["AutoUserInfoMax", "AutoUserInfoInterval"]: |
|
340 return int( |
|
341 Preferences.Prefs.settings.value( |
|
342 self.PreferencesKey + "/" + key, self.__defaults[key] |
|
343 ) |
|
344 ) |
|
345 else: |
|
346 return Preferences.Prefs.settings.value( |
|
347 self.PreferencesKey + "/" + key, self.__defaults[key] |
|
348 ) |
|
349 return None |
|
350 |
|
351 def setPreferences(self, key, value): |
|
352 """ |
|
353 Public method to store the various settings values. |
|
354 |
|
355 @param key the key of the setting to be set |
|
356 @type str |
|
357 @param value the value to be set |
|
358 @type Any |
|
359 """ |
|
360 Preferences.Prefs.settings.setValue(self.PreferencesKey + "/" + key, value) |