src/eric7/Network/IRC/IrcChannelWidget.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
11 11
12 import pathlib 12 import pathlib
13 import re 13 import re
14 14
15 from PyQt6.QtCore import ( 15 from PyQt6.QtCore import (
16 pyqtSlot, pyqtSignal, QDateTime, QPoint, QTimer, QUrl, QCoreApplication 16 pyqtSlot,
17 pyqtSignal,
18 QDateTime,
19 QPoint,
20 QTimer,
21 QUrl,
22 QCoreApplication,
17 ) 23 )
18 from PyQt6.QtGui import QIcon, QPainter, QTextCursor, QDesktopServices 24 from PyQt6.QtGui import QIcon, QPainter, QTextCursor, QDesktopServices
19 from PyQt6.QtWidgets import ( 25 from PyQt6.QtWidgets import (
20 QWidget, QListWidgetItem, QMenu, QApplication, QInputDialog, QLineEdit 26 QWidget,
27 QListWidgetItem,
28 QMenu,
29 QApplication,
30 QInputDialog,
31 QLineEdit,
21 ) 32 )
22 33
23 from EricWidgets import EricMessageBox, EricFileDialog 34 from EricWidgets import EricMessageBox, EricFileDialog
24 from EricWidgets.EricApplication import ericApp 35 from EricWidgets.EricApplication import ericApp
25 36
36 47
37 class IrcUserItem(QListWidgetItem): 48 class IrcUserItem(QListWidgetItem):
38 """ 49 """
39 Class implementing a list widget item containing an IRC channel user. 50 Class implementing a list widget item containing an IRC channel user.
40 """ 51 """
41 Normal = 0x00 # no privileges 52
42 Operator = 0x01 # channel operator 53 Normal = 0x00 # no privileges
43 Voice = 0x02 # voice operator 54 Operator = 0x01 # channel operator
44 Admin = 0x04 # administrator 55 Voice = 0x02 # voice operator
45 Halfop = 0x08 # half operator 56 Admin = 0x04 # administrator
46 Owner = 0x10 # channel owner 57 Halfop = 0x08 # half operator
47 Away = 0x80 # user away 58 Owner = 0x10 # channel owner
48 59 Away = 0x80 # user away
60
49 PrivilegeMapping = { 61 PrivilegeMapping = {
50 "a": Away, 62 "a": Away,
51 "o": Operator, 63 "o": Operator,
52 "O": Owner, 64 "O": Owner,
53 "v": Voice, 65 "v": Voice,
54
55 } 66 }
56 67
57 def __init__(self, name, parent=None): 68 def __init__(self, name, parent=None):
58 """ 69 """
59 Constructor 70 Constructor
60 71
61 @param name string with user name and privilege prefix (string) 72 @param name string with user name and privilege prefix (string)
62 @param parent reference to the parent widget (QListWidget or 73 @param parent reference to the parent widget (QListWidget or
63 QListWidgetItem) 74 QListWidgetItem)
64 """ 75 """
65 super().__init__(name, parent) 76 super().__init__(name, parent)
66 77
67 self.__privilege = IrcUserItem.Normal 78 self.__privilege = IrcUserItem.Normal
68 self.__name = name 79 self.__name = name
69 self.__ignored = False 80 self.__ignored = False
70 81
71 self.__setText() 82 self.__setText()
72 self.__setIcon() 83 self.__setIcon()
73 84
74 def name(self): 85 def name(self):
75 """ 86 """
76 Public method to get the user name. 87 Public method to get the user name.
77 88
78 @return user name (string) 89 @return user name (string)
79 """ 90 """
80 return self.__name 91 return self.__name
81 92
82 def setName(self, name): 93 def setName(self, name):
83 """ 94 """
84 Public method to set a new nick name. 95 Public method to set a new nick name.
85 96
86 @param name new nick name for the user (string) 97 @param name new nick name for the user (string)
87 """ 98 """
88 self.__name = name 99 self.__name = name
89 self.__setText() 100 self.__setText()
90 101
91 def changePrivilege(self, privilege): 102 def changePrivilege(self, privilege):
92 """ 103 """
93 Public method to set or unset a user privilege. 104 Public method to set or unset a user privilege.
94 105
95 @param privilege privilege to set or unset (string) 106 @param privilege privilege to set or unset (string)
96 """ 107 """
97 oper = privilege[0] 108 oper = privilege[0]
98 priv = privilege[1] 109 priv = privilege[1]
99 if priv in IrcUserItem.PrivilegeMapping: 110 if priv in IrcUserItem.PrivilegeMapping:
100 if oper == "+": 111 if oper == "+":
101 self.__privilege |= IrcUserItem.PrivilegeMapping[priv] 112 self.__privilege |= IrcUserItem.PrivilegeMapping[priv]
102 elif oper == "-": 113 elif oper == "-":
103 self.__privilege &= ~IrcUserItem.PrivilegeMapping[priv] 114 self.__privilege &= ~IrcUserItem.PrivilegeMapping[priv]
104 self.__setIcon() 115 self.__setIcon()
105 116
106 def clearPrivileges(self): 117 def clearPrivileges(self):
107 """ 118 """
108 Public method to clear the user privileges. 119 Public method to clear the user privileges.
109 """ 120 """
110 self.__privilege = IrcUserItem.Normal 121 self.__privilege = IrcUserItem.Normal
111 self.__setIcon() 122 self.__setIcon()
112 123
113 def __setText(self): 124 def __setText(self):
114 """ 125 """
115 Private method to set the user item text. 126 Private method to set the user item text.
116 """ 127 """
117 if self.__ignored: 128 if self.__ignored:
118 self.setText(QCoreApplication.translate( 129 self.setText(
119 "IrcUserItem", 130 QCoreApplication.translate("IrcUserItem", "{0} (ignored)").format(
120 "{0} (ignored)").format(self.__name)) 131 self.__name
132 )
133 )
121 else: 134 else:
122 self.setText(self.__name) 135 self.setText(self.__name)
123 136
124 def __setIcon(self): 137 def __setIcon(self):
125 """ 138 """
126 Private method to set the icon dependent on user privileges. 139 Private method to set the icon dependent on user privileges.
127 """ 140 """
128 # step 1: determine the icon 141 # step 1: determine the icon
138 icon = UI.PixmapCache.getIcon("ircAdmin") 151 icon = UI.PixmapCache.getIcon("ircAdmin")
139 else: 152 else:
140 icon = UI.PixmapCache.getIcon("ircNormal") 153 icon = UI.PixmapCache.getIcon("ircNormal")
141 if self.__privilege & IrcUserItem.Away: 154 if self.__privilege & IrcUserItem.Away:
142 icon = self.__awayIcon(icon) 155 icon = self.__awayIcon(icon)
143 156
144 # step 2: set the icon 157 # step 2: set the icon
145 self.setIcon(icon) 158 self.setIcon(icon)
146 159
147 def __awayIcon(self, icon): 160 def __awayIcon(self, icon):
148 """ 161 """
149 Private method to convert an icon to an away icon. 162 Private method to convert an icon to an away icon.
150 163
151 @param icon icon to be converted (QIcon) 164 @param icon icon to be converted (QIcon)
152 @return away icon (QIcon) 165 @return away icon (QIcon)
153 """ 166 """
154 pix1 = icon.pixmap(16, 16) 167 pix1 = icon.pixmap(16, 16)
155 pix2 = UI.PixmapCache.getPixmap("ircAway") 168 pix2 = UI.PixmapCache.getPixmap("ircAway")
156 painter = QPainter(pix1) 169 painter = QPainter(pix1)
157 painter.drawPixmap(0, 0, pix2) 170 painter.drawPixmap(0, 0, pix2)
158 painter.end() 171 painter.end()
159 return QIcon(pix1) 172 return QIcon(pix1)
160 173
161 def parseWhoFlags(self, flags): 174 def parseWhoFlags(self, flags):
162 """ 175 """
163 Public method to parse the user flags reported by a WHO command. 176 Public method to parse the user flags reported by a WHO command.
164 177
165 @param flags user flags as reported by WHO (string) 178 @param flags user flags as reported by WHO (string)
166 """ 179 """
167 # H The user is not away. 180 # H The user is not away.
168 # G The user is set away. 181 # G The user is set away.
169 # * The user is an IRC operator. 182 # * The user is an IRC operator.
179 privilege = IrcUserItem.Admin 192 privilege = IrcUserItem.Admin
180 if flags.startswith("G"): 193 if flags.startswith("G"):
181 privilege |= IrcUserItem.Away 194 privilege |= IrcUserItem.Away
182 self.__privilege = privilege 195 self.__privilege = privilege
183 self.__setIcon() 196 self.__setIcon()
184 197
185 def canChangeTopic(self): 198 def canChangeTopic(self):
186 """ 199 """
187 Public method to check, if the user is allowed to change the topic. 200 Public method to check, if the user is allowed to change the topic.
188 201
189 @return flag indicating that the topic can be changed (boolean) 202 @return flag indicating that the topic can be changed (boolean)
190 """ 203 """
191 return(bool(self.__privilege & IrcUserItem.Operator) or 204 return (
192 bool(self.__privilege & IrcUserItem.Admin) or 205 bool(self.__privilege & IrcUserItem.Operator)
193 bool(self.__privilege & IrcUserItem.Owner)) 206 or bool(self.__privilege & IrcUserItem.Admin)
194 207 or bool(self.__privilege & IrcUserItem.Owner)
208 )
209
195 def setIgnored(self, ignored): 210 def setIgnored(self, ignored):
196 """ 211 """
197 Public method to set the user status to ignored. 212 Public method to set the user status to ignored.
198 213
199 @param ignored flag indicating the new ignored status 214 @param ignored flag indicating the new ignored status
200 @type bool 215 @type bool
201 """ 216 """
202 self.__ignored = ignored 217 self.__ignored = ignored
203 self.__setText() 218 self.__setText()
204 219
205 def isIgnored(self): 220 def isIgnored(self):
206 """ 221 """
207 Public method to check, if this user is ignored. 222 Public method to check, if this user is ignored.
208 223
209 @return flag indicating the ignored status 224 @return flag indicating the ignored status
210 @rtype bool 225 @rtype bool
211 """ 226 """
212 return self.__ignored 227 return self.__ignored
213 228
214 229
215 class IrcChannelWidget(QWidget, Ui_IrcChannelWidget): 230 class IrcChannelWidget(QWidget, Ui_IrcChannelWidget):
216 """ 231 """
217 Class implementing the IRC channel widget. 232 Class implementing the IRC channel widget.
218 233
219 @signal sendData(str) emitted to send a message to the channel 234 @signal sendData(str) emitted to send a message to the channel
220 @signal sendCtcpRequest(str, str, str) emitted to send a CTCP request 235 @signal sendCtcpRequest(str, str, str) emitted to send a CTCP request
221 @signal sendCtcpReply(str, str) emitted to send a CTCP reply 236 @signal sendCtcpReply(str, str) emitted to send a CTCP reply
222 @signal channelClosed(str) emitted after the user has left the channel 237 @signal channelClosed(str) emitted after the user has left the channel
223 @signal openPrivateChat(str) emitted to open a "channel" for private 238 @signal openPrivateChat(str) emitted to open a "channel" for private
225 @signal awayCommand(str) emitted to set the away status via the /away 240 @signal awayCommand(str) emitted to set the away status via the /away
226 command 241 command
227 @signal leaveChannels(list) emitted to leave a list of channels 242 @signal leaveChannels(list) emitted to leave a list of channels
228 @signal leaveAllChannels() emitted to leave all channels 243 @signal leaveAllChannels() emitted to leave all channels
229 """ 244 """
245
230 sendData = pyqtSignal(str) 246 sendData = pyqtSignal(str)
231 sendCtcpRequest = pyqtSignal(str, str, str) 247 sendCtcpRequest = pyqtSignal(str, str, str)
232 sendCtcpReply = pyqtSignal(str, str) 248 sendCtcpReply = pyqtSignal(str, str)
233 channelClosed = pyqtSignal(str) 249 channelClosed = pyqtSignal(str)
234 openPrivateChat = pyqtSignal(str) 250 openPrivateChat = pyqtSignal(str)
235 awayCommand = pyqtSignal(str) 251 awayCommand = pyqtSignal(str)
236 leaveChannels = pyqtSignal(list) 252 leaveChannels = pyqtSignal(list)
237 leaveAllChannels = pyqtSignal() 253 leaveAllChannels = pyqtSignal()
238 254
239 UrlRe = re.compile( 255 UrlRe = re.compile(
240 r"""((?:http|ftp|https):\/\/[\w\-_]+(?:\.[\w\-_]+)+""" 256 r"""((?:http|ftp|https):\/\/[\w\-_]+(?:\.[\w\-_]+)+"""
241 r"""(?:[\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?)""") 257 r"""(?:[\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?)"""
242 258 )
259
243 JoinIndicator = "-->" 260 JoinIndicator = "-->"
244 LeaveIndicator = "<--" 261 LeaveIndicator = "<--"
245 MessageIndicator = "***" 262 MessageIndicator = "***"
246 263
247 def __init__(self, parent=None): 264 def __init__(self, parent=None):
248 """ 265 """
249 Constructor 266 Constructor
250 267
251 @param parent reference to the parent widget (QWidget) 268 @param parent reference to the parent widget (QWidget)
252 """ 269 """
253 super().__init__(parent) 270 super().__init__(parent)
254 self.setupUi(self) 271 self.setupUi(self)
255 272
256 self.__ui = ericApp().getObject("UserInterface") 273 self.__ui = ericApp().getObject("UserInterface")
257 self.__ircWidget = parent 274 self.__ircWidget = parent
258 275
259 self.editTopicButton.setIcon( 276 self.editTopicButton.setIcon(UI.PixmapCache.getIcon("ircEditTopic"))
260 UI.PixmapCache.getIcon("ircEditTopic"))
261 self.editTopicButton.hide() 277 self.editTopicButton.hide()
262 278
263 height = self.usersList.height() + self.messages.height() 279 height = self.usersList.height() + self.messages.height()
264 self.splitter.setSizes([int(height * 0.3), int(height * 0.7)]) 280 self.splitter.setSizes([int(height * 0.3), int(height * 0.7)])
265 281
266 self.__initMessagesMenu() 282 self.__initMessagesMenu()
267 self.__initUsersMenu() 283 self.__initUsersMenu()
268 284
269 self.__name = "" 285 self.__name = ""
270 self.__userName = "" 286 self.__userName = ""
271 self.__partMessage = "" 287 self.__partMessage = ""
272 self.__prefixToPrivilege = {} 288 self.__prefixToPrivilege = {}
273 self.__private = False 289 self.__private = False
274 self.__privatePartner = "" 290 self.__privatePartner = ""
275 self.__whoIsNick = "" 291 self.__whoIsNick = ""
276 292
277 self.__markerLine = "" 293 self.__markerLine = ""
278 self.__hidden = True 294 self.__hidden = True
279 295
280 self.__serviceNamesLower = ["nickserv", "chanserv", "memoserv"] 296 self.__serviceNamesLower = ["nickserv", "chanserv", "memoserv"]
281 297
282 self.__patterns = [ 298 self.__patterns = [
283 # :foo_!n=foo@foohost.bar.net PRIVMSG #eric-ide :some long message 299 # :foo_!n=foo@foohost.bar.net PRIVMSG #eric-ide :some long message
284 # :foo_!n=foo@foohost.bar.net PRIVMSG bar_ :some long message 300 # :foo_!n=foo@foohost.bar.net PRIVMSG bar_ :some long message
285 (re.compile(r":([^!]+)!([^ ]+)\sPRIVMSG\s([^ ]+)\s:(.*)"), 301 (re.compile(r":([^!]+)!([^ ]+)\sPRIVMSG\s([^ ]+)\s:(.*)"), self.__message),
286 self.__message),
287 # :foo_!n=foo@foohost.bar.net JOIN :#eric-ide 302 # :foo_!n=foo@foohost.bar.net JOIN :#eric-ide
288 (re.compile(r":([^!]+)!([^ ]+)\sJOIN\s:?([^ ]+)"), 303 (re.compile(r":([^!]+)!([^ ]+)\sJOIN\s:?([^ ]+)"), self.__userJoin),
289 self.__userJoin),
290 # :foo_!n=foo@foohost.bar.net PART #eric-ide :part message 304 # :foo_!n=foo@foohost.bar.net PART #eric-ide :part message
291 (re.compile(r":([^!]+).*\sPART\s([^ ]+)\s:(.*)"), self.__userPart), 305 (re.compile(r":([^!]+).*\sPART\s([^ ]+)\s:(.*)"), self.__userPart),
292 # :foo_!n=foo@foohost.bar.net PART #eric-ide 306 # :foo_!n=foo@foohost.bar.net PART #eric-ide
293 (re.compile(r":([^!]+).*\sPART\s([^ ]+)\s*"), self.__userPart), 307 (re.compile(r":([^!]+).*\sPART\s([^ ]+)\s*"), self.__userPart),
294 # :foo_!n=foo@foohost.bar.net QUIT :quit message 308 # :foo_!n=foo@foohost.bar.net QUIT :quit message
296 # :foo_!n=foo@foohost.bar.net QUIT 310 # :foo_!n=foo@foohost.bar.net QUIT
297 (re.compile(r":([^!]+).*\sQUIT\s*"), self.__userQuit), 311 (re.compile(r":([^!]+).*\sQUIT\s*"), self.__userQuit),
298 # :foo_!n=foo@foohost.bar.net NICK :newnick 312 # :foo_!n=foo@foohost.bar.net NICK :newnick
299 (re.compile(r":([^!]+).*\sNICK\s:(.*)"), self.__userNickChange), 313 (re.compile(r":([^!]+).*\sNICK\s:(.*)"), self.__userNickChange),
300 # :foo_!n=foo@foohost.bar.net MODE #eric-ide +o foo_ 314 # :foo_!n=foo@foohost.bar.net MODE #eric-ide +o foo_
301 (re.compile(r":([^!]+).*\sMODE\s([^ ]+)\s([+-][ovO]+)\s([^ ]+).*"), 315 (
302 self.__setUserPrivilege), 316 re.compile(r":([^!]+).*\sMODE\s([^ ]+)\s([+-][ovO]+)\s([^ ]+).*"),
317 self.__setUserPrivilege,
318 ),
303 # :cameron.libera.chat MODE #eric-ide +ns 319 # :cameron.libera.chat MODE #eric-ide +ns
304 (re.compile(r":([^ ]+)\sMODE\s([^ ]+)\s(.+)"), 320 (re.compile(r":([^ ]+)\sMODE\s([^ ]+)\s(.+)"), self.__updateChannelModes),
305 self.__updateChannelModes),
306 # :foo_!n=foo@foohost.bar.net TOPIC #eric-ide :eric - Python IDE 321 # :foo_!n=foo@foohost.bar.net TOPIC #eric-ide :eric - Python IDE
307 (re.compile(r":.*\sTOPIC\s([^ ]+)\s:(.*)"), self.__setTopic), 322 (re.compile(r":.*\sTOPIC\s([^ ]+)\s:(.*)"), self.__setTopic),
308 # :sturgeon.libera.chat 301 foo_ bar :Gone away for now 323 # :sturgeon.libera.chat 301 foo_ bar :Gone away for now
309 (re.compile(r":.*\s301\s([^ ]+)\s([^ ]+)\s:(.+)"), 324 (re.compile(r":.*\s301\s([^ ]+)\s([^ ]+)\s:(.+)"), self.__userAway),
310 self.__userAway),
311 # :sturgeon.libera.chat 315 foo_ #eric-ide :End of /WHO list. 325 # :sturgeon.libera.chat 315 foo_ #eric-ide :End of /WHO list.
312 (re.compile(r":.*\s315\s[^ ]+\s([^ ]+)\s:(.*)"), self.__whoEnd), 326 (re.compile(r":.*\s315\s[^ ]+\s([^ ]+)\s:(.*)"), self.__whoEnd),
313 # :zelazny.libera.chat 324 foo_ #eric-ide +cnt 327 # :zelazny.libera.chat 324 foo_ #eric-ide +cnt
314 (re.compile(r":.*\s324\s.*\s([^ ]+)\s(.+)"), self.__channelModes), 328 (re.compile(r":.*\s324\s.*\s([^ ]+)\s(.+)"), self.__channelModes),
315 # :zelazny.libera.chat 328 foo_ #eric-ide :http://www.bugger.com/ 329 # :zelazny.libera.chat 328 foo_ #eric-ide :http://www.bugger.com/
316 (re.compile(r":.*\s328\s.*\s([^ ]+)\s:(.+)"), self.__channelUrl), 330 (re.compile(r":.*\s328\s.*\s([^ ]+)\s:(.+)"), self.__channelUrl),
317 # :zelazny.libera.chat 329 foo_ #eric-ide 1353001005 331 # :zelazny.libera.chat 329 foo_ #eric-ide 1353001005
318 (re.compile(r":.*\s329\s.*\s([^ ]+)\s(.+)"), 332 (re.compile(r":.*\s329\s.*\s([^ ]+)\s(.+)"), self.__channelCreated),
319 self.__channelCreated),
320 # :zelazny.libera.chat 332 foo_ #eric-ide :eric support channel 333 # :zelazny.libera.chat 332 foo_ #eric-ide :eric support channel
321 (re.compile(r":.*\s332\s.*\s([^ ]+)\s:(.*)"), self.__setTopic), 334 (re.compile(r":.*\s332\s.*\s([^ ]+)\s:(.*)"), self.__setTopic),
322 # :zelazny.libera.chat foo_ 333 #eric-ide foo 1353089020 335 # :zelazny.libera.chat foo_ 333 #eric-ide foo 1353089020
323 (re.compile(r":.*\s333\s.*\s([^ ]+)\s([^ ]+)\s(\d+)"), 336 (re.compile(r":.*\s333\s.*\s([^ ]+)\s([^ ]+)\s(\d+)"), self.__topicCreated),
324 self.__topicCreated),
325 # :cameron.libera.chat 352 detlev_ #eric-ide ~foo foohost.bar.net 337 # :cameron.libera.chat 352 detlev_ #eric-ide ~foo foohost.bar.net
326 # cameron.libera.chat foo_ H :0 Foo Bar 338 # cameron.libera.chat foo_ H :0 Foo Bar
327 (re.compile( 339 (
328 r":.*\s352\s[^ ]+\s([^ ]+)\s([^ ]+)\s([^ ]+)\s[^ ]+\s([^ ]+)" 340 re.compile(
329 r"\s([^ ]+)\s:\d+\s(.*)"), self.__whoEntry), 341 r":.*\s352\s[^ ]+\s([^ ]+)\s([^ ]+)\s([^ ]+)\s[^ ]+\s([^ ]+)"
342 r"\s([^ ]+)\s:\d+\s(.*)"
343 ),
344 self.__whoEntry,
345 ),
330 # :zelazny.libera.chat 353 foo_ @ #eric-ide :@user1 +user2 user3 346 # :zelazny.libera.chat 353 foo_ @ #eric-ide :@user1 +user2 user3
331 (re.compile(r":.*\s353\s.*\s.\s([^ ]+)\s:(.*)"), self.__userList), 347 (re.compile(r":.*\s353\s.*\s.\s([^ ]+)\s:(.*)"), self.__userList),
332 # :sturgeon.libera.chat 354 foo_ 42 ChanServ H@ 348 # :sturgeon.libera.chat 354 foo_ 42 ChanServ H@
333 (re.compile(r":.*\s354\s[^ ]+\s42\s([^ ]+)\s(.*)"), 349 (re.compile(r":.*\s354\s[^ ]+\s42\s([^ ]+)\s(.*)"), self.__autoWhoEntry),
334 self.__autoWhoEntry),
335 # :zelazny.libera.chat 366 foo_ #eric-ide :End of /NAMES list. 350 # :zelazny.libera.chat 366 foo_ #eric-ide :End of /NAMES list.
336 (re.compile(r":.*\s366\s.*\s([^ ]+)\s:(.*)"), self.__ignore), 351 (re.compile(r":.*\s366\s.*\s([^ ]+)\s:(.*)"), self.__ignore),
337 # :sturgeon.libera.chat 704 foo_ index :Help topics available: 352 # :sturgeon.libera.chat 704 foo_ index :Help topics available:
338 (re.compile(r":.*\s70[456]\s[^ ]+\s([^ ]+)\s:(.*)"), self.__help), 353 (re.compile(r":.*\s70[456]\s[^ ]+\s([^ ]+)\s:(.*)"), self.__help),
339
340 # WHOIS replies 354 # WHOIS replies
341 # :sturgeon.libera.chat 311 foo_ bar ~bar barhost.foo.net * :Bar 355 # :sturgeon.libera.chat 311 foo_ bar ~bar barhost.foo.net * :Bar
342 (re.compile( 356 (
343 r":.*\s311\s[^ ]+\s([^ ]+)\s([^ ]+)\s([^ ]+)\s\*\s:(.*)"), 357 re.compile(r":.*\s311\s[^ ]+\s([^ ]+)\s([^ ]+)\s([^ ]+)\s\*\s:(.*)"),
344 self.__whoIsUser), 358 self.__whoIsUser,
359 ),
345 # :sturgeon.libera.chat 319 foo_ bar :@#eric-ide 360 # :sturgeon.libera.chat 319 foo_ bar :@#eric-ide
346 (re.compile(r":.*\s319\s[^ ]+\s([^ ]+)\s:(.*)"), 361 (re.compile(r":.*\s319\s[^ ]+\s([^ ]+)\s:(.*)"), self.__whoIsChannels),
347 self.__whoIsChannels),
348 # :sturgeon.libera.chat 312 foo_ bar sturgeon.libera.chat :London 362 # :sturgeon.libera.chat 312 foo_ bar sturgeon.libera.chat :London
349 (re.compile(r":.*\s312\s[^ ]+\s([^ ]+)\s([^ ]+)\s:(.*)"), 363 (
350 self.__whoIsServer), 364 re.compile(r":.*\s312\s[^ ]+\s([^ ]+)\s([^ ]+)\s:(.*)"),
365 self.__whoIsServer,
366 ),
351 # :sturgeon.libera.chat 671 foo_ bar :is using a secure connection 367 # :sturgeon.libera.chat 671 foo_ bar :is using a secure connection
352 (re.compile(r":.*\s671\s[^ ]+\s([^ ]+)\s:.*"), self.__whoIsSecure), 368 (re.compile(r":.*\s671\s[^ ]+\s([^ ]+)\s:.*"), self.__whoIsSecure),
353 # :sturgeon.libera.chat 317 foo_ bar 3758 1355046912 :seconds 369 # :sturgeon.libera.chat 317 foo_ bar 3758 1355046912 :seconds
354 # idle, signon time 370 # idle, signon time
355 (re.compile(r":.*\s317\s[^ ]+\s([^ ]+)\s(\d+)\s(\d+)\s:.*"), 371 (
356 self.__whoIsIdle), 372 re.compile(r":.*\s317\s[^ ]+\s([^ ]+)\s(\d+)\s(\d+)\s:.*"),
373 self.__whoIsIdle,
374 ),
357 # :sturgeon.libera.chat 330 foo_ bar bar :is logged in as 375 # :sturgeon.libera.chat 330 foo_ bar bar :is logged in as
358 (re.compile(r":.*\s330\s[^ ]+\s([^ ]+)\s([^ ]+)\s:.*"), 376 (
359 self.__whoIsAccount), 377 re.compile(r":.*\s330\s[^ ]+\s([^ ]+)\s([^ ]+)\s:.*"),
378 self.__whoIsAccount,
379 ),
360 # :sturgeon.libera.chat 318 foo_ bar :End of /WHOIS list. 380 # :sturgeon.libera.chat 318 foo_ bar :End of /WHOIS list.
361 (re.compile(r":.*\s318\s[^ ]+\s([^ ]+)\s:(.*)"), self.__whoIsEnd), 381 (re.compile(r":.*\s318\s[^ ]+\s([^ ]+)\s:(.*)"), self.__whoIsEnd),
362 # :sturgeon.libera.chat 307 foo_ bar :is an identified user 382 # :sturgeon.libera.chat 307 foo_ bar :is an identified user
363 (re.compile(r":.*\s307\s[^ ]+\s([^ ]+)\s:(.*)"), 383 (re.compile(r":.*\s307\s[^ ]+\s([^ ]+)\s:(.*)"), self.__whoIsIdentify),
364 self.__whoIsIdentify),
365 # :sturgeon.libera.chat 320 foo_ bar :is an identified user 384 # :sturgeon.libera.chat 320 foo_ bar :is an identified user
366 (re.compile(r":.*\s320\s[^ ]+\s([^ ]+)\s:(.*)"), 385 (re.compile(r":.*\s320\s[^ ]+\s([^ ]+)\s:(.*)"), self.__whoIsIdentify),
367 self.__whoIsIdentify),
368 # :sturgeon.libera.chat 310 foo_ bar :is available for help 386 # :sturgeon.libera.chat 310 foo_ bar :is available for help
369 (re.compile(r":.*\s310\s[^ ]+\s([^ ]+)\s:(.*)"), 387 (re.compile(r":.*\s310\s[^ ]+\s([^ ]+)\s:(.*)"), self.__whoIsHelper),
370 self.__whoIsHelper),
371 # :sturgeon.libera.chat 338 foo_ bar real.ident@real.host 388 # :sturgeon.libera.chat 338 foo_ bar real.ident@real.host
372 # 12.34.56.78 :Actual user@host, Actual IP 389 # 12.34.56.78 :Actual user@host, Actual IP
373 (re.compile(r":.*\s338\s[^ ]+\s([^ ]+)\s([^ ]+)\s([^ ]+)\s:.*"), 390 (
374 self.__whoIsActually), 391 re.compile(r":.*\s338\s[^ ]+\s([^ ]+)\s([^ ]+)\s([^ ]+)\s:.*"),
392 self.__whoIsActually,
393 ),
375 # :sturgeon.libera.chat 313 foo_ bar :is an IRC Operator 394 # :sturgeon.libera.chat 313 foo_ bar :is an IRC Operator
376 (re.compile(r":.*\s313\s[^ ]+\s([^ ]+)\s:(.*)"), 395 (re.compile(r":.*\s313\s[^ ]+\s([^ ]+)\s:(.*)"), self.__whoIsOperator),
377 self.__whoIsOperator),
378 # :sturgeon.libera.chat 378 foo_ bar :is connecting from 396 # :sturgeon.libera.chat 378 foo_ bar :is connecting from
379 # *@mnch-4d044d5a.pool.mediaWays.net 77.4.77.90 397 # *@mnch-4d044d5a.pool.mediaWays.net 77.4.77.90
380 (re.compile(r":.*\s378\s[^ ]+\s([^ ]+)\s:.*\s([^ ]+)\s([^ ]+)"), 398 (
381 self.__whoIsConnection), 399 re.compile(r":.*\s378\s[^ ]+\s([^ ]+)\s:.*\s([^ ]+)\s([^ ]+)"),
400 self.__whoIsConnection,
401 ),
382 ] 402 ]
383 403
384 self.__autoWhoTemplate = "WHO {0} %tnf,42" 404 self.__autoWhoTemplate = "WHO {0} %tnf,42"
385 self.__autoWhoTimer = QTimer() 405 self.__autoWhoTimer = QTimer()
386 self.__autoWhoTimer.setSingleShot(True) 406 self.__autoWhoTimer.setSingleShot(True)
387 self.__autoWhoTimer.timeout.connect(self.__sendAutoWhoCommand) 407 self.__autoWhoTimer.timeout.connect(self.__sendAutoWhoCommand)
388 self.__autoWhoRequested = False 408 self.__autoWhoRequested = False
389 409
390 @pyqtSlot() 410 @pyqtSlot()
391 def on_messageEdit_returnPressed(self): 411 def on_messageEdit_returnPressed(self):
392 """ 412 """
393 Private slot to send a message to the channel. 413 Private slot to send a message to the channel.
394 """ 414 """
398 418
399 def __processUserMessage(self, msg): 419 def __processUserMessage(self, msg):
400 """ 420 """
401 Private method to process a message entered by the user or via the 421 Private method to process a message entered by the user or via the
402 user list context menu. 422 user list context menu.
403 423
404 @param msg message to be processed 424 @param msg message to be processed
405 @type str 425 @type str
406 """ 426 """
407 self.messages.append( 427 self.messages.append(
408 '<font color="{0}">{2} <b>&lt;</b><font color="{1}">{3}</font>' 428 '<font color="{0}">{2} <b>&lt;</b><font color="{1}">{3}</font>'
409 '<b>&gt;</b> {4}</font>'.format( 429 "<b>&gt;</b> {4}</font>".format(
410 Preferences.getIrc("ChannelMessageColour"), 430 Preferences.getIrc("ChannelMessageColour"),
411 Preferences.getIrc("OwnNickColour"), 431 Preferences.getIrc("OwnNickColour"),
412 ircTimestamp(), self.__userName, 432 ircTimestamp(),
413 Utilities.html_encode(msg))) 433 self.__userName,
434 Utilities.html_encode(msg),
435 )
436 )
414 437
415 if msg.startswith("/"): 438 if msg.startswith("/"):
416 if self.__private: 439 if self.__private:
417 EricMessageBox.information( 440 EricMessageBox.information(
418 self, 441 self,
419 self.tr("Send Message"), 442 self.tr("Send Message"),
420 self.tr( 443 self.tr(
421 """Messages starting with a '/' are not allowed""" 444 """Messages starting with a '/' are not allowed"""
422 """ in private chats.""")) 445 """ in private chats."""
446 ),
447 )
423 else: 448 else:
424 sendData = True 449 sendData = True
425 # flag set to False, if command was handled 450 # flag set to False, if command was handled
426 451
427 msgList = msg.split() 452 msgList = msg.split()
428 cmd = msgList[0][1:].upper() 453 cmd = msgList[0][1:].upper()
429 if cmd in ["MSG", "QUERY"]: 454 if cmd in ["MSG", "QUERY"]:
430 cmd = "PRIVMSG" 455 cmd = "PRIVMSG"
431 if len(msgList) > 1: 456 if len(msgList) > 1:
432 if ( 457 if msgList[1].strip().lower() in self.__serviceNamesLower:
433 msgList[1].strip().lower() in
434 self.__serviceNamesLower
435 ):
436 msg = ( 458 msg = (
437 "PRIVMSG " + 459 "PRIVMSG "
438 msgList[1].strip().lower() + 460 + msgList[1].strip().lower()
439 " :" + " ".join(msgList[2:]) 461 + " :"
462 + " ".join(msgList[2:])
440 ) 463 )
441 else: 464 else:
442 msg = "PRIVMSG {0} :{1}".format( 465 msg = "PRIVMSG {0} :{1}".format(
443 msgList[1], " ".join(msgList[2:])) 466 msgList[1], " ".join(msgList[2:])
467 )
444 else: 468 else:
445 msgList[0] = cmd 469 msgList[0] = cmd
446 msg = " ".join(msgList) 470 msg = " ".join(msgList)
447 elif cmd == "NOTICE": 471 elif cmd == "NOTICE":
448 if len(msgList) > 2: 472 if len(msgList) > 2:
449 msg = "NOTICE {0} :{1}".format( 473 msg = "NOTICE {0} :{1}".format(
450 msgList[1], " ".join(msgList[2:])) 474 msgList[1], " ".join(msgList[2:])
475 )
451 else: 476 else:
452 msg = "NOTICE {0}".format(" ".join(msgList[1:])) 477 msg = "NOTICE {0}".format(" ".join(msgList[1:]))
453 elif cmd == "PING": 478 elif cmd == "PING":
454 receiver = msgList[1] 479 receiver = msgList[1]
455 msg = "PING {0} " 480 msg = "PING {0} "
464 else: 489 else:
465 ignored = True 490 ignored = True
466 userNamesList = msgList[1:] 491 userNamesList = msgList[1:]
467 else: 492 else:
468 userNamesList = [] 493 userNamesList = []
469 userNames = ",".join( 494 userNames = ",".join(u.rstrip(",") for u in userNamesList).split(
470 u.rstrip(",") for u in userNamesList).split(",") 495 ","
496 )
471 for userName in userNames: 497 for userName in userNames:
472 itm = self.__findUser(userName) 498 itm = self.__findUser(userName)
473 if itm: 499 if itm:
474 itm.setIgnored(ignored) 500 itm.setIgnored(ignored)
475 elif cmd == "UNIGNORE": 501 elif cmd == "UNIGNORE":
476 sendData = False 502 sendData = False
477 if len(msgList) > 1: 503 if len(msgList) > 1:
478 userNamesList = msgList[1:] 504 userNamesList = msgList[1:]
479 else: 505 else:
480 userNamesList = [] 506 userNamesList = []
481 userNames = ",".join( 507 userNames = ",".join(u.rstrip(",") for u in userNamesList).split(
482 u.rstrip(",") for u in userNamesList).split(",") 508 ","
509 )
483 for userName in userNames: 510 for userName in userNames:
484 itm = self.__findUser(userName) 511 itm = self.__findUser(userName)
485 if itm: 512 if itm:
486 itm.setIgnored(False) 513 itm.setIgnored(False)
487 elif cmd == "AWAY": 514 elif cmd == "AWAY":
497 channels = msgList[1].split(",") 524 channels = msgList[1].split(",")
498 if len(msgList) > 2: 525 if len(msgList) > 2:
499 keys = msgList[2].split(",") 526 keys = msgList[2].split(",")
500 else: 527 else:
501 keys = [] 528 keys = []
502 for channel, key in zip_longest( 529 for channel, key in zip_longest(channels, keys, fillvalue=""):
503 channels, keys, fillvalue=""):
504 self.__ircWidget.joinChannel(channel, key) 530 self.__ircWidget.joinChannel(channel, key)
505 elif cmd == "PART": 531 elif cmd == "PART":
506 sendData = False 532 sendData = False
507 if len(msgList) == 1: 533 if len(msgList) == 1:
508 self.leaveChannel() 534 self.leaveChannel()
515 msg = msg[1:] 541 msg = msg[1:]
516 if sendData: 542 if sendData:
517 self.sendData.emit(msg) 543 self.sendData.emit(msg)
518 else: 544 else:
519 if self.__private: 545 if self.__private:
520 self.sendData.emit( 546 self.sendData.emit("PRIVMSG " + self.__privatePartner + " :" + msg)
521 "PRIVMSG " + self.__privatePartner + " :" + msg)
522 else: 547 else:
523 self.sendData.emit( 548 self.sendData.emit("PRIVMSG " + self.__name + " :" + msg)
524 "PRIVMSG " + self.__name + " :" + msg)
525 549
526 self.messageEdit.clear() 550 self.messageEdit.clear()
527 self.unsetMarkerLine() 551 self.unsetMarkerLine()
528 552
529 def requestLeave(self): 553 def requestLeave(self):
530 """ 554 """
531 Public method to leave the channel. 555 Public method to leave the channel.
532 """ 556 """
533 ok = EricMessageBox.yesNo( 557 ok = EricMessageBox.yesNo(
534 self, 558 self,
535 self.tr("Leave IRC channel"), 559 self.tr("Leave IRC channel"),
536 self.tr( 560 self.tr(
537 """Do you really want to leave the IRC channel""" 561 """Do you really want to leave the IRC channel""" """ <b>{0}</b>?"""
538 """ <b>{0}</b>?""").format(self.__name)) 562 ).format(self.__name),
563 )
539 if ok: 564 if ok:
540 self.leaveChannel() 565 self.leaveChannel()
541 566
542 def leaveChannel(self): 567 def leaveChannel(self):
543 """ 568 """
544 Public slot to leave the channel. 569 Public slot to leave the channel.
545 """ 570 """
546 if not self.__private: 571 if not self.__private:
547 self.sendData.emit( 572 self.sendData.emit("PART " + self.__name + " :" + self.__partMessage)
548 "PART " + self.__name + " :" + self.__partMessage)
549 self.channelClosed.emit(self.__name) 573 self.channelClosed.emit(self.__name)
550 574
551 def name(self): 575 def name(self):
552 """ 576 """
553 Public method to get the name of the channel. 577 Public method to get the name of the channel.
554 578
555 @return name of the channel (string) 579 @return name of the channel (string)
556 """ 580 """
557 return self.__name 581 return self.__name
558 582
559 def setName(self, name): 583 def setName(self, name):
560 """ 584 """
561 Public method to set the name of the channel. 585 Public method to set the name of the channel.
562 586
563 @param name of the channel (string) 587 @param name of the channel (string)
564 """ 588 """
565 self.__name = name 589 self.__name = name
566 590
567 def getUsersCount(self): 591 def getUsersCount(self):
568 """ 592 """
569 Public method to get the users count of the channel. 593 Public method to get the users count of the channel.
570 594
571 @return users count of the channel (integer) 595 @return users count of the channel (integer)
572 """ 596 """
573 return self.usersList.count() 597 return self.usersList.count()
574 598
575 def userName(self): 599 def userName(self):
576 """ 600 """
577 Public method to get the nick name of the user. 601 Public method to get the nick name of the user.
578 602
579 @return nick name of the user (string) 603 @return nick name of the user (string)
580 """ 604 """
581 return self.__userName 605 return self.__userName
582 606
583 def setUserName(self, name): 607 def setUserName(self, name):
584 """ 608 """
585 Public method to set the user name for the channel. 609 Public method to set the user name for the channel.
586 610
587 @param name user name for the channel (string) 611 @param name user name for the channel (string)
588 """ 612 """
589 self.__userName = name 613 self.__userName = name
590 614
591 def partMessage(self): 615 def partMessage(self):
592 """ 616 """
593 Public method to get the part message. 617 Public method to get the part message.
594 618
595 @return part message (string) 619 @return part message (string)
596 """ 620 """
597 return self.__partMessage 621 return self.__partMessage
598 622
599 def setPartMessage(self, message): 623 def setPartMessage(self, message):
600 """ 624 """
601 Public method to set the part message. 625 Public method to set the part message.
602 626
603 @param message message to be used for PART messages (string) 627 @param message message to be used for PART messages (string)
604 """ 628 """
605 self.__partMessage = message 629 self.__partMessage = message
606 630
607 def setPrivate(self, private, partner=""): 631 def setPrivate(self, private, partner=""):
608 """ 632 """
609 Public method to set the private chat mode. 633 Public method to set the private chat mode.
610 634
611 @param private flag indicating private chat mode (boolean) 635 @param private flag indicating private chat mode (boolean)
612 @param partner name of the partner user (string) 636 @param partner name of the partner user (string)
613 """ 637 """
614 self.__private = private 638 self.__private = private
615 self.__privatePartner = partner 639 self.__privatePartner = partner
616 self.editTopicButton.setEnabled(private) 640 self.editTopicButton.setEnabled(private)
617 641
618 def setPrivateInfo(self, infoText): 642 def setPrivateInfo(self, infoText):
619 """ 643 """
620 Public method to set some info text for private chat mode. 644 Public method to set some info text for private chat mode.
621 645
622 @param infoText info text to be shown (string) 646 @param infoText info text to be shown (string)
623 """ 647 """
624 if self.__private: 648 if self.__private:
625 self.topicLabel.setText(infoText) 649 self.topicLabel.setText(infoText)
626 650
627 def handleMessage(self, line): 651 def handleMessage(self, line):
628 """ 652 """
629 Public method to handle the message sent by the server. 653 Public method to handle the message sent by the server.
630 654
631 @param line server message (string) 655 @param line server message (string)
632 @return flag indicating, if the message was handled (boolean) 656 @return flag indicating, if the message was handled (boolean)
633 """ 657 """
634 for patternRe, patternFunc in self.__patterns: 658 for patternRe, patternFunc in self.__patterns:
635 match = patternRe.match(line) 659 match = patternRe.match(line)
636 if match is not None and patternFunc(match): 660 if match is not None and patternFunc(match):
637 return True 661 return True
638 662
639 return False 663 return False
640 664
641 def __message(self, match): 665 def __message(self, match):
642 """ 666 """
643 Private method to handle messages to the channel. 667 Private method to handle messages to the channel.
644 668
645 @param match match object that matched the pattern 669 @param match match object that matched the pattern
646 @return flag indicating whether the message was handled (boolean) 670 @return flag indicating whether the message was handled (boolean)
647 """ 671 """
648 # group(1) sender user name 672 # group(1) sender user name
649 # group(2) sender user@host 673 # group(2) sender user@host
653 senderName = match.group(1) 677 senderName = match.group(1)
654 itm = self.__findUser(senderName) 678 itm = self.__findUser(senderName)
655 if itm and itm.isIgnored(): 679 if itm and itm.isIgnored():
656 # user should be ignored 680 # user should be ignored
657 return True 681 return True
658 682
659 if match.group(4).startswith("\x01"): 683 if match.group(4).startswith("\x01"):
660 return self.__handleCtcp(match) 684 return self.__handleCtcp(match)
661 685
662 self.addMessage(senderName, match.group(4)) 686 self.addMessage(senderName, match.group(4))
663 if self.__private and not self.topicLabel.text(): 687 if self.__private and not self.topicLabel.text():
664 self.setPrivateInfo( 688 self.setPrivateInfo("{0} - {1}".format(match.group(1), match.group(2)))
665 "{0} - {1}".format(match.group(1), match.group(2))) 689 return True
666 return True 690
667 691 return False
668 return False 692
669
670 def addMessage(self, sender, msg): 693 def addMessage(self, sender, msg):
671 """ 694 """
672 Public method to add a message from external. 695 Public method to add a message from external.
673 696
674 @param sender nick name of the sender (string) 697 @param sender nick name of the sender (string)
675 @param msg message received from sender (string) 698 @param msg message received from sender (string)
676 """ 699 """
677 self.__appendMessage( 700 self.__appendMessage(
678 '<font color="{0}">{2} <b>&lt;</b><font color="{1}">{3}</font>' 701 '<font color="{0}">{2} <b>&lt;</b><font color="{1}">{3}</font>'
679 '<b>&gt;</b> {4}</font>'.format( 702 "<b>&gt;</b> {4}</font>".format(
680 Preferences.getIrc("ChannelMessageColour"), 703 Preferences.getIrc("ChannelMessageColour"),
681 Preferences.getIrc("NickColour"), 704 Preferences.getIrc("NickColour"),
682 ircTimestamp(), sender, ircFilter(msg))) 705 ircTimestamp(),
706 sender,
707 ircFilter(msg),
708 )
709 )
683 if Preferences.getIrc("ShowNotifications"): 710 if Preferences.getIrc("ShowNotifications"):
684 if Preferences.getIrc("NotifyMessage"): 711 if Preferences.getIrc("NotifyMessage"):
685 self.__ui.showNotification( 712 self.__ui.showNotification(
686 UI.PixmapCache.getPixmap("irc48"), 713 UI.PixmapCache.getPixmap("irc48"), self.tr("Channel Message"), msg
687 self.tr("Channel Message"), msg) 714 )
688 elif ( 715 elif (
689 Preferences.getIrc("NotifyNick") and 716 Preferences.getIrc("NotifyNick")
690 self.__userName.lower() in msg.lower() 717 and self.__userName.lower() in msg.lower()
691 ): 718 ):
692 self.__ui.showNotification( 719 self.__ui.showNotification(
693 UI.PixmapCache.getPixmap("irc48"), 720 UI.PixmapCache.getPixmap("irc48"), self.tr("Nick mentioned"), msg
694 self.tr("Nick mentioned"), msg) 721 )
695 722
696 def addUsers(self, users): 723 def addUsers(self, users):
697 """ 724 """
698 Public method to add users to the channel. 725 Public method to add users to the channel.
699 726
700 @param users list of user names to add (list of string) 727 @param users list of user names to add (list of string)
701 """ 728 """
702 for user in users: 729 for user in users:
703 itm = self.__findUser(user) 730 itm = self.__findUser(user)
704 if itm is None: 731 if itm is None:
705 IrcUserItem(user, self.usersList) 732 IrcUserItem(user, self.usersList)
706 733
707 def __userJoin(self, match): 734 def __userJoin(self, match):
708 """ 735 """
709 Private method to handle a user joining the channel. 736 Private method to handle a user joining the channel.
710 737
711 @param match match object that matched the pattern 738 @param match match object that matched the pattern
712 @return flag indicating whether the message was handled (boolean) 739 @return flag indicating whether the message was handled (boolean)
713 """ 740 """
714 if match.group(3).lower() == self.__name.lower(): 741 if match.group(3).lower() == self.__name.lower():
715 if self.__userName != match.group(1): 742 if self.__userName != match.group(1):
716 IrcUserItem(match.group(1), self.usersList) 743 IrcUserItem(match.group(1), self.usersList)
717 msg = self.tr( 744 msg = self.tr("{0} has joined the channel {1} ({2}).").format(
718 "{0} has joined the channel {1} ({2}).").format( 745 match.group(1), self.__name, match.group(2)
719 match.group(1), self.__name, match.group(2)) 746 )
720 self.__addManagementMessage( 747 self.__addManagementMessage(IrcChannelWidget.JoinIndicator, msg)
721 IrcChannelWidget.JoinIndicator, msg)
722 else: 748 else:
723 msg = self.tr( 749 msg = self.tr("You have joined the channel {0} ({1}).").format(
724 "You have joined the channel {0} ({1}).").format( 750 self.__name, match.group(2)
725 self.__name, match.group(2)) 751 )
726 self.__addManagementMessage( 752 self.__addManagementMessage(IrcChannelWidget.JoinIndicator, msg)
727 IrcChannelWidget.JoinIndicator, msg) 753 if Preferences.getIrc("ShowNotifications") and Preferences.getIrc(
728 if ( 754 "NotifyJoinPart"
729 Preferences.getIrc("ShowNotifications") and
730 Preferences.getIrc("NotifyJoinPart")
731 ): 755 ):
732 self.__ui.showNotification( 756 self.__ui.showNotification(
733 UI.PixmapCache.getPixmap("irc48"), 757 UI.PixmapCache.getPixmap("irc48"), self.tr("Join Channel"), msg
734 self.tr("Join Channel"), msg) 758 )
735 return True 759 return True
736 760
737 return False 761 return False
738 762
739 def __userPart(self, match): 763 def __userPart(self, match):
740 """ 764 """
741 Private method to handle a user leaving the channel. 765 Private method to handle a user leaving the channel.
742 766
743 @param match match object that matched the pattern 767 @param match match object that matched the pattern
744 @return flag indicating whether the message was handled (boolean) 768 @return flag indicating whether the message was handled (boolean)
745 """ 769 """
746 if match.group(2).lower() == self.__name.lower(): 770 if match.group(2).lower() == self.__name.lower():
747 itm = self.__findUser(match.group(1)) 771 itm = self.__findUser(match.group(1))
748 self.usersList.takeItem(self.usersList.row(itm)) 772 self.usersList.takeItem(self.usersList.row(itm))
749 del itm 773 del itm
750 if match.lastindex == 2: 774 if match.lastindex == 2:
751 msg = self.tr("{0} has left {1}.").format( 775 msg = self.tr("{0} has left {1}.").format(match.group(1), self.__name)
752 match.group(1), self.__name)
753 nmsg = msg 776 nmsg = msg
754 self.__addManagementMessage( 777 self.__addManagementMessage(IrcChannelWidget.LeaveIndicator, msg)
755 IrcChannelWidget.LeaveIndicator, msg)
756 else: 778 else:
757 msg = self.tr("{0} has left {1}: {2}.").format( 779 msg = self.tr("{0} has left {1}: {2}.").format(
758 match.group(1), self.__name, ircFilter(match.group(3))) 780 match.group(1), self.__name, ircFilter(match.group(3))
781 )
759 nmsg = self.tr("{0} has left {1}: {2}.").format( 782 nmsg = self.tr("{0} has left {1}: {2}.").format(
760 match.group(1), self.__name, match.group(3)) 783 match.group(1), self.__name, match.group(3)
761 self.__addManagementMessage( 784 )
762 IrcChannelWidget.LeaveIndicator, msg) 785 self.__addManagementMessage(IrcChannelWidget.LeaveIndicator, msg)
763 if ( 786 if Preferences.getIrc("ShowNotifications") and Preferences.getIrc(
764 Preferences.getIrc("ShowNotifications") and 787 "NotifyJoinPart"
765 Preferences.getIrc("NotifyJoinPart")
766 ): 788 ):
767 self.__ui.showNotification( 789 self.__ui.showNotification(
768 UI.PixmapCache.getPixmap("irc48"), 790 UI.PixmapCache.getPixmap("irc48"), self.tr("Leave Channel"), nmsg
769 self.tr("Leave Channel"), nmsg) 791 )
770 return True 792 return True
771 793
772 return False 794 return False
773 795
774 def __userQuit(self, match): 796 def __userQuit(self, match):
775 """ 797 """
776 Private method to handle a user logging off the server. 798 Private method to handle a user logging off the server.
777 799
778 @param match match object that matched the pattern 800 @param match match object that matched the pattern
779 @return flag indicating whether the message was handled (boolean) 801 @return flag indicating whether the message was handled (boolean)
780 """ 802 """
781 itm = self.__findUser(match.group(1)) 803 itm = self.__findUser(match.group(1))
782 if itm: 804 if itm:
783 self.usersList.takeItem(self.usersList.row(itm)) 805 self.usersList.takeItem(self.usersList.row(itm))
784 del itm 806 del itm
785 if match.lastindex == 1: 807 if match.lastindex == 1:
786 msg = self.tr("{0} has quit {1}.").format( 808 msg = self.tr("{0} has quit {1}.").format(match.group(1), self.__name)
787 match.group(1), self.__name) 809 self.__addManagementMessage(IrcChannelWidget.MessageIndicator, msg)
788 self.__addManagementMessage(
789 IrcChannelWidget.MessageIndicator, msg)
790 else: 810 else:
791 msg = self.tr("{0} has quit {1}: {2}.").format( 811 msg = self.tr("{0} has quit {1}: {2}.").format(
792 match.group(1), self.__name, ircFilter(match.group(2))) 812 match.group(1), self.__name, ircFilter(match.group(2))
793 self.__addManagementMessage( 813 )
794 IrcChannelWidget.MessageIndicator, msg) 814 self.__addManagementMessage(IrcChannelWidget.MessageIndicator, msg)
795 if ( 815 if Preferences.getIrc("ShowNotifications") and Preferences.getIrc(
796 Preferences.getIrc("ShowNotifications") and 816 "NotifyJoinPart"
797 Preferences.getIrc("NotifyJoinPart")
798 ): 817 ):
799 self.__ui.showNotification( 818 self.__ui.showNotification(
800 UI.PixmapCache.getPixmap("irc48"), 819 UI.PixmapCache.getPixmap("irc48"), self.tr("Quit"), msg
801 self.tr("Quit"), msg) 820 )
802 821
803 # always return False for other channels and server to process 822 # always return False for other channels and server to process
804 return False 823 return False
805 824
806 def __userNickChange(self, match): 825 def __userNickChange(self, match):
807 """ 826 """
808 Private method to handle a nickname change of a user. 827 Private method to handle a nickname change of a user.
809 828
810 @param match match object that matched the pattern 829 @param match match object that matched the pattern
811 @return flag indicating whether the message was handled (boolean) 830 @return flag indicating whether the message was handled (boolean)
812 """ 831 """
813 itm = self.__findUser(match.group(1)) 832 itm = self.__findUser(match.group(1))
814 if itm: 833 if itm:
815 itm.setName(match.group(2)) 834 itm.setName(match.group(2))
816 if match.group(1) == self.__userName: 835 if match.group(1) == self.__userName:
817 self.__addManagementMessage( 836 self.__addManagementMessage(
818 IrcChannelWidget.MessageIndicator, 837 IrcChannelWidget.MessageIndicator,
819 self.tr("You are now known as {0}.").format( 838 self.tr("You are now known as {0}.").format(match.group(2)),
820 match.group(2))) 839 )
821 self.__userName = match.group(2) 840 self.__userName = match.group(2)
822 else: 841 else:
823 self.__addManagementMessage( 842 self.__addManagementMessage(
824 IrcChannelWidget.MessageIndicator, 843 IrcChannelWidget.MessageIndicator,
825 self.tr("User {0} is now known as {1}.").format( 844 self.tr("User {0} is now known as {1}.").format(
826 match.group(1), match.group(2))) 845 match.group(1), match.group(2)
827 846 ),
847 )
848
828 # always return False for other channels and server to process 849 # always return False for other channels and server to process
829 return False 850 return False
830 851
831 def __userList(self, match): 852 def __userList(self, match):
832 """ 853 """
833 Private method to handle the receipt of a list of users of the channel. 854 Private method to handle the receipt of a list of users of the channel.
834 855
835 @param match match object that matched the pattern 856 @param match match object that matched the pattern
836 @return flag indicating whether the message was handled (boolean) 857 @return flag indicating whether the message was handled (boolean)
837 """ 858 """
838 if match.group(1).lower() == self.__name.lower(): 859 if match.group(1).lower() == self.__name.lower():
839 users = match.group(2).split() 860 users = match.group(2).split()
842 itm = self.__findUser(userName) 863 itm = self.__findUser(userName)
843 if itm is None: 864 if itm is None:
844 itm = IrcUserItem(userName, self.usersList) 865 itm = IrcUserItem(userName, self.usersList)
845 for privilege in userPrivileges: 866 for privilege in userPrivileges:
846 itm.changePrivilege(privilege) 867 itm.changePrivilege(privilege)
847 868
848 self.__setEditTopicButton() 869 self.__setEditTopicButton()
849 return True 870 return True
850 871
851 return False 872 return False
852 873
853 def __userAway(self, match): 874 def __userAway(self, match):
854 """ 875 """
855 Private method to handle a topic change of the channel. 876 Private method to handle a topic change of the channel.
856 877
857 @param match match object that matched the pattern 878 @param match match object that matched the pattern
858 @return flag indicating whether the message was handled (boolean) 879 @return flag indicating whether the message was handled (boolean)
859 """ 880 """
860 if match.group(1).lower() == self.__name.lower(): 881 if match.group(1).lower() == self.__name.lower():
861 self.__addManagementMessage( 882 self.__addManagementMessage(
862 self.tr("Away"), 883 self.tr("Away"),
863 self.tr("{0} is away: {1}").format( 884 self.tr("{0} is away: {1}").format(match.group(2), match.group(3)),
864 match.group(2), match.group(3))) 885 )
865 return True 886 return True
866 887
867 return False 888 return False
868 889
869 def __setTopic(self, match): 890 def __setTopic(self, match):
870 """ 891 """
871 Private method to handle a topic change of the channel. 892 Private method to handle a topic change of the channel.
872 893
873 @param match match object that matched the pattern 894 @param match match object that matched the pattern
874 @return flag indicating whether the message was handled (boolean) 895 @return flag indicating whether the message was handled (boolean)
875 """ 896 """
876 if match.group(1).lower() == self.__name.lower(): 897 if match.group(1).lower() == self.__name.lower():
877 self.topicLabel.setText(match.group(2)) 898 self.topicLabel.setText(match.group(2))
878 self.__addManagementMessage( 899 self.__addManagementMessage(
879 IrcChannelWidget.MessageIndicator, 900 IrcChannelWidget.MessageIndicator,
880 ircFilter(self.tr('The channel topic is: "{0}".').format( 901 ircFilter(
881 match.group(2)))) 902 self.tr('The channel topic is: "{0}".').format(match.group(2))
882 return True 903 ),
883 904 )
884 return False 905 return True
885 906
907 return False
908
886 def __topicCreated(self, match): 909 def __topicCreated(self, match):
887 """ 910 """
888 Private method to handle a topic created message. 911 Private method to handle a topic created message.
889 912
890 @param match match object that matched the pattern 913 @param match match object that matched the pattern
891 @return flag indicating whether the message was handled (boolean) 914 @return flag indicating whether the message was handled (boolean)
892 """ 915 """
893 if match.group(1).lower() == self.__name.lower(): 916 if match.group(1).lower() == self.__name.lower():
894 self.__addManagementMessage( 917 self.__addManagementMessage(
895 IrcChannelWidget.MessageIndicator, 918 IrcChannelWidget.MessageIndicator,
896 self.tr("The topic was set by {0} on {1}.").format( 919 self.tr("The topic was set by {0} on {1}.").format(
897 match.group(2), 920 match.group(2),
898 QDateTime.fromSecsSinceEpoch(int(match.group(3))) 921 QDateTime.fromSecsSinceEpoch(int(match.group(3))).toString(
899 .toString("yyyy-MM-dd hh:mm"))) 922 "yyyy-MM-dd hh:mm"
900 return True 923 ),
901 924 ),
902 return False 925 )
903 926 return True
927
928 return False
929
904 def __channelUrl(self, match): 930 def __channelUrl(self, match):
905 """ 931 """
906 Private method to handle a channel URL message. 932 Private method to handle a channel URL message.
907 933
908 @param match match object that matched the pattern 934 @param match match object that matched the pattern
909 @return flag indicating whether the message was handled (boolean) 935 @return flag indicating whether the message was handled (boolean)
910 """ 936 """
911 if match.group(1).lower() == self.__name.lower(): 937 if match.group(1).lower() == self.__name.lower():
912 self.__addManagementMessage( 938 self.__addManagementMessage(
913 IrcChannelWidget.MessageIndicator, 939 IrcChannelWidget.MessageIndicator,
914 ircFilter(self.tr("Channel URL: {0}").format( 940 ircFilter(self.tr("Channel URL: {0}").format(match.group(2))),
915 match.group(2)))) 941 )
916 return True 942 return True
917 943
918 return False 944 return False
919 945
920 def __channelModes(self, match): 946 def __channelModes(self, match):
921 """ 947 """
922 Private method to handle a message reporting the channel modes. 948 Private method to handle a message reporting the channel modes.
923 949
924 @param match match object that matched the pattern 950 @param match match object that matched the pattern
925 @return flag indicating whether the message was handled (boolean) 951 @return flag indicating whether the message was handled (boolean)
926 """ 952 """
927 if match.group(1).lower() == self.__name.lower(): 953 if match.group(1).lower() == self.__name.lower():
928 modesDict = getChannelModesDict() 954 modesDict = getChannelModesDict()
932 for modeChar in modeString: 958 for modeChar in modeString:
933 if modeChar == "+": 959 if modeChar == "+":
934 continue 960 continue
935 elif modeChar == "k": 961 elif modeChar == "k":
936 parameter = modesParameters.pop(0) 962 parameter = modesParameters.pop(0)
937 modes.append(self.tr( 963 modes.append(self.tr("password protected ({0})").format(parameter))
938 "password protected ({0})").format(parameter))
939 elif modeChar == "l": 964 elif modeChar == "l":
940 parameter = modesParameters.pop(0) 965 parameter = modesParameters.pop(0)
941 modes.append(self.tr( 966 modes.append(self.tr("limited to %n user(s)", "", int(parameter)))
942 "limited to %n user(s)", "", int(parameter)))
943 elif modeChar in modesDict: 967 elif modeChar in modesDict:
944 modes.append(modesDict[modeChar]) 968 modes.append(modesDict[modeChar])
945 else: 969 else:
946 modes.append(modeChar) 970 modes.append(modeChar)
947 971
948 self.__addManagementMessage( 972 self.__addManagementMessage(
949 IrcChannelWidget.MessageIndicator, 973 IrcChannelWidget.MessageIndicator,
950 self.tr("Channel modes: {0}.").format(", ".join(modes))) 974 self.tr("Channel modes: {0}.").format(", ".join(modes)),
951 975 )
952 return True 976
953 977 return True
954 return False 978
955 979 return False
980
956 def __channelCreated(self, match): 981 def __channelCreated(self, match):
957 """ 982 """
958 Private method to handle a channel created message. 983 Private method to handle a channel created message.
959 984
960 @param match match object that matched the pattern 985 @param match match object that matched the pattern
961 @return flag indicating whether the message was handled (boolean) 986 @return flag indicating whether the message was handled (boolean)
962 """ 987 """
963 if match.group(1).lower() == self.__name.lower(): 988 if match.group(1).lower() == self.__name.lower():
964 self.__addManagementMessage( 989 self.__addManagementMessage(
965 IrcChannelWidget.MessageIndicator, 990 IrcChannelWidget.MessageIndicator,
966 self.tr("This channel was created on {0}.").format( 991 self.tr("This channel was created on {0}.").format(
967 QDateTime.fromSecsSinceEpoch(int(match.group(2))) 992 QDateTime.fromSecsSinceEpoch(int(match.group(2))).toString(
968 .toString("yyyy-MM-dd hh:mm"))) 993 "yyyy-MM-dd hh:mm"
969 return True 994 )
970 995 ),
971 return False 996 )
972 997 return True
998
999 return False
1000
973 def __updateChannelModes(self, match): 1001 def __updateChannelModes(self, match):
974 """ 1002 """
975 Private method to handle a message reporting the channel modes. 1003 Private method to handle a message reporting the channel modes.
976 1004
977 @param match match object that matched the pattern 1005 @param match match object that matched the pattern
978 @return flag indicating whether the message was handled (boolean) 1006 @return flag indicating whether the message was handled (boolean)
979 """ 1007 """
980 # group(1) user or server 1008 # group(1) user or server
981 # group(2) channel 1009 # group(2) channel
998 message = self.tr( 1026 message = self.tr(
999 "{0} sets the channel mode to 'anonymous'." 1027 "{0} sets the channel mode to 'anonymous'."
1000 ).format(nick) 1028 ).format(nick)
1001 else: 1029 else:
1002 message = self.tr( 1030 message = self.tr(
1003 "{0} removes the 'anonymous' mode from the" 1031 "{0} removes the 'anonymous' mode from the" " channel."
1004 " channel.").format(nick) 1032 ).format(nick)
1005 elif mode == "b": 1033 elif mode == "b":
1006 if isPlus: 1034 if isPlus:
1007 message = self.tr( 1035 message = self.tr("{0} sets a ban on {1}.").format(
1008 "{0} sets a ban on {1}.").format( 1036 nick, modesParameters.pop(0)
1009 nick, modesParameters.pop(0)) 1037 )
1010 else: 1038 else:
1011 message = self.tr( 1039 message = self.tr("{0} removes the ban on {1}.").format(
1012 "{0} removes the ban on {1}.").format( 1040 nick, modesParameters.pop(0)
1013 nick, modesParameters.pop(0)) 1041 )
1014 elif mode == "c": 1042 elif mode == "c":
1015 if isPlus: 1043 if isPlus:
1016 message = self.tr( 1044 message = self.tr(
1017 "{0} sets the channel mode to 'no colors" 1045 "{0} sets the channel mode to 'no colors" " allowed'."
1018 " allowed'.").format(nick) 1046 ).format(nick)
1019 else: 1047 else:
1020 message = self.tr( 1048 message = self.tr(
1021 "{0} sets the channel mode to 'allow color" 1049 "{0} sets the channel mode to 'allow color" " codes'."
1022 " codes'.").format(nick) 1050 ).format(nick)
1023 elif mode == "e": 1051 elif mode == "e":
1024 if isPlus: 1052 if isPlus:
1025 message = self.tr( 1053 message = self.tr("{0} sets a ban exception on {1}.").format(
1026 "{0} sets a ban exception on {1}.").format( 1054 nick, modesParameters.pop(0)
1027 nick, modesParameters.pop(0)) 1055 )
1028 else: 1056 else:
1029 message = self.tr( 1057 message = self.tr(
1030 "{0} removes the ban exception on {1}.").format( 1058 "{0} removes the ban exception on {1}."
1031 nick, modesParameters.pop(0)) 1059 ).format(nick, modesParameters.pop(0))
1032 elif mode == "i": 1060 elif mode == "i":
1033 if isPlus: 1061 if isPlus:
1034 message = self.tr( 1062 message = self.tr(
1035 "{0} sets the channel mode to 'invite only'." 1063 "{0} sets the channel mode to 'invite only'."
1036 ).format(nick) 1064 ).format(nick)
1037 else: 1065 else:
1038 message = self.tr( 1066 message = self.tr(
1039 "{0} removes the 'invite only' mode from the" 1067 "{0} removes the 'invite only' mode from the" " channel."
1040 " channel.").format(nick) 1068 ).format(nick)
1041 elif mode == "k": 1069 elif mode == "k":
1042 if isPlus: 1070 if isPlus:
1043 message = self.tr( 1071 message = self.tr("{0} sets the channel key to '{1}'.").format(
1044 "{0} sets the channel key to '{1}'.").format( 1072 nick, modesParameters.pop(0)
1045 nick, modesParameters.pop(0)) 1073 )
1046 else: 1074 else:
1047 message = self.tr( 1075 message = self.tr("{0} removes the channel key.").format(nick)
1048 "{0} removes the channel key.").format(nick)
1049 elif mode == "l": 1076 elif mode == "l":
1050 if isPlus: 1077 if isPlus:
1051 message = self.tr( 1078 message = self.tr(
1052 "{0} sets the channel limit to %n nick(s).", "", 1079 "{0} sets the channel limit to %n nick(s).",
1053 int(modesParameters.pop(0))).format(nick) 1080 "",
1081 int(modesParameters.pop(0)),
1082 ).format(nick)
1054 else: 1083 else:
1055 message = self.tr( 1084 message = self.tr("{0} removes the channel limit.").format(nick)
1056 "{0} removes the channel limit.").format(nick)
1057 elif mode == "m": 1085 elif mode == "m":
1058 if isPlus: 1086 if isPlus:
1059 message = self.tr( 1087 message = self.tr(
1060 "{0} sets the channel mode to 'moderated'." 1088 "{0} sets the channel mode to 'moderated'."
1061 ).format(nick) 1089 ).format(nick)
1065 ).format(nick) 1093 ).format(nick)
1066 elif mode == "n": 1094 elif mode == "n":
1067 if isPlus: 1095 if isPlus:
1068 message = self.tr( 1096 message = self.tr(
1069 "{0} sets the channel mode to 'no messages from" 1097 "{0} sets the channel mode to 'no messages from"
1070 " outside'.").format(nick) 1098 " outside'."
1099 ).format(nick)
1071 else: 1100 else:
1072 message = self.tr( 1101 message = self.tr(
1073 "{0} sets the channel mode to 'allow messages" 1102 "{0} sets the channel mode to 'allow messages"
1074 " from outside'.").format(nick) 1103 " from outside'."
1104 ).format(nick)
1075 elif mode == "p": 1105 elif mode == "p":
1076 if isPlus: 1106 if isPlus:
1077 message = self.tr( 1107 message = self.tr(
1078 "{0} sets the channel mode to 'private'." 1108 "{0} sets the channel mode to 'private'."
1079 ).format(nick) 1109 ).format(nick)
1101 message = self.tr( 1131 message = self.tr(
1102 "{0} sets the channel mode to 'visible'." 1132 "{0} sets the channel mode to 'visible'."
1103 ).format(nick) 1133 ).format(nick)
1104 elif mode == "t": 1134 elif mode == "t":
1105 if isPlus: 1135 if isPlus:
1106 message = self.tr( 1136 message = self.tr("{0} switches on 'topic protection'.").format(
1107 "{0} switches on 'topic protection'.").format(nick) 1137 nick
1138 )
1108 else: 1139 else:
1109 message = self.tr( 1140 message = self.tr(
1110 "{0} switches off 'topic protection'." 1141 "{0} switches off 'topic protection'."
1111 ).format(nick) 1142 ).format(nick)
1112 elif mode == "I": 1143 elif mode == "I":
1113 if isPlus: 1144 if isPlus:
1114 message = self.tr( 1145 message = self.tr("{0} sets invitation mask {1}.").format(
1115 "{0} sets invitation mask {1}.").format( 1146 nick, modesParameters.pop(0)
1116 nick, modesParameters.pop(0)) 1147 )
1117 else: 1148 else:
1118 message = self.tr( 1149 message = self.tr(
1119 "{0} removes the invitation mask {1}.").format( 1150 "{0} removes the invitation mask {1}."
1120 nick, modesParameters.pop(0)) 1151 ).format(nick, modesParameters.pop(0))
1121 1152
1122 self.__addManagementMessage(self.tr("Mode"), message) 1153 self.__addManagementMessage(self.tr("Mode"), message)
1123 1154
1124 return True 1155 return True
1125 1156
1126 return False 1157 return False
1127 1158
1128 def __setUserPrivilege(self, match): 1159 def __setUserPrivilege(self, match):
1129 """ 1160 """
1130 Private method to handle a change of user privileges for the channel. 1161 Private method to handle a change of user privileges for the channel.
1131 1162
1132 @param match match object that matched the pattern 1163 @param match match object that matched the pattern
1133 @return flag indicating whether the message was handled (boolean) 1164 @return flag indicating whether the message was handled (boolean)
1134 """ 1165 """
1135 if match.group(2).lower() == self.__name.lower(): 1166 if match.group(2).lower() == self.__name.lower():
1136 itm = self.__findUser(match.group(4)) 1167 itm = self.__findUser(match.group(4))
1138 itm.changePrivilege(match.group(3)) 1169 itm.changePrivilege(match.group(3))
1139 self.__setEditTopicButton() 1170 self.__setEditTopicButton()
1140 self.__addManagementMessage( 1171 self.__addManagementMessage(
1141 IrcChannelWidget.MessageIndicator, 1172 IrcChannelWidget.MessageIndicator,
1142 self.tr("{0} sets mode for {1}: {2}.").format( 1173 self.tr("{0} sets mode for {1}: {2}.").format(
1143 match.group(1), match.group(4), match.group(3))) 1174 match.group(1), match.group(4), match.group(3)
1144 return True 1175 ),
1145 1176 )
1146 return False 1177 return True
1147 1178
1179 return False
1180
1148 def __ignore(self, match): 1181 def __ignore(self, match):
1149 """ 1182 """
1150 Private method to handle a channel message we are not interested in. 1183 Private method to handle a channel message we are not interested in.
1151 1184
1152 @param match match object that matched the pattern 1185 @param match match object that matched the pattern
1153 @return flag indicating whether the message was handled (boolean) 1186 @return flag indicating whether the message was handled (boolean)
1154 """ 1187 """
1155 if match.group(1).lower() == self.__name.lower(): 1188 if match.group(1).lower() == self.__name.lower():
1156 return True 1189 return True
1157 1190
1158 return False 1191 return False
1159 1192
1160 def __help(self, match): 1193 def __help(self, match):
1161 """ 1194 """
1162 Private method to handle a help message. 1195 Private method to handle a help message.
1163 1196
1164 @param match match object that matched the pattern 1197 @param match match object that matched the pattern
1165 @return flag indicating whether the message was handled (boolean) 1198 @return flag indicating whether the message was handled (boolean)
1166 """ 1199 """
1167 self.__addManagementMessage( 1200 self.__addManagementMessage(
1168 self.tr("Help"), 1201 self.tr("Help"), "{0} {1}".format(match.group(1), ircFilter(match.group(2)))
1169 "{0} {1}".format(match.group(1), ircFilter(match.group(2)))) 1202 )
1170 return True 1203 return True
1171 1204
1172 def __handleCtcp(self, match): 1205 def __handleCtcp(self, match):
1173 """ 1206 """
1174 Private method to handle a CTCP channel command. 1207 Private method to handle a CTCP channel command.
1175 1208
1176 @param match reference to the match object 1209 @param match reference to the match object
1177 @return flag indicating, if the message was handled (boolean) 1210 @return flag indicating, if the message was handled (boolean)
1178 """ 1211 """
1179 # group(1) sender user name 1212 # group(1) sender user name
1180 # group(2) sender user@host 1213 # group(2) sender user@host
1190 if ctcpRequest == "version": 1223 if ctcpRequest == "version":
1191 msg = "Eric IRC client {0}, {1}".format(Version, Copyright) 1224 msg = "Eric IRC client {0}, {1}".format(Version, Copyright)
1192 self.__addManagementMessage( 1225 self.__addManagementMessage(
1193 self.tr("CTCP"), 1226 self.tr("CTCP"),
1194 self.tr("Received Version request from {0}.").format( 1227 self.tr("Received Version request from {0}.").format(
1195 match.group(1))) 1228 match.group(1)
1229 ),
1230 )
1196 self.sendCtcpReply.emit(match.group(1), "VERSION " + msg) 1231 self.sendCtcpReply.emit(match.group(1), "VERSION " + msg)
1197 elif ctcpRequest == "ping": 1232 elif ctcpRequest == "ping":
1198 self.__addManagementMessage( 1233 self.__addManagementMessage(
1199 self.tr("CTCP"), 1234 self.tr("CTCP"),
1200 self.tr( 1235 self.tr(
1201 "Received CTCP-PING request from {0}," 1236 "Received CTCP-PING request from {0}," " sending answer."
1202 " sending answer.").format(match.group(1))) 1237 ).format(match.group(1)),
1203 self.sendCtcpReply.emit( 1238 )
1204 match.group(1), "PING {0}".format(ctcpArg)) 1239 self.sendCtcpReply.emit(match.group(1), "PING {0}".format(ctcpArg))
1205 elif ctcpRequest == "clientinfo": 1240 elif ctcpRequest == "clientinfo":
1206 self.__addManagementMessage( 1241 self.__addManagementMessage(
1207 self.tr("CTCP"), 1242 self.tr("CTCP"),
1208 self.tr( 1243 self.tr(
1209 "Received CTCP-CLIENTINFO request from {0}," 1244 "Received CTCP-CLIENTINFO request from {0}," " sending answer."
1210 " sending answer.").format(match.group(1))) 1245 ).format(match.group(1)),
1246 )
1211 self.sendCtcpReply.emit( 1247 self.sendCtcpReply.emit(
1212 match.group(1), "CLIENTINFO CLIENTINFO PING VERSION") 1248 match.group(1), "CLIENTINFO CLIENTINFO PING VERSION"
1249 )
1213 else: 1250 else:
1214 self.__addManagementMessage( 1251 self.__addManagementMessage(
1215 self.tr("CTCP"), 1252 self.tr("CTCP"),
1216 self.tr("Received unknown CTCP-{0} request from {1}.") 1253 self.tr("Received unknown CTCP-{0} request from {1}.").format(
1217 .format(ctcpRequest, match.group(1))) 1254 ctcpRequest, match.group(1)
1218 return True 1255 ),
1219 1256 )
1220 return False 1257 return True
1221 1258
1259 return False
1260
1222 def setUserPrivilegePrefix(self, prefixes): 1261 def setUserPrivilegePrefix(self, prefixes):
1223 """ 1262 """
1224 Public method to set the user privilege to prefix mapping. 1263 Public method to set the user privilege to prefix mapping.
1225 1264
1226 @param prefixes dictionary with privilege as key and prefix as value 1265 @param prefixes dictionary with privilege as key and prefix as value
1227 """ 1266 """
1228 self.__prefixToPrivilege = {} 1267 self.__prefixToPrivilege = {}
1229 for privilege, prefix in prefixes.items(): 1268 for privilege, prefix in prefixes.items():
1230 if prefix: 1269 if prefix:
1231 self.__prefixToPrivilege[prefix] = privilege 1270 self.__prefixToPrivilege[prefix] = privilege
1232 1271
1233 def __findUser(self, name): 1272 def __findUser(self, name):
1234 """ 1273 """
1235 Private method to find the user in the list of users. 1274 Private method to find the user in the list of users.
1236 1275
1237 @param name user name to search for (string) 1276 @param name user name to search for (string)
1238 @return reference to the list entry (QListWidgetItem) 1277 @return reference to the list entry (QListWidgetItem)
1239 """ 1278 """
1240 for row in range(self.usersList.count()): 1279 for row in range(self.usersList.count()):
1241 itm = self.usersList.item(row) 1280 itm = self.usersList.item(row)
1242 if itm.name() == name: 1281 if itm.name() == name:
1243 return itm 1282 return itm
1244 1283
1245 return None 1284 return None
1246 1285
1247 def __extractPrivilege(self, name): 1286 def __extractPrivilege(self, name):
1248 """ 1287 """
1249 Private method to extract the user privileges out of the name. 1288 Private method to extract the user privileges out of the name.
1250 1289
1251 @param name user name and prefixes (string) 1290 @param name user name and prefixes (string)
1252 @return list of privileges and user name (list of string, string) 1291 @return list of privileges and user name (list of string, string)
1253 """ 1292 """
1254 privileges = [] 1293 privileges = []
1255 while name[0] in self.__prefixToPrivilege: 1294 while name[0] in self.__prefixToPrivilege:
1256 prefix = name[0] 1295 prefix = name[0]
1257 privileges.append(self.__prefixToPrivilege[prefix]) 1296 privileges.append(self.__prefixToPrivilege[prefix])
1258 name = name[1:] 1297 name = name[1:]
1259 if name[0] == ",": 1298 if name[0] == ",":
1260 name = name[1:] 1299 name = name[1:]
1261 1300
1262 return privileges, name 1301 return privileges, name
1263 1302
1264 def __addManagementMessage(self, indicator, message): 1303 def __addManagementMessage(self, indicator, message):
1265 """ 1304 """
1266 Private method to add a channel management message to the list. 1305 Private method to add a channel management message to the list.
1267 1306
1268 @param indicator indicator to be shown (string) 1307 @param indicator indicator to be shown (string)
1269 @param message message to be shown (string) 1308 @param message message to be shown (string)
1270 """ 1309 """
1271 if indicator == self.JoinIndicator: 1310 if indicator == self.JoinIndicator:
1272 color = Preferences.getIrc("JoinChannelColour") 1311 color = Preferences.getIrc("JoinChannelColour")
1274 color = Preferences.getIrc("LeaveChannelColour") 1313 color = Preferences.getIrc("LeaveChannelColour")
1275 else: 1314 else:
1276 color = Preferences.getIrc("ChannelInfoColour") 1315 color = Preferences.getIrc("ChannelInfoColour")
1277 self.__appendMessage( 1316 self.__appendMessage(
1278 '<font color="{0}">{1} <b>[</b>{2}<b>]</b> {3}</font>'.format( 1317 '<font color="{0}">{1} <b>[</b>{2}<b>]</b> {3}</font>'.format(
1279 color, ircTimestamp(), indicator, message)) 1318 color, ircTimestamp(), indicator, message
1280 1319 )
1320 )
1321
1281 def __appendMessage(self, message): 1322 def __appendMessage(self, message):
1282 """ 1323 """
1283 Private slot to append a message. 1324 Private slot to append a message.
1284 1325
1285 @param message message to be appended (string) 1326 @param message message to be appended (string)
1286 """ 1327 """
1287 if ( 1328 if (
1288 self.__hidden and 1329 self.__hidden
1289 self.__markerLine == "" and 1330 and self.__markerLine == ""
1290 Preferences.getIrc("MarkPositionWhenHidden") 1331 and Preferences.getIrc("MarkPositionWhenHidden")
1291 ): 1332 ):
1292 self.setMarkerLine() 1333 self.setMarkerLine()
1293 self.messages.append(message) 1334 self.messages.append(message)
1294 1335
1295 def setMarkerLine(self): 1336 def setMarkerLine(self):
1296 """ 1337 """
1297 Public method to draw a line to mark the current position. 1338 Public method to draw a line to mark the current position.
1298 """ 1339 """
1299 self.unsetMarkerLine() 1340 self.unsetMarkerLine()
1300 self.__markerLine = ( 1341 self.__markerLine = (
1301 '<span style=" color:{0}; background-color:{1};">{2}</span>' 1342 '<span style=" color:{0}; background-color:{1};">{2}</span>'.format(
1302 .format(Preferences.getIrc("MarkerLineForegroundColour"), 1343 Preferences.getIrc("MarkerLineForegroundColour"),
1303 Preferences.getIrc("MarkerLineBackgroundColour"), 1344 Preferences.getIrc("MarkerLineBackgroundColour"),
1304 self.tr('--- New From Here ---')) 1345 self.tr("--- New From Here ---"),
1346 )
1305 ) 1347 )
1306 self.messages.append(self.__markerLine) 1348 self.messages.append(self.__markerLine)
1307 1349
1308 def unsetMarkerLine(self): 1350 def unsetMarkerLine(self):
1309 """ 1351 """
1310 Public method to remove the marker line. 1352 Public method to remove the marker line.
1311 """ 1353 """
1312 if self.__markerLine: 1354 if self.__markerLine:
1318 else: 1360 else:
1319 txt = txt.replace(self.__markerLine, "") 1361 txt = txt.replace(self.__markerLine, "")
1320 self.messages.setHtml(txt) 1362 self.messages.setHtml(txt)
1321 self.__markerLine = "" 1363 self.__markerLine = ""
1322 self.messages.moveCursor(QTextCursor.MoveOperation.End) 1364 self.messages.moveCursor(QTextCursor.MoveOperation.End)
1323 1365
1324 def __clearMessages(self): 1366 def __clearMessages(self):
1325 """ 1367 """
1326 Private slot to clear the contents of the messages display. 1368 Private slot to clear the contents of the messages display.
1327 """ 1369 """
1328 self.messages.clear() 1370 self.messages.clear()
1329 1371
1330 def __copyMessages(self): 1372 def __copyMessages(self):
1331 """ 1373 """
1332 Private slot to copy the selection of the messages display to the 1374 Private slot to copy the selection of the messages display to the
1333 clipboard. 1375 clipboard.
1334 """ 1376 """
1335 self.messages.copy() 1377 self.messages.copy()
1336 1378
1337 def __copyAllMessages(self): 1379 def __copyAllMessages(self):
1338 """ 1380 """
1339 Private slot to copy the contents of the messages display to the 1381 Private slot to copy the contents of the messages display to the
1340 clipboard. 1382 clipboard.
1341 """ 1383 """
1342 txt = self.messages.toPlainText() 1384 txt = self.messages.toPlainText()
1343 if txt: 1385 if txt:
1344 cb = QApplication.clipboard() 1386 cb = QApplication.clipboard()
1345 cb.setText(txt) 1387 cb.setText(txt)
1346 1388
1347 def __cutAllMessages(self): 1389 def __cutAllMessages(self):
1348 """ 1390 """
1349 Private slot to cut the contents of the messages display to the 1391 Private slot to cut the contents of the messages display to the
1350 clipboard. 1392 clipboard.
1351 """ 1393 """
1352 txt = self.messages.toPlainText() 1394 txt = self.messages.toPlainText()
1353 if txt: 1395 if txt:
1354 cb = QApplication.clipboard() 1396 cb = QApplication.clipboard()
1355 cb.setText(txt) 1397 cb.setText(txt)
1356 self.messages.clear() 1398 self.messages.clear()
1357 1399
1358 def __saveMessages(self): 1400 def __saveMessages(self):
1359 """ 1401 """
1360 Private slot to save the contents of the messages display. 1402 Private slot to save the contents of the messages display.
1361 """ 1403 """
1362 hasText = not self.messages.document().isEmpty() 1404 hasText = not self.messages.document().isEmpty()
1367 htmlExtension = "html" 1409 htmlExtension = "html"
1368 fname, selectedFilter = EricFileDialog.getSaveFileNameAndFilter( 1410 fname, selectedFilter = EricFileDialog.getSaveFileNameAndFilter(
1369 self, 1411 self,
1370 self.tr("Save Messages"), 1412 self.tr("Save Messages"),
1371 "", 1413 "",
1372 self.tr( 1414 self.tr("HTML Files (*.{0});;Text Files (*.txt);;All Files (*)").format(
1373 "HTML Files (*.{0});;Text Files (*.txt);;All Files (*)") 1415 htmlExtension
1374 .format(htmlExtension), 1416 ),
1375 None, 1417 None,
1376 EricFileDialog.DontConfirmOverwrite) 1418 EricFileDialog.DontConfirmOverwrite,
1419 )
1377 if fname: 1420 if fname:
1378 fpath = pathlib.Path(fname) 1421 fpath = pathlib.Path(fname)
1379 if not fpath.suffix: 1422 if not fpath.suffix:
1380 ex = selectedFilter.split("(*")[1].split(")")[0] 1423 ex = selectedFilter.split("(*")[1].split(")")[0]
1381 if ex: 1424 if ex:
1382 fpath = fpath.with_suffix(ex) 1425 fpath = fpath.with_suffix(ex)
1383 if fpath.exists(): 1426 if fpath.exists():
1384 res = EricMessageBox.yesNo( 1427 res = EricMessageBox.yesNo(
1385 self, 1428 self,
1386 self.tr("Save Messages"), 1429 self.tr("Save Messages"),
1387 self.tr("<p>The file <b>{0}</b> already exists." 1430 self.tr(
1388 " Overwrite it?</p>").format(fpath), 1431 "<p>The file <b>{0}</b> already exists."
1389 icon=EricMessageBox.Warning) 1432 " Overwrite it?</p>"
1433 ).format(fpath),
1434 icon=EricMessageBox.Warning,
1435 )
1390 if not res: 1436 if not res:
1391 return 1437 return
1392 1438
1393 try: 1439 try:
1394 txt = ( 1440 txt = (
1395 self.messages.toHtml() 1441 self.messages.toHtml()
1396 if fpath.suffix.lower() in [".htm", ".html"] else 1442 if fpath.suffix.lower() in [".htm", ".html"]
1397 self.messages.toPlainText() 1443 else self.messages.toPlainText()
1398 ) 1444 )
1399 with fpath.open("w", encoding="utf-8") as f: 1445 with fpath.open("w", encoding="utf-8") as f:
1400 f.write(txt) 1446 f.write(txt)
1401 except OSError as err: 1447 except OSError as err:
1402 EricMessageBox.critical( 1448 EricMessageBox.critical(
1403 self, 1449 self,
1404 self.tr("Error saving Messages"), 1450 self.tr("Error saving Messages"),
1405 self.tr( 1451 self.tr(
1406 """<p>The messages contents could not be written""" 1452 """<p>The messages contents could not be written"""
1407 """ to <b>{0}</b></p><p>Reason: {1}</p>""") 1453 """ to <b>{0}</b></p><p>Reason: {1}</p>"""
1408 .format(fpath, str(err))) 1454 ).format(fpath, str(err)),
1409 1455 )
1456
1410 def __initMessagesMenu(self): 1457 def __initMessagesMenu(self):
1411 """ 1458 """
1412 Private slot to initialize the context menu of the messages pane. 1459 Private slot to initialize the context menu of the messages pane.
1413 """ 1460 """
1414 self.__messagesMenu = QMenu(self) 1461 self.__messagesMenu = QMenu(self)
1415 self.__copyMessagesAct = self.__messagesMenu.addAction( 1462 self.__copyMessagesAct = self.__messagesMenu.addAction(
1416 UI.PixmapCache.getIcon("editCopy"), 1463 UI.PixmapCache.getIcon("editCopy"), self.tr("Copy"), self.__copyMessages
1417 self.tr("Copy"), self.__copyMessages) 1464 )
1418 self.__messagesMenu.addSeparator() 1465 self.__messagesMenu.addSeparator()
1419 self.__cutAllMessagesAct = self.__messagesMenu.addAction( 1466 self.__cutAllMessagesAct = self.__messagesMenu.addAction(
1420 UI.PixmapCache.getIcon("editCut"), 1467 UI.PixmapCache.getIcon("editCut"), self.tr("Cut all"), self.__cutAllMessages
1421 self.tr("Cut all"), self.__cutAllMessages) 1468 )
1422 self.__copyAllMessagesAct = self.__messagesMenu.addAction( 1469 self.__copyAllMessagesAct = self.__messagesMenu.addAction(
1423 UI.PixmapCache.getIcon("editCopy"), 1470 UI.PixmapCache.getIcon("editCopy"),
1424 self.tr("Copy all"), self.__copyAllMessages) 1471 self.tr("Copy all"),
1472 self.__copyAllMessages,
1473 )
1425 self.__messagesMenu.addSeparator() 1474 self.__messagesMenu.addSeparator()
1426 self.__clearMessagesAct = self.__messagesMenu.addAction( 1475 self.__clearMessagesAct = self.__messagesMenu.addAction(
1427 UI.PixmapCache.getIcon("editDelete"), 1476 UI.PixmapCache.getIcon("editDelete"), self.tr("Clear"), self.__clearMessages
1428 self.tr("Clear"), self.__clearMessages) 1477 )
1429 self.__messagesMenu.addSeparator() 1478 self.__messagesMenu.addSeparator()
1430 self.__saveMessagesAct = self.__messagesMenu.addAction( 1479 self.__saveMessagesAct = self.__messagesMenu.addAction(
1431 UI.PixmapCache.getIcon("fileSave"), 1480 UI.PixmapCache.getIcon("fileSave"), self.tr("Save"), self.__saveMessages
1432 self.tr("Save"), self.__saveMessages) 1481 )
1433 self.__messagesMenu.addSeparator() 1482 self.__messagesMenu.addSeparator()
1434 self.__setMarkerMessagesAct = self.__messagesMenu.addAction( 1483 self.__setMarkerMessagesAct = self.__messagesMenu.addAction(
1435 self.tr("Mark Current Position"), self.setMarkerLine) 1484 self.tr("Mark Current Position"), self.setMarkerLine
1485 )
1436 self.__unsetMarkerMessagesAct = self.__messagesMenu.addAction( 1486 self.__unsetMarkerMessagesAct = self.__messagesMenu.addAction(
1437 self.tr("Remove Position Marker"), 1487 self.tr("Remove Position Marker"), self.unsetMarkerLine
1438 self.unsetMarkerLine) 1488 )
1439 1489
1440 self.on_messages_copyAvailable(False) 1490 self.on_messages_copyAvailable(False)
1441 1491
1442 @pyqtSlot(bool) 1492 @pyqtSlot(bool)
1443 def on_messages_copyAvailable(self, yes): 1493 def on_messages_copyAvailable(self, yes):
1444 """ 1494 """
1445 Private slot to react to text selection/deselection of the messages 1495 Private slot to react to text selection/deselection of the messages
1446 edit. 1496 edit.
1447 1497
1448 @param yes flag signaling the availability of selected text (boolean) 1498 @param yes flag signaling the availability of selected text (boolean)
1449 """ 1499 """
1450 self.__copyMessagesAct.setEnabled(yes) 1500 self.__copyMessagesAct.setEnabled(yes)
1451 1501
1452 @pyqtSlot(QPoint) 1502 @pyqtSlot(QPoint)
1453 def on_messages_customContextMenuRequested(self, pos): 1503 def on_messages_customContextMenuRequested(self, pos):
1454 """ 1504 """
1455 Private slot to show the context menu of the messages pane. 1505 Private slot to show the context menu of the messages pane.
1456 1506
1457 @param pos the position of the mouse pointer (QPoint) 1507 @param pos the position of the mouse pointer (QPoint)
1458 """ 1508 """
1459 enable = not self.messages.document().isEmpty() 1509 enable = not self.messages.document().isEmpty()
1460 self.__cutAllMessagesAct.setEnabled(enable) 1510 self.__cutAllMessagesAct.setEnabled(enable)
1461 self.__copyAllMessagesAct.setEnabled(enable) 1511 self.__copyAllMessagesAct.setEnabled(enable)
1462 self.__saveMessagesAct.setEnabled(enable) 1512 self.__saveMessagesAct.setEnabled(enable)
1463 self.__setMarkerMessagesAct.setEnabled(self.__markerLine == "") 1513 self.__setMarkerMessagesAct.setEnabled(self.__markerLine == "")
1464 self.__unsetMarkerMessagesAct.setEnabled(self.__markerLine != "") 1514 self.__unsetMarkerMessagesAct.setEnabled(self.__markerLine != "")
1465 self.__messagesMenu.popup(self.messages.mapToGlobal(pos)) 1515 self.__messagesMenu.popup(self.messages.mapToGlobal(pos))
1466 1516
1467 def __whoIs(self): 1517 def __whoIs(self):
1468 """ 1518 """
1469 Private slot to get information about the selected user. 1519 Private slot to get information about the selected user.
1470 """ 1520 """
1471 self.__whoIsNick = self.usersList.selectedItems()[0].text() 1521 self.__whoIsNick = self.usersList.selectedItems()[0].text()
1472 self.sendData.emit("WHOIS " + self.__whoIsNick) 1522 self.sendData.emit("WHOIS " + self.__whoIsNick)
1473 1523
1474 def __openPrivateChat(self): 1524 def __openPrivateChat(self):
1475 """ 1525 """
1476 Private slot to open a chat with the selected user. 1526 Private slot to open a chat with the selected user.
1477 """ 1527 """
1478 user = self.usersList.selectedItems()[0].text() 1528 user = self.usersList.selectedItems()[0].text()
1479 self.openPrivateChat.emit(user) 1529 self.openPrivateChat.emit(user)
1480 1530
1481 def __sendUserMessage(self): 1531 def __sendUserMessage(self):
1482 """ 1532 """
1483 Private slot to send a private message to a specific user. 1533 Private slot to send a private message to a specific user.
1484 """ 1534 """
1485 from EricWidgets import EricTextInputDialog 1535 from EricWidgets import EricTextInputDialog
1486 1536
1487 user = self.usersList.selectedItems()[0].text() 1537 user = self.usersList.selectedItems()[0].text()
1488 ok, message = EricTextInputDialog.getText( 1538 ok, message = EricTextInputDialog.getText(
1489 self, self.tr("Send Message"), 1539 self,
1540 self.tr("Send Message"),
1490 self.tr("Enter the message to be sent:"), 1541 self.tr("Enter the message to be sent:"),
1491 minimumWidth=400) 1542 minimumWidth=400,
1543 )
1492 if ok and message: 1544 if ok and message:
1493 self.__processUserMessage("/MSG {0} {1}".format(user, message)) 1545 self.__processUserMessage("/MSG {0} {1}".format(user, message))
1494 1546
1495 def __sendUserQuery(self): 1547 def __sendUserQuery(self):
1496 """ 1548 """
1497 Private slot to send a query message to a specific user. 1549 Private slot to send a query message to a specific user.
1498 """ 1550 """
1499 from EricWidgets import EricTextInputDialog 1551 from EricWidgets import EricTextInputDialog
1500 1552
1501 user = self.usersList.selectedItems()[0].text() 1553 user = self.usersList.selectedItems()[0].text()
1502 ok, message = EricTextInputDialog.getText( 1554 ok, message = EricTextInputDialog.getText(
1503 self, self.tr("Send Query"), 1555 self,
1556 self.tr("Send Query"),
1504 self.tr("Enter the message to be sent:"), 1557 self.tr("Enter the message to be sent:"),
1505 minimumWidth=400) 1558 minimumWidth=400,
1559 )
1506 if ok and message: 1560 if ok and message:
1507 self.__processUserMessage("/QUERY {0} {1}".format(user, message)) 1561 self.__processUserMessage("/QUERY {0} {1}".format(user, message))
1508 1562
1509 def __sendUserNotice(self): 1563 def __sendUserNotice(self):
1510 """ 1564 """
1511 Private slot to send a notice message to a specific user. 1565 Private slot to send a notice message to a specific user.
1512 """ 1566 """
1513 from EricWidgets import EricTextInputDialog 1567 from EricWidgets import EricTextInputDialog
1514 1568
1515 user = self.usersList.selectedItems()[0].text() 1569 user = self.usersList.selectedItems()[0].text()
1516 ok, message = EricTextInputDialog.getText( 1570 ok, message = EricTextInputDialog.getText(
1517 self, self.tr("Send Notice"), 1571 self,
1572 self.tr("Send Notice"),
1518 self.tr("Enter the message to be sent:"), 1573 self.tr("Enter the message to be sent:"),
1519 minimumWidth=400) 1574 minimumWidth=400,
1575 )
1520 if ok and message: 1576 if ok and message:
1521 self.__processUserMessage("/NOTICE {0} {1}".format(user, message)) 1577 self.__processUserMessage("/NOTICE {0} {1}".format(user, message))
1522 1578
1523 def __pingUser(self): 1579 def __pingUser(self):
1524 """ 1580 """
1525 Private slot to send a ping to a specific user. 1581 Private slot to send a ping to a specific user.
1526 """ 1582 """
1527 user = self.usersList.selectedItems()[0].text() 1583 user = self.usersList.selectedItems()[0].text()
1528 self.__processUserMessage("/PING {0}".format(user)) 1584 self.__processUserMessage("/PING {0}".format(user))
1529 1585
1530 def __ignoreUser(self): 1586 def __ignoreUser(self):
1531 """ 1587 """
1532 Private slot to ignore a specific user. 1588 Private slot to ignore a specific user.
1533 """ 1589 """
1534 user = self.usersList.selectedItems()[0].text() 1590 user = self.usersList.selectedItems()[0].text()
1535 self.__processUserMessage("/IGNORE {0}".format(user)) 1591 self.__processUserMessage("/IGNORE {0}".format(user))
1536 1592
1537 def __initUsersMenu(self): 1593 def __initUsersMenu(self):
1538 """ 1594 """
1539 Private slot to initialize the users list context menu. 1595 Private slot to initialize the users list context menu.
1540 """ 1596 """
1541 self.__usersMenu = QMenu(self) 1597 self.__usersMenu = QMenu(self)
1542 self.__whoIsAct = self.__usersMenu.addAction( 1598 self.__whoIsAct = self.__usersMenu.addAction(self.tr("Who Is"), self.__whoIs)
1543 self.tr("Who Is"), self.__whoIs)
1544 self.__usersMenu.addSeparator() 1599 self.__usersMenu.addSeparator()
1545 self.__privateChatAct = self.__usersMenu.addAction( 1600 self.__privateChatAct = self.__usersMenu.addAction(
1546 self.tr("Private Chat"), self.__openPrivateChat) 1601 self.tr("Private Chat"), self.__openPrivateChat
1602 )
1547 self.__usersMenu.addSeparator() 1603 self.__usersMenu.addSeparator()
1548 self.__sendUserMessageAct = self.__usersMenu.addAction( 1604 self.__sendUserMessageAct = self.__usersMenu.addAction(
1549 self.tr("Send Message"), self.__sendUserMessage) 1605 self.tr("Send Message"), self.__sendUserMessage
1606 )
1550 self.__sendUserQueryAct = self.__usersMenu.addAction( 1607 self.__sendUserQueryAct = self.__usersMenu.addAction(
1551 self.tr("Send Query"), self.__sendUserQuery) 1608 self.tr("Send Query"), self.__sendUserQuery
1609 )
1552 self.__sendUserNoticeAct = self.__usersMenu.addAction( 1610 self.__sendUserNoticeAct = self.__usersMenu.addAction(
1553 self.tr("Send Notice"), self.__sendUserNotice) 1611 self.tr("Send Notice"), self.__sendUserNotice
1612 )
1554 self.__usersMenu.addSeparator() 1613 self.__usersMenu.addSeparator()
1555 self.__pingUserAct = self.__usersMenu.addAction( 1614 self.__pingUserAct = self.__usersMenu.addAction(
1556 self.tr("Send Ping"), self.__pingUser) 1615 self.tr("Send Ping"), self.__pingUser
1616 )
1557 self.__ignoreUserAct = self.__usersMenu.addAction( 1617 self.__ignoreUserAct = self.__usersMenu.addAction(
1558 self.tr("Ignore User"), self.__ignoreUser) 1618 self.tr("Ignore User"), self.__ignoreUser
1619 )
1559 self.__usersMenu.addSeparator() 1620 self.__usersMenu.addSeparator()
1560 self.__usersListRefreshAct = self.__usersMenu.addAction( 1621 self.__usersListRefreshAct = self.__usersMenu.addAction(
1561 self.tr("Refresh"), self.__sendAutoWhoCommand) 1622 self.tr("Refresh"), self.__sendAutoWhoCommand
1562 1623 )
1624
1563 @pyqtSlot(QPoint) 1625 @pyqtSlot(QPoint)
1564 def on_usersList_customContextMenuRequested(self, pos): 1626 def on_usersList_customContextMenuRequested(self, pos):
1565 """ 1627 """
1566 Private slot to show the context menu of the users list. 1628 Private slot to show the context menu of the users list.
1567 1629
1568 @param pos the position of the mouse pointer (QPoint) 1630 @param pos the position of the mouse pointer (QPoint)
1569 """ 1631 """
1570 enable = len(self.usersList.selectedItems()) > 0 1632 enable = len(self.usersList.selectedItems()) > 0
1571 enablePrivate = enable and not self.__private 1633 enablePrivate = enable and not self.__private
1572 itm = self.usersList.itemAt(pos) 1634 itm = self.usersList.itemAt(pos)
1573 if itm and enablePrivate: 1635 if itm and enablePrivate:
1574 enablePrivate = itm.text().lower() not in [ 1636 enablePrivate = itm.text().lower() not in [
1575 "chanserv", self.__userName.lower()] 1637 "chanserv",
1638 self.__userName.lower(),
1639 ]
1576 self.__whoIsAct.setEnabled(enable) 1640 self.__whoIsAct.setEnabled(enable)
1577 self.__privateChatAct.setEnabled(enablePrivate) 1641 self.__privateChatAct.setEnabled(enablePrivate)
1578 self.__usersListRefreshAct.setEnabled( 1642 self.__usersListRefreshAct.setEnabled(
1579 self.usersList.count() <= Preferences.getIrc("AutoUserInfoMax")) 1643 self.usersList.count() <= Preferences.getIrc("AutoUserInfoMax")
1644 )
1580 self.__usersMenu.popup(self.usersList.mapToGlobal(pos)) 1645 self.__usersMenu.popup(self.usersList.mapToGlobal(pos))
1581 1646
1582 def hideEvent(self, evt): 1647 def hideEvent(self, evt):
1583 """ 1648 """
1584 Protected method handling hide events. 1649 Protected method handling hide events.
1585 1650
1586 @param evt reference to the hide event (QHideEvent) 1651 @param evt reference to the hide event (QHideEvent)
1587 """ 1652 """
1588 self.__hidden = True 1653 self.__hidden = True
1589 1654
1590 def showEvent(self, evt): 1655 def showEvent(self, evt):
1591 """ 1656 """
1592 Protected method handling show events. 1657 Protected method handling show events.
1593 1658
1594 @param evt reference to the show event (QShowEvent) 1659 @param evt reference to the show event (QShowEvent)
1595 """ 1660 """
1596 self.__hidden = False 1661 self.__hidden = False
1597 1662
1598 def initAutoWho(self): 1663 def initAutoWho(self):
1599 """ 1664 """
1600 Public method to initialize the Auto Who system. 1665 Public method to initialize the Auto Who system.
1601 """ 1666 """
1602 if Preferences.getIrc("AutoUserInfoLookup"): 1667 if Preferences.getIrc("AutoUserInfoLookup"):
1603 self.__autoWhoTimer.setInterval( 1668 self.__autoWhoTimer.setInterval(
1604 Preferences.getIrc("AutoUserInfoInterval") * 1000) 1669 Preferences.getIrc("AutoUserInfoInterval") * 1000
1670 )
1605 self.__autoWhoTimer.start() 1671 self.__autoWhoTimer.start()
1606 1672
1607 @pyqtSlot() 1673 @pyqtSlot()
1608 def __sendAutoWhoCommand(self): 1674 def __sendAutoWhoCommand(self):
1609 """ 1675 """
1610 Private slot to send the WHO command to update the users list. 1676 Private slot to send the WHO command to update the users list.
1611 """ 1677 """
1612 if self.usersList.count() <= Preferences.getIrc("AutoUserInfoMax"): 1678 if self.usersList.count() <= Preferences.getIrc("AutoUserInfoMax"):
1613 self.__autoWhoRequested = True 1679 self.__autoWhoRequested = True
1614 self.sendData.emit(self.__autoWhoTemplate.format(self.__name)) 1680 self.sendData.emit(self.__autoWhoTemplate.format(self.__name))
1615 1681
1616 def __autoWhoEntry(self, match): 1682 def __autoWhoEntry(self, match):
1617 """ 1683 """
1618 Private method to handle a WHO entry returned by the server as 1684 Private method to handle a WHO entry returned by the server as
1619 requested automatically. 1685 requested automatically.
1620 1686
1621 @param match match object that matched the pattern 1687 @param match match object that matched the pattern
1622 @return flag indicating whether the message was handled (boolean) 1688 @return flag indicating whether the message was handled (boolean)
1623 """ 1689 """
1624 # group(1) nick 1690 # group(1) nick
1625 # group(2) user flags 1691 # group(2) user flags
1626 if self.__autoWhoRequested: 1692 if self.__autoWhoRequested:
1627 itm = self.__findUser(match.group(1)) 1693 itm = self.__findUser(match.group(1))
1628 if itm: 1694 if itm:
1629 itm.parseWhoFlags(match.group(2)) 1695 itm.parseWhoFlags(match.group(2))
1630 return True 1696 return True
1631 1697
1632 return False 1698 return False
1633 1699
1634 def __whoEnd(self, match): 1700 def __whoEnd(self, match):
1635 """ 1701 """
1636 Private method to handle the end of the WHO list. 1702 Private method to handle the end of the WHO list.
1637 1703
1638 @param match match object that matched the pattern 1704 @param match match object that matched the pattern
1639 @return flag indicating whether the message was handled (boolean) 1705 @return flag indicating whether the message was handled (boolean)
1640 """ 1706 """
1641 if match.group(1).lower() == self.__name.lower(): 1707 if match.group(1).lower() == self.__name.lower():
1642 if self.__autoWhoRequested: 1708 if self.__autoWhoRequested:
1643 self.__autoWhoRequested = False 1709 self.__autoWhoRequested = False
1644 self.initAutoWho() 1710 self.initAutoWho()
1645 else: 1711 else:
1646 self.__addManagementMessage( 1712 self.__addManagementMessage(
1647 self.tr("Who"), 1713 self.tr("Who"),
1648 self.tr("End of WHO list for {0}.").format( 1714 self.tr("End of WHO list for {0}.").format(match.group(1)),
1649 match.group(1))) 1715 )
1650 return True 1716 return True
1651 1717
1652 return False 1718 return False
1653 1719
1654 def __whoEntry(self, match): 1720 def __whoEntry(self, match):
1655 """ 1721 """
1656 Private method to handle a WHO entry returned by the server as 1722 Private method to handle a WHO entry returned by the server as
1657 requested manually. 1723 requested manually.
1658 1724
1659 @param match match object that matched the pattern 1725 @param match match object that matched the pattern
1660 @return flag indicating whether the message was handled (boolean) 1726 @return flag indicating whether the message was handled (boolean)
1661 """ 1727 """
1662 # group(1) channel 1728 # group(1) channel
1663 # group(2) user 1729 # group(2) user
1664 # group(3) host 1730 # group(3) host
1665 # group(4) nick 1731 # group(4) nick
1666 # group(5) user flags 1732 # group(5) user flags
1667 # group(6) real name 1733 # group(6) real name
1668 if match.group(1).lower() == self.__name.lower(): 1734 if match.group(1).lower() == self.__name.lower():
1669 away = ( 1735 away = self.tr(" (Away)") if match.group(5).startswith("G") else ""
1670 self.tr(" (Away)")
1671 if match.group(5).startswith("G") else ""
1672 )
1673 self.__addManagementMessage( 1736 self.__addManagementMessage(
1674 self.tr("Who"), 1737 self.tr("Who"),
1675 self.tr("{0} is {1}@{2} ({3}){4}").format( 1738 self.tr("{0} is {1}@{2} ({3}){4}").format(
1676 match.group(4), match.group(2), match.group(3), 1739 match.group(4), match.group(2), match.group(3), match.group(6), away
1677 match.group(6), away)) 1740 ),
1678 return True 1741 )
1679 1742 return True
1680 return False 1743
1681 1744 return False
1745
1682 def __whoIsUser(self, match): 1746 def __whoIsUser(self, match):
1683 """ 1747 """
1684 Private method to handle the WHOIS user reply. 1748 Private method to handle the WHOIS user reply.
1685 1749
1686 @param match match object that matched the pattern 1750 @param match match object that matched the pattern
1687 @return flag indicating whether the message was handled (boolean) 1751 @return flag indicating whether the message was handled (boolean)
1688 """ 1752 """
1689 # group(1) nick 1753 # group(1) nick
1690 # group(2) user 1754 # group(2) user
1693 if match.group(1) == self.__whoIsNick: 1757 if match.group(1) == self.__whoIsNick:
1694 realName = match.group(4).replace("<", "&lt;").replace(">", "&gt;") 1758 realName = match.group(4).replace("<", "&lt;").replace(">", "&gt;")
1695 self.__addManagementMessage( 1759 self.__addManagementMessage(
1696 self.tr("Whois"), 1760 self.tr("Whois"),
1697 self.tr("{0} is {1}@{2} ({3}).").format( 1761 self.tr("{0} is {1}@{2} ({3}).").format(
1698 match.group(1), match.group(2), match.group(3), realName)) 1762 match.group(1), match.group(2), match.group(3), realName
1699 return True 1763 ),
1700 1764 )
1701 return False 1765 return True
1702 1766
1767 return False
1768
1703 def __whoIsChannels(self, match): 1769 def __whoIsChannels(self, match):
1704 """ 1770 """
1705 Private method to handle the WHOIS channels reply. 1771 Private method to handle the WHOIS channels reply.
1706 1772
1707 @param match match object that matched the pattern 1773 @param match match object that matched the pattern
1708 @return flag indicating whether the message was handled (boolean) 1774 @return flag indicating whether the message was handled (boolean)
1709 """ 1775 """
1710 # group(1) nick 1776 # group(1) nick
1711 # group(2) channels 1777 # group(2) channels
1714 voiceChannels = [] 1780 voiceChannels = []
1715 opChannels = [] 1781 opChannels = []
1716 halfopChannels = [] 1782 halfopChannels = []
1717 ownerChannels = [] 1783 ownerChannels = []
1718 adminChannels = [] 1784 adminChannels = []
1719 1785
1720 # generate the list of channels the user is in 1786 # generate the list of channels the user is in
1721 channelList = match.group(2).split() 1787 channelList = match.group(2).split()
1722 for channel in channelList: 1788 for channel in channelList:
1723 if channel.startswith(("*", "&")): 1789 if channel.startswith(("*", "&")):
1724 adminChannels.append(channel[1:]) 1790 adminChannels.append(channel[1:])
1725 elif ( 1791 elif channel.startswith(("!", "~")) and self.__ircWidget.isChannelName(
1726 channel.startswith(("!", "~")) and 1792 channel[1:]
1727 self.__ircWidget.isChannelName(channel[1:])
1728 ): 1793 ):
1729 ownerChannels.append(channel[1:]) 1794 ownerChannels.append(channel[1:])
1730 elif channel.startswith("@+"): 1795 elif channel.startswith("@+"):
1731 opChannels.append(channel[2:]) 1796 opChannels.append(channel[2:])
1732 elif channel.startswith("@"): 1797 elif channel.startswith("@"):
1735 halfopChannels.append(channel[1:]) 1800 halfopChannels.append(channel[1:])
1736 elif channel.startswith("+"): 1801 elif channel.startswith("+"):
1737 voiceChannels.append(channel[1:]) 1802 voiceChannels.append(channel[1:])
1738 else: 1803 else:
1739 userChannels.append(channel) 1804 userChannels.append(channel)
1740 1805
1741 # show messages 1806 # show messages
1742 if userChannels: 1807 if userChannels:
1743 self.__addManagementMessage( 1808 self.__addManagementMessage(
1744 self.tr("Whois"), 1809 self.tr("Whois"),
1745 self.tr("{0} is a user on channels: {1}").format( 1810 self.tr("{0} is a user on channels: {1}").format(
1746 match.group(1), " ".join(userChannels))) 1811 match.group(1), " ".join(userChannels)
1812 ),
1813 )
1747 if voiceChannels: 1814 if voiceChannels:
1748 self.__addManagementMessage( 1815 self.__addManagementMessage(
1749 self.tr("Whois"), 1816 self.tr("Whois"),
1750 self.tr("{0} has voice on channels: {1}").format( 1817 self.tr("{0} has voice on channels: {1}").format(
1751 match.group(1), " ".join(voiceChannels))) 1818 match.group(1), " ".join(voiceChannels)
1819 ),
1820 )
1752 if halfopChannels: 1821 if halfopChannels:
1753 self.__addManagementMessage( 1822 self.__addManagementMessage(
1754 self.tr("Whois"), 1823 self.tr("Whois"),
1755 self.tr("{0} is a halfop on channels: {1}").format( 1824 self.tr("{0} is a halfop on channels: {1}").format(
1756 match.group(1), " ".join(halfopChannels))) 1825 match.group(1), " ".join(halfopChannels)
1826 ),
1827 )
1757 if opChannels: 1828 if opChannels:
1758 self.__addManagementMessage( 1829 self.__addManagementMessage(
1759 self.tr("Whois"), 1830 self.tr("Whois"),
1760 self.tr("{0} is an operator on channels: {1}").format( 1831 self.tr("{0} is an operator on channels: {1}").format(
1761 match.group(1), " ".join(opChannels))) 1832 match.group(1), " ".join(opChannels)
1833 ),
1834 )
1762 if ownerChannels: 1835 if ownerChannels:
1763 self.__addManagementMessage( 1836 self.__addManagementMessage(
1764 self.tr("Whois"), 1837 self.tr("Whois"),
1765 self.tr("{0} is owner of channels: {1}").format( 1838 self.tr("{0} is owner of channels: {1}").format(
1766 match.group(1), " ".join(ownerChannels))) 1839 match.group(1), " ".join(ownerChannels)
1840 ),
1841 )
1767 if adminChannels: 1842 if adminChannels:
1768 self.__addManagementMessage( 1843 self.__addManagementMessage(
1769 self.tr("Whois"), 1844 self.tr("Whois"),
1770 self.tr("{0} is admin on channels: {1}").format( 1845 self.tr("{0} is admin on channels: {1}").format(
1771 match.group(1), " ".join(adminChannels))) 1846 match.group(1), " ".join(adminChannels)
1772 return True 1847 ),
1773 1848 )
1774 return False 1849 return True
1775 1850
1851 return False
1852
1776 def __whoIsServer(self, match): 1853 def __whoIsServer(self, match):
1777 """ 1854 """
1778 Private method to handle the WHOIS server reply. 1855 Private method to handle the WHOIS server reply.
1779 1856
1780 @param match match object that matched the pattern 1857 @param match match object that matched the pattern
1781 @return flag indicating whether the message was handled (boolean) 1858 @return flag indicating whether the message was handled (boolean)
1782 """ 1859 """
1783 # group(1) nick 1860 # group(1) nick
1784 # group(2) server 1861 # group(2) server
1785 # group(3) server info 1862 # group(3) server info
1786 if match.group(1) == self.__whoIsNick: 1863 if match.group(1) == self.__whoIsNick:
1787 self.__addManagementMessage( 1864 self.__addManagementMessage(
1788 self.tr("Whois"), 1865 self.tr("Whois"),
1789 self.tr("{0} is online via {1} ({2}).").format( 1866 self.tr("{0} is online via {1} ({2}).").format(
1790 match.group(1), match.group(2), match.group(3))) 1867 match.group(1), match.group(2), match.group(3)
1791 return True 1868 ),
1792 1869 )
1793 return False 1870 return True
1794 1871
1872 return False
1873
1795 def __whoIsOperator(self, match): 1874 def __whoIsOperator(self, match):
1796 """ 1875 """
1797 Private method to handle the WHOIS operator reply. 1876 Private method to handle the WHOIS operator reply.
1798 1877
1799 @param match match object that matched the pattern 1878 @param match match object that matched the pattern
1800 @return flag indicating whether the message was handled (boolean) 1879 @return flag indicating whether the message was handled (boolean)
1801 """ 1880 """
1802 # group(1) nick 1881 # group(1) nick
1803 # group(2) message 1882 # group(2) message
1804 if match.group(1) == self.__whoIsNick: 1883 if match.group(1) == self.__whoIsNick:
1805 if match.group(2).lower().startswith("is an irc operator"): 1884 if match.group(2).lower().startswith("is an irc operator"):
1806 self.__addManagementMessage( 1885 self.__addManagementMessage(
1807 self.tr("Whois"), 1886 self.tr("Whois"),
1808 self.tr("{0} is an IRC Operator.").format( 1887 self.tr("{0} is an IRC Operator.").format(match.group(1)),
1809 match.group(1))) 1888 )
1810 else: 1889 else:
1811 self.__addManagementMessage( 1890 self.__addManagementMessage(
1812 self.tr("Whois"), 1891 self.tr("Whois"), "{0} {1}".format(match.group(1), match.group(2))
1813 "{0} {1}".format(match.group(1), match.group(2))) 1892 )
1814 return True 1893 return True
1815 1894
1816 return False 1895 return False
1817 1896
1818 def __whoIsIdle(self, match): 1897 def __whoIsIdle(self, match):
1819 """ 1898 """
1820 Private method to handle the WHOIS idle reply. 1899 Private method to handle the WHOIS idle reply.
1821 1900
1822 @param match match object that matched the pattern 1901 @param match match object that matched the pattern
1823 @return flag indicating whether the message was handled (boolean) 1902 @return flag indicating whether the message was handled (boolean)
1824 """ 1903 """
1825 # group(1) nick 1904 # group(1) nick
1826 # group(2) idle seconds 1905 # group(2) idle seconds
1828 if match.group(1) == self.__whoIsNick: 1907 if match.group(1) == self.__whoIsNick:
1829 seconds = int(match.group(2)) 1908 seconds = int(match.group(2))
1830 minutes = seconds // 60 1909 minutes = seconds // 60
1831 hours = minutes // 60 1910 hours = minutes // 60
1832 days = hours // 24 1911 days = hours // 24
1833 1912
1834 signonTimestamp = int(match.group(3)) 1913 signonTimestamp = int(match.group(3))
1835 signonTime = QDateTime() 1914 signonTime = QDateTime()
1836 signonTime.setTime_t(signonTimestamp) 1915 signonTime.setTime_t(signonTimestamp)
1837 1916
1838 if days: 1917 if days:
1839 daysString = self.tr("%n day(s)", "", days) 1918 daysString = self.tr("%n day(s)", "", days)
1840 hoursString = self.tr("%n hour(s)", "", hours) 1919 hoursString = self.tr("%n hour(s)", "", hours)
1841 minutesString = self.tr("%n minute(s)", "", minutes) 1920 minutesString = self.tr("%n minute(s)", "", minutes)
1842 secondsString = self.tr("%n second(s)", "", seconds) 1921 secondsString = self.tr("%n second(s)", "", seconds)
1844 self.tr("Whois"), 1923 self.tr("Whois"),
1845 self.tr( 1924 self.tr(
1846 "{0} has been idle for {1}, {2}, {3}, and {4}.", 1925 "{0} has been idle for {1}, {2}, {3}, and {4}.",
1847 "{0} = name of person, {1} = (x days)," 1926 "{0} = name of person, {1} = (x days),"
1848 " {2} = (x hours), {3} = (x minutes)," 1927 " {2} = (x hours), {3} = (x minutes),"
1849 " {4} = (x seconds)").format( 1928 " {4} = (x seconds)",
1850 match.group(1), daysString, hoursString, minutesString, 1929 ).format(
1851 secondsString)) 1930 match.group(1),
1931 daysString,
1932 hoursString,
1933 minutesString,
1934 secondsString,
1935 ),
1936 )
1852 elif hours: 1937 elif hours:
1853 hoursString = self.tr("%n hour(s)", "", hours) 1938 hoursString = self.tr("%n hour(s)", "", hours)
1854 minutesString = self.tr("%n minute(s)", "", minutes) 1939 minutesString = self.tr("%n minute(s)", "", minutes)
1855 secondsString = self.tr("%n second(s)", "", seconds) 1940 secondsString = self.tr("%n second(s)", "", seconds)
1856 self.__addManagementMessage( 1941 self.__addManagementMessage(
1857 self.tr("Whois"), 1942 self.tr("Whois"),
1858 self.tr( 1943 self.tr(
1859 "{0} has been idle for {1}, {2}, and {3}.", 1944 "{0} has been idle for {1}, {2}, and {3}.",
1860 "{0} = name of person, {1} = (x hours), " 1945 "{0} = name of person, {1} = (x hours), "
1861 "{2} = (x minutes), {3} = (x seconds)") 1946 "{2} = (x minutes), {3} = (x seconds)",
1862 .format(match.group(1), hoursString, minutesString, 1947 ).format(match.group(1), hoursString, minutesString, secondsString),
1863 secondsString)) 1948 )
1864 elif minutes: 1949 elif minutes:
1865 minutesString = self.tr("%n minute(s)", "", minutes) 1950 minutesString = self.tr("%n minute(s)", "", minutes)
1866 secondsString = self.tr("%n second(s)", "", seconds) 1951 secondsString = self.tr("%n second(s)", "", seconds)
1867 self.__addManagementMessage( 1952 self.__addManagementMessage(
1868 self.tr("Whois"), 1953 self.tr("Whois"),
1869 self.tr( 1954 self.tr(
1870 "{0} has been idle for {1} and {2}.", 1955 "{0} has been idle for {1} and {2}.",
1871 "{0} = name of person, {1} = (x minutes), " 1956 "{0} = name of person, {1} = (x minutes), " "{3} = (x seconds)",
1872 "{3} = (x seconds)") 1957 ).format(match.group(1), minutesString, secondsString),
1873 .format(match.group(1), minutesString, secondsString)) 1958 )
1874 else: 1959 else:
1875 self.__addManagementMessage( 1960 self.__addManagementMessage(
1876 self.tr("Whois"), 1961 self.tr("Whois"),
1877 self.tr( 1962 self.tr("{0} has been idle for %n second(s).", "", seconds).format(
1878 "{0} has been idle for %n second(s).", "", 1963 match.group(1)
1879 seconds).format(match.group(1))) 1964 ),
1880 1965 )
1966
1881 if not signonTime.isNull(): 1967 if not signonTime.isNull():
1882 self.__addManagementMessage( 1968 self.__addManagementMessage(
1883 self.tr("Whois"), 1969 self.tr("Whois"),
1884 self.tr("{0} has been online since {1}.").format( 1970 self.tr("{0} has been online since {1}.").format(
1885 match.group(1), 1971 match.group(1), signonTime.toString("yyyy-MM-dd, hh:mm:ss")
1886 signonTime.toString("yyyy-MM-dd, hh:mm:ss"))) 1972 ),
1887 return True 1973 )
1888 1974 return True
1889 return False 1975
1890 1976 return False
1977
1891 def __whoIsEnd(self, match): 1978 def __whoIsEnd(self, match):
1892 """ 1979 """
1893 Private method to handle the end of WHOIS reply. 1980 Private method to handle the end of WHOIS reply.
1894 1981
1895 @param match match object that matched the pattern 1982 @param match match object that matched the pattern
1896 @return flag indicating whether the message was handled (boolean) 1983 @return flag indicating whether the message was handled (boolean)
1897 """ 1984 """
1898 # group(1) nick 1985 # group(1) nick
1899 # group(2) end message 1986 # group(2) end message
1900 if match.group(1) == self.__whoIsNick: 1987 if match.group(1) == self.__whoIsNick:
1901 self.__whoIsNick = "" 1988 self.__whoIsNick = ""
1902 self.__addManagementMessage( 1989 self.__addManagementMessage(
1903 self.tr("Whois"), 1990 self.tr("Whois"),
1904 self.tr("End of WHOIS list for {0}.").format( 1991 self.tr("End of WHOIS list for {0}.").format(match.group(1)),
1905 match.group(1))) 1992 )
1906 return True 1993 return True
1907 1994
1908 return False 1995 return False
1909 1996
1910 def __whoIsIdentify(self, match): 1997 def __whoIsIdentify(self, match):
1911 """ 1998 """
1912 Private method to handle the WHOIS identify and identified replies. 1999 Private method to handle the WHOIS identify and identified replies.
1913 2000
1914 @param match match object that matched the pattern 2001 @param match match object that matched the pattern
1915 @return flag indicating whether the message was handled (boolean) 2002 @return flag indicating whether the message was handled (boolean)
1916 """ 2003 """
1917 # group(1) nick 2004 # group(1) nick
1918 # group(2) identified message 2005 # group(2) identified message
1919 if match.group(1) == self.__whoIsNick: 2006 if match.group(1) == self.__whoIsNick:
1920 self.__addManagementMessage( 2007 self.__addManagementMessage(
1921 self.tr("Whois"), 2008 self.tr("Whois"),
1922 self.tr("{0} is an identified user.").format( 2009 self.tr("{0} is an identified user.").format(match.group(1)),
1923 match.group(1))) 2010 )
1924 return True 2011 return True
1925 2012
1926 return False 2013 return False
1927 2014
1928 def __whoIsHelper(self, match): 2015 def __whoIsHelper(self, match):
1929 """ 2016 """
1930 Private method to handle the WHOIS helper reply. 2017 Private method to handle the WHOIS helper reply.
1931 2018
1932 @param match match object that matched the pattern 2019 @param match match object that matched the pattern
1933 @return flag indicating whether the message was handled (boolean) 2020 @return flag indicating whether the message was handled (boolean)
1934 """ 2021 """
1935 # group(1) nick 2022 # group(1) nick
1936 # group(2) helper message 2023 # group(2) helper message
1937 if match.group(1) == self.__whoIsNick: 2024 if match.group(1) == self.__whoIsNick:
1938 self.__addManagementMessage( 2025 self.__addManagementMessage(
1939 self.tr("Whois"), 2026 self.tr("Whois"),
1940 self.tr("{0} is available for help.").format( 2027 self.tr("{0} is available for help.").format(match.group(1)),
1941 match.group(1))) 2028 )
1942 return True 2029 return True
1943 2030
1944 return False 2031 return False
1945 2032
1946 def __whoIsAccount(self, match): 2033 def __whoIsAccount(self, match):
1947 """ 2034 """
1948 Private method to handle the WHOIS account reply. 2035 Private method to handle the WHOIS account reply.
1949 2036
1950 @param match match object that matched the pattern 2037 @param match match object that matched the pattern
1951 @return flag indicating whether the message was handled (boolean) 2038 @return flag indicating whether the message was handled (boolean)
1952 """ 2039 """
1953 # group(1) nick 2040 # group(1) nick
1954 # group(2) login name 2041 # group(2) login name
1955 if match.group(1) == self.__whoIsNick: 2042 if match.group(1) == self.__whoIsNick:
1956 self.__addManagementMessage( 2043 self.__addManagementMessage(
1957 self.tr("Whois"), 2044 self.tr("Whois"),
1958 self.tr("{0} is logged in as {1}.").format( 2045 self.tr("{0} is logged in as {1}.").format(
1959 match.group(1), match.group(2))) 2046 match.group(1), match.group(2)
1960 return True 2047 ),
1961 2048 )
1962 return False 2049 return True
1963 2050
2051 return False
2052
1964 def __whoIsActually(self, match): 2053 def __whoIsActually(self, match):
1965 """ 2054 """
1966 Private method to handle the WHOIS actually reply. 2055 Private method to handle the WHOIS actually reply.
1967 2056
1968 @param match match object that matched the pattern 2057 @param match match object that matched the pattern
1969 @return flag indicating whether the message was handled (boolean) 2058 @return flag indicating whether the message was handled (boolean)
1970 """ 2059 """
1971 # group(1) nick 2060 # group(1) nick
1972 # group(2) actual user@host 2061 # group(2) actual user@host
1973 # group(3) actual IP 2062 # group(3) actual IP
1974 if match.group(1) == self.__whoIsNick: 2063 if match.group(1) == self.__whoIsNick:
1975 self.__addManagementMessage( 2064 self.__addManagementMessage(
1976 self.tr("Whois"), 2065 self.tr("Whois"),
1977 self.tr( 2066 self.tr("{0} is actually using the host {1} (IP: {2}).").format(
1978 "{0} is actually using the host {1} (IP: {2}).").format( 2067 match.group(1), match.group(2), match.group(3)
1979 match.group(1), match.group(2), match.group(3))) 2068 ),
1980 return True 2069 )
1981 2070 return True
1982 return False 2071
1983 2072 return False
2073
1984 def __whoIsSecure(self, match): 2074 def __whoIsSecure(self, match):
1985 """ 2075 """
1986 Private method to handle the WHOIS secure reply. 2076 Private method to handle the WHOIS secure reply.
1987 2077
1988 @param match match object that matched the pattern 2078 @param match match object that matched the pattern
1989 @return flag indicating whether the message was handled (boolean) 2079 @return flag indicating whether the message was handled (boolean)
1990 """ 2080 """
1991 # group(1) nick 2081 # group(1) nick
1992 if match.group(1) == self.__whoIsNick: 2082 if match.group(1) == self.__whoIsNick:
1993 self.__addManagementMessage( 2083 self.__addManagementMessage(
1994 self.tr("Whois"), 2084 self.tr("Whois"),
1995 self.tr("{0} is using a secure connection.").format( 2085 self.tr("{0} is using a secure connection.").format(match.group(1)),
1996 match.group(1))) 2086 )
1997 return True 2087 return True
1998 2088
1999 return False 2089 return False
2000 2090
2001 def __whoIsConnection(self, match): 2091 def __whoIsConnection(self, match):
2002 """ 2092 """
2003 Private method to handle the WHOIS connection reply. 2093 Private method to handle the WHOIS connection reply.
2004 2094
2005 @param match match object that matched the pattern 2095 @param match match object that matched the pattern
2006 @return flag indicating whether the message was handled (boolean) 2096 @return flag indicating whether the message was handled (boolean)
2007 """ 2097 """
2008 # group(1) nick 2098 # group(1) nick
2009 # group(2) host name 2099 # group(2) host name
2010 # group(3) IP 2100 # group(3) IP
2011 if match.group(1) == self.__whoIsNick: 2101 if match.group(1) == self.__whoIsNick:
2012 self.__addManagementMessage( 2102 self.__addManagementMessage(
2013 self.tr("Whois"), 2103 self.tr("Whois"),
2014 self.tr("{0} is connecting from {1} (IP: {2}).").format( 2104 self.tr("{0} is connecting from {1} (IP: {2}).").format(
2015 match.group(1), match.group(2), match.group(3))) 2105 match.group(1), match.group(2), match.group(3)
2016 return True 2106 ),
2017 2107 )
2018 return False 2108 return True
2019 2109
2110 return False
2111
2020 def __setEditTopicButton(self): 2112 def __setEditTopicButton(self):
2021 """ 2113 """
2022 Private method to set the visibility of the Edit Topic button. 2114 Private method to set the visibility of the Edit Topic button.
2023 """ 2115 """
2024 itm = self.__findUser(self.__userName) 2116 itm = self.__findUser(self.__userName)
2025 if itm: 2117 if itm:
2026 self.editTopicButton.setVisible(itm.canChangeTopic()) 2118 self.editTopicButton.setVisible(itm.canChangeTopic())
2027 2119
2028 @pyqtSlot() 2120 @pyqtSlot()
2029 def on_editTopicButton_clicked(self): 2121 def on_editTopicButton_clicked(self):
2030 """ 2122 """
2031 Private slot to change the topic of the channel. 2123 Private slot to change the topic of the channel.
2032 """ 2124 """
2033 topic, ok = QInputDialog.getText( 2125 topic, ok = QInputDialog.getText(
2034 self, 2126 self,
2035 self.tr("Edit Channel Topic"), 2127 self.tr("Edit Channel Topic"),
2036 self.tr("Enter the topic for this channel:"), 2128 self.tr("Enter the topic for this channel:"),
2037 QLineEdit.EchoMode.Normal, 2129 QLineEdit.EchoMode.Normal,
2038 self.topicLabel.text()) 2130 self.topicLabel.text(),
2131 )
2039 if ok and topic != "": 2132 if ok and topic != "":
2040 self.sendData.emit("TOPIC {0} :{1}".format( 2133 self.sendData.emit("TOPIC {0} :{1}".format(self.__name, topic))
2041 self.__name, topic)) 2134
2042
2043 @pyqtSlot(QUrl) 2135 @pyqtSlot(QUrl)
2044 def on_messages_anchorClicked(self, url): 2136 def on_messages_anchorClicked(self, url):
2045 """ 2137 """
2046 Private slot to open links in the default browser. 2138 Private slot to open links in the default browser.
2047 2139
2048 @param url URL to be opened (QUrl) 2140 @param url URL to be opened (QUrl)
2049 """ 2141 """
2050 QDesktopServices.openUrl(url) 2142 QDesktopServices.openUrl(url)

eric ide

mercurial