--- a/src/eric7/Network/IRC/IrcChannelWidget.py Wed Jul 13 11:16:20 2022 +0200 +++ b/src/eric7/Network/IRC/IrcChannelWidget.py Wed Jul 13 14:55:47 2022 +0200 @@ -13,11 +13,22 @@ import re from PyQt6.QtCore import ( - pyqtSlot, pyqtSignal, QDateTime, QPoint, QTimer, QUrl, QCoreApplication + pyqtSlot, + pyqtSignal, + QDateTime, + QPoint, + QTimer, + QUrl, + QCoreApplication, ) from PyQt6.QtGui import QIcon, QPainter, QTextCursor, QDesktopServices from PyQt6.QtWidgets import ( - QWidget, QListWidgetItem, QMenu, QApplication, QInputDialog, QLineEdit + QWidget, + QListWidgetItem, + QMenu, + QApplication, + QInputDialog, + QLineEdit, ) from EricWidgets import EricMessageBox, EricFileDialog @@ -38,60 +49,60 @@ """ Class implementing a list widget item containing an IRC channel user. """ - Normal = 0x00 # no privileges - Operator = 0x01 # channel operator - Voice = 0x02 # voice operator - Admin = 0x04 # administrator - Halfop = 0x08 # half operator - Owner = 0x10 # channel owner - Away = 0x80 # user away - + + Normal = 0x00 # no privileges + Operator = 0x01 # channel operator + Voice = 0x02 # voice operator + Admin = 0x04 # administrator + Halfop = 0x08 # half operator + Owner = 0x10 # channel owner + Away = 0x80 # user away + PrivilegeMapping = { "a": Away, "o": Operator, "O": Owner, "v": Voice, - } - + def __init__(self, name, parent=None): """ Constructor - + @param name string with user name and privilege prefix (string) @param parent reference to the parent widget (QListWidget or QListWidgetItem) """ super().__init__(name, parent) - + self.__privilege = IrcUserItem.Normal self.__name = name self.__ignored = False - + self.__setText() self.__setIcon() - + def name(self): """ Public method to get the user name. - + @return user name (string) """ return self.__name - + def setName(self, name): """ Public method to set a new nick name. - + @param name new nick name for the user (string) """ self.__name = name self.__setText() - + def changePrivilege(self, privilege): """ Public method to set or unset a user privilege. - + @param privilege privilege to set or unset (string) """ oper = privilege[0] @@ -102,25 +113,27 @@ elif oper == "-": self.__privilege &= ~IrcUserItem.PrivilegeMapping[priv] self.__setIcon() - + def clearPrivileges(self): """ Public method to clear the user privileges. """ self.__privilege = IrcUserItem.Normal self.__setIcon() - + def __setText(self): """ Private method to set the user item text. """ if self.__ignored: - self.setText(QCoreApplication.translate( - "IrcUserItem", - "{0} (ignored)").format(self.__name)) + self.setText( + QCoreApplication.translate("IrcUserItem", "{0} (ignored)").format( + self.__name + ) + ) else: self.setText(self.__name) - + def __setIcon(self): """ Private method to set the icon dependent on user privileges. @@ -140,14 +153,14 @@ icon = UI.PixmapCache.getIcon("ircNormal") if self.__privilege & IrcUserItem.Away: icon = self.__awayIcon(icon) - + # step 2: set the icon self.setIcon(icon) - + def __awayIcon(self, icon): """ Private method to convert an icon to an away icon. - + @param icon icon to be converted (QIcon) @return away icon (QIcon) """ @@ -157,11 +170,11 @@ painter.drawPixmap(0, 0, pix2) painter.end() return QIcon(pix1) - + def parseWhoFlags(self, flags): """ Public method to parse the user flags reported by a WHO command. - + @param flags user flags as reported by WHO (string) """ # H The user is not away. @@ -181,31 +194,33 @@ privilege |= IrcUserItem.Away self.__privilege = privilege self.__setIcon() - + def canChangeTopic(self): """ Public method to check, if the user is allowed to change the topic. - + @return flag indicating that the topic can be changed (boolean) """ - return(bool(self.__privilege & IrcUserItem.Operator) or - bool(self.__privilege & IrcUserItem.Admin) or - bool(self.__privilege & IrcUserItem.Owner)) - + return ( + bool(self.__privilege & IrcUserItem.Operator) + or bool(self.__privilege & IrcUserItem.Admin) + or bool(self.__privilege & IrcUserItem.Owner) + ) + def setIgnored(self, ignored): """ Public method to set the user status to ignored. - + @param ignored flag indicating the new ignored status @type bool """ self.__ignored = ignored self.__setText() - + def isIgnored(self): """ Public method to check, if this user is ignored. - + @return flag indicating the ignored status @rtype bool """ @@ -215,7 +230,7 @@ class IrcChannelWidget(QWidget, Ui_IrcChannelWidget): """ Class implementing the IRC channel widget. - + @signal sendData(str) emitted to send a message to the channel @signal sendCtcpRequest(str, str, str) emitted to send a CTCP request @signal sendCtcpReply(str, str) emitted to send a CTCP reply @@ -227,6 +242,7 @@ @signal leaveChannels(list) emitted to leave a list of channels @signal leaveAllChannels() emitted to leave all channels """ + sendData = pyqtSignal(str) sendCtcpRequest = pyqtSignal(str, str, str) sendCtcpReply = pyqtSignal(str, str) @@ -235,37 +251,37 @@ awayCommand = pyqtSignal(str) leaveChannels = pyqtSignal(list) leaveAllChannels = pyqtSignal() - + UrlRe = re.compile( r"""((?:http|ftp|https):\/\/[\w\-_]+(?:\.[\w\-_]+)+""" - r"""(?:[\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?)""") - + r"""(?:[\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?)""" + ) + JoinIndicator = "-->" LeaveIndicator = "<--" MessageIndicator = "***" - + def __init__(self, parent=None): """ Constructor - + @param parent reference to the parent widget (QWidget) """ super().__init__(parent) self.setupUi(self) - + self.__ui = ericApp().getObject("UserInterface") self.__ircWidget = parent - - self.editTopicButton.setIcon( - UI.PixmapCache.getIcon("ircEditTopic")) + + self.editTopicButton.setIcon(UI.PixmapCache.getIcon("ircEditTopic")) self.editTopicButton.hide() - + height = self.usersList.height() + self.messages.height() self.splitter.setSizes([int(height * 0.3), int(height * 0.7)]) - + self.__initMessagesMenu() self.__initUsersMenu() - + self.__name = "" self.__userName = "" self.__partMessage = "" @@ -273,20 +289,18 @@ self.__private = False self.__privatePartner = "" self.__whoIsNick = "" - + self.__markerLine = "" self.__hidden = True - + self.__serviceNamesLower = ["nickserv", "chanserv", "memoserv"] - + self.__patterns = [ # :foo_!n=foo@foohost.bar.net PRIVMSG #eric-ide :some long message # :foo_!n=foo@foohost.bar.net PRIVMSG bar_ :some long message - (re.compile(r":([^!]+)!([^ ]+)\sPRIVMSG\s([^ ]+)\s:(.*)"), - self.__message), + (re.compile(r":([^!]+)!([^ ]+)\sPRIVMSG\s([^ ]+)\s:(.*)"), self.__message), # :foo_!n=foo@foohost.bar.net JOIN :#eric-ide - (re.compile(r":([^!]+)!([^ ]+)\sJOIN\s:?([^ ]+)"), - self.__userJoin), + (re.compile(r":([^!]+)!([^ ]+)\sJOIN\s:?([^ ]+)"), self.__userJoin), # :foo_!n=foo@foohost.bar.net PART #eric-ide :part message (re.compile(r":([^!]+).*\sPART\s([^ ]+)\s:(.*)"), self.__userPart), # :foo_!n=foo@foohost.bar.net PART #eric-ide @@ -298,16 +312,16 @@ # :foo_!n=foo@foohost.bar.net NICK :newnick (re.compile(r":([^!]+).*\sNICK\s:(.*)"), self.__userNickChange), # :foo_!n=foo@foohost.bar.net MODE #eric-ide +o foo_ - (re.compile(r":([^!]+).*\sMODE\s([^ ]+)\s([+-][ovO]+)\s([^ ]+).*"), - self.__setUserPrivilege), + ( + re.compile(r":([^!]+).*\sMODE\s([^ ]+)\s([+-][ovO]+)\s([^ ]+).*"), + self.__setUserPrivilege, + ), # :cameron.libera.chat MODE #eric-ide +ns - (re.compile(r":([^ ]+)\sMODE\s([^ ]+)\s(.+)"), - self.__updateChannelModes), + (re.compile(r":([^ ]+)\sMODE\s([^ ]+)\s(.+)"), self.__updateChannelModes), # :foo_!n=foo@foohost.bar.net TOPIC #eric-ide :eric - Python IDE (re.compile(r":.*\sTOPIC\s([^ ]+)\s:(.*)"), self.__setTopic), # :sturgeon.libera.chat 301 foo_ bar :Gone away for now - (re.compile(r":.*\s301\s([^ ]+)\s([^ ]+)\s:(.+)"), - self.__userAway), + (re.compile(r":.*\s301\s([^ ]+)\s([^ ]+)\s:(.+)"), self.__userAway), # :sturgeon.libera.chat 315 foo_ #eric-ide :End of /WHO list. (re.compile(r":.*\s315\s[^ ]+\s([^ ]+)\s:(.*)"), self.__whoEnd), # :zelazny.libera.chat 324 foo_ #eric-ide +cnt @@ -315,78 +329,84 @@ # :zelazny.libera.chat 328 foo_ #eric-ide :http://www.bugger.com/ (re.compile(r":.*\s328\s.*\s([^ ]+)\s:(.+)"), self.__channelUrl), # :zelazny.libera.chat 329 foo_ #eric-ide 1353001005 - (re.compile(r":.*\s329\s.*\s([^ ]+)\s(.+)"), - self.__channelCreated), + (re.compile(r":.*\s329\s.*\s([^ ]+)\s(.+)"), self.__channelCreated), # :zelazny.libera.chat 332 foo_ #eric-ide :eric support channel (re.compile(r":.*\s332\s.*\s([^ ]+)\s:(.*)"), self.__setTopic), # :zelazny.libera.chat foo_ 333 #eric-ide foo 1353089020 - (re.compile(r":.*\s333\s.*\s([^ ]+)\s([^ ]+)\s(\d+)"), - self.__topicCreated), + (re.compile(r":.*\s333\s.*\s([^ ]+)\s([^ ]+)\s(\d+)"), self.__topicCreated), # :cameron.libera.chat 352 detlev_ #eric-ide ~foo foohost.bar.net # cameron.libera.chat foo_ H :0 Foo Bar - (re.compile( - r":.*\s352\s[^ ]+\s([^ ]+)\s([^ ]+)\s([^ ]+)\s[^ ]+\s([^ ]+)" - r"\s([^ ]+)\s:\d+\s(.*)"), self.__whoEntry), + ( + re.compile( + r":.*\s352\s[^ ]+\s([^ ]+)\s([^ ]+)\s([^ ]+)\s[^ ]+\s([^ ]+)" + r"\s([^ ]+)\s:\d+\s(.*)" + ), + self.__whoEntry, + ), # :zelazny.libera.chat 353 foo_ @ #eric-ide :@user1 +user2 user3 (re.compile(r":.*\s353\s.*\s.\s([^ ]+)\s:(.*)"), self.__userList), # :sturgeon.libera.chat 354 foo_ 42 ChanServ H@ - (re.compile(r":.*\s354\s[^ ]+\s42\s([^ ]+)\s(.*)"), - self.__autoWhoEntry), + (re.compile(r":.*\s354\s[^ ]+\s42\s([^ ]+)\s(.*)"), self.__autoWhoEntry), # :zelazny.libera.chat 366 foo_ #eric-ide :End of /NAMES list. (re.compile(r":.*\s366\s.*\s([^ ]+)\s:(.*)"), self.__ignore), # :sturgeon.libera.chat 704 foo_ index :Help topics available: (re.compile(r":.*\s70[456]\s[^ ]+\s([^ ]+)\s:(.*)"), self.__help), - # WHOIS replies # :sturgeon.libera.chat 311 foo_ bar ~bar barhost.foo.net * :Bar - (re.compile( - r":.*\s311\s[^ ]+\s([^ ]+)\s([^ ]+)\s([^ ]+)\s\*\s:(.*)"), - self.__whoIsUser), + ( + re.compile(r":.*\s311\s[^ ]+\s([^ ]+)\s([^ ]+)\s([^ ]+)\s\*\s:(.*)"), + self.__whoIsUser, + ), # :sturgeon.libera.chat 319 foo_ bar :@#eric-ide - (re.compile(r":.*\s319\s[^ ]+\s([^ ]+)\s:(.*)"), - self.__whoIsChannels), + (re.compile(r":.*\s319\s[^ ]+\s([^ ]+)\s:(.*)"), self.__whoIsChannels), # :sturgeon.libera.chat 312 foo_ bar sturgeon.libera.chat :London - (re.compile(r":.*\s312\s[^ ]+\s([^ ]+)\s([^ ]+)\s:(.*)"), - self.__whoIsServer), + ( + re.compile(r":.*\s312\s[^ ]+\s([^ ]+)\s([^ ]+)\s:(.*)"), + self.__whoIsServer, + ), # :sturgeon.libera.chat 671 foo_ bar :is using a secure connection (re.compile(r":.*\s671\s[^ ]+\s([^ ]+)\s:.*"), self.__whoIsSecure), # :sturgeon.libera.chat 317 foo_ bar 3758 1355046912 :seconds # idle, signon time - (re.compile(r":.*\s317\s[^ ]+\s([^ ]+)\s(\d+)\s(\d+)\s:.*"), - self.__whoIsIdle), + ( + re.compile(r":.*\s317\s[^ ]+\s([^ ]+)\s(\d+)\s(\d+)\s:.*"), + self.__whoIsIdle, + ), # :sturgeon.libera.chat 330 foo_ bar bar :is logged in as - (re.compile(r":.*\s330\s[^ ]+\s([^ ]+)\s([^ ]+)\s:.*"), - self.__whoIsAccount), + ( + re.compile(r":.*\s330\s[^ ]+\s([^ ]+)\s([^ ]+)\s:.*"), + self.__whoIsAccount, + ), # :sturgeon.libera.chat 318 foo_ bar :End of /WHOIS list. (re.compile(r":.*\s318\s[^ ]+\s([^ ]+)\s:(.*)"), self.__whoIsEnd), # :sturgeon.libera.chat 307 foo_ bar :is an identified user - (re.compile(r":.*\s307\s[^ ]+\s([^ ]+)\s:(.*)"), - self.__whoIsIdentify), + (re.compile(r":.*\s307\s[^ ]+\s([^ ]+)\s:(.*)"), self.__whoIsIdentify), # :sturgeon.libera.chat 320 foo_ bar :is an identified user - (re.compile(r":.*\s320\s[^ ]+\s([^ ]+)\s:(.*)"), - self.__whoIsIdentify), + (re.compile(r":.*\s320\s[^ ]+\s([^ ]+)\s:(.*)"), self.__whoIsIdentify), # :sturgeon.libera.chat 310 foo_ bar :is available for help - (re.compile(r":.*\s310\s[^ ]+\s([^ ]+)\s:(.*)"), - self.__whoIsHelper), + (re.compile(r":.*\s310\s[^ ]+\s([^ ]+)\s:(.*)"), self.__whoIsHelper), # :sturgeon.libera.chat 338 foo_ bar real.ident@real.host # 12.34.56.78 :Actual user@host, Actual IP - (re.compile(r":.*\s338\s[^ ]+\s([^ ]+)\s([^ ]+)\s([^ ]+)\s:.*"), - self.__whoIsActually), + ( + re.compile(r":.*\s338\s[^ ]+\s([^ ]+)\s([^ ]+)\s([^ ]+)\s:.*"), + self.__whoIsActually, + ), # :sturgeon.libera.chat 313 foo_ bar :is an IRC Operator - (re.compile(r":.*\s313\s[^ ]+\s([^ ]+)\s:(.*)"), - self.__whoIsOperator), + (re.compile(r":.*\s313\s[^ ]+\s([^ ]+)\s:(.*)"), self.__whoIsOperator), # :sturgeon.libera.chat 378 foo_ bar :is connecting from # *@mnch-4d044d5a.pool.mediaWays.net 77.4.77.90 - (re.compile(r":.*\s378\s[^ ]+\s([^ ]+)\s:.*\s([^ ]+)\s([^ ]+)"), - self.__whoIsConnection), + ( + re.compile(r":.*\s378\s[^ ]+\s([^ ]+)\s:.*\s([^ ]+)\s([^ ]+)"), + self.__whoIsConnection, + ), ] - + self.__autoWhoTemplate = "WHO {0} %tnf,42" self.__autoWhoTimer = QTimer() self.__autoWhoTimer.setSingleShot(True) self.__autoWhoTimer.timeout.connect(self.__sendAutoWhoCommand) self.__autoWhoRequested = False - + @pyqtSlot() def on_messageEdit_returnPressed(self): """ @@ -400,17 +420,20 @@ """ Private method to process a message entered by the user or via the user list context menu. - + @param msg message to be processed @type str """ self.messages.append( '<font color="{0}">{2} <b><</b><font color="{1}">{3}</font>' - '<b>></b> {4}</font>'.format( + "<b>></b> {4}</font>".format( Preferences.getIrc("ChannelMessageColour"), Preferences.getIrc("OwnNickColour"), - ircTimestamp(), self.__userName, - Utilities.html_encode(msg))) + ircTimestamp(), + self.__userName, + Utilities.html_encode(msg), + ) + ) if msg.startswith("/"): if self.__private: @@ -419,7 +442,9 @@ self.tr("Send Message"), self.tr( """Messages starting with a '/' are not allowed""" - """ in private chats.""")) + """ in private chats.""" + ), + ) else: sendData = True # flag set to False, if command was handled @@ -429,25 +454,25 @@ if cmd in ["MSG", "QUERY"]: cmd = "PRIVMSG" if len(msgList) > 1: - if ( - msgList[1].strip().lower() in - self.__serviceNamesLower - ): + if msgList[1].strip().lower() in self.__serviceNamesLower: msg = ( - "PRIVMSG " + - msgList[1].strip().lower() + - " :" + " ".join(msgList[2:]) + "PRIVMSG " + + msgList[1].strip().lower() + + " :" + + " ".join(msgList[2:]) ) else: msg = "PRIVMSG {0} :{1}".format( - msgList[1], " ".join(msgList[2:])) + msgList[1], " ".join(msgList[2:]) + ) else: msgList[0] = cmd msg = " ".join(msgList) elif cmd == "NOTICE": if len(msgList) > 2: msg = "NOTICE {0} :{1}".format( - msgList[1], " ".join(msgList[2:])) + msgList[1], " ".join(msgList[2:]) + ) else: msg = "NOTICE {0}".format(" ".join(msgList[1:])) elif cmd == "PING": @@ -466,8 +491,9 @@ userNamesList = msgList[1:] else: userNamesList = [] - userNames = ",".join( - u.rstrip(",") for u in userNamesList).split(",") + userNames = ",".join(u.rstrip(",") for u in userNamesList).split( + "," + ) for userName in userNames: itm = self.__findUser(userName) if itm: @@ -478,8 +504,9 @@ userNamesList = msgList[1:] else: userNamesList = [] - userNames = ",".join( - u.rstrip(",") for u in userNamesList).split(",") + userNames = ",".join(u.rstrip(",") for u in userNamesList).split( + "," + ) for userName in userNames: itm = self.__findUser(userName) if itm: @@ -499,8 +526,7 @@ keys = msgList[2].split(",") else: keys = [] - for channel, key in zip_longest( - channels, keys, fillvalue=""): + for channel, key in zip_longest(channels, keys, fillvalue=""): self.__ircWidget.joinChannel(channel, key) elif cmd == "PART": sendData = False @@ -517,15 +543,13 @@ self.sendData.emit(msg) else: if self.__private: - self.sendData.emit( - "PRIVMSG " + self.__privatePartner + " :" + msg) + self.sendData.emit("PRIVMSG " + self.__privatePartner + " :" + msg) else: - self.sendData.emit( - "PRIVMSG " + self.__name + " :" + msg) + self.sendData.emit("PRIVMSG " + self.__name + " :" + msg) self.messageEdit.clear() self.unsetMarkerLine() - + def requestLeave(self): """ Public method to leave the channel. @@ -534,8 +558,9 @@ self, self.tr("Leave IRC channel"), self.tr( - """Do you really want to leave the IRC channel""" - """ <b>{0}</b>?""").format(self.__name)) + """Do you really want to leave the IRC channel""" """ <b>{0}</b>?""" + ).format(self.__name), + ) if ok: self.leaveChannel() @@ -544,90 +569,89 @@ Public slot to leave the channel. """ if not self.__private: - self.sendData.emit( - "PART " + self.__name + " :" + self.__partMessage) + self.sendData.emit("PART " + self.__name + " :" + self.__partMessage) self.channelClosed.emit(self.__name) - + def name(self): """ Public method to get the name of the channel. - + @return name of the channel (string) """ return self.__name - + def setName(self, name): """ Public method to set the name of the channel. - + @param name of the channel (string) """ self.__name = name - + def getUsersCount(self): """ Public method to get the users count of the channel. - + @return users count of the channel (integer) """ return self.usersList.count() - + def userName(self): """ Public method to get the nick name of the user. - + @return nick name of the user (string) """ return self.__userName - + def setUserName(self, name): """ Public method to set the user name for the channel. - + @param name user name for the channel (string) """ self.__userName = name - + def partMessage(self): """ Public method to get the part message. - + @return part message (string) """ return self.__partMessage - + def setPartMessage(self, message): """ Public method to set the part message. - + @param message message to be used for PART messages (string) """ self.__partMessage = message - + def setPrivate(self, private, partner=""): """ Public method to set the private chat mode. - + @param private flag indicating private chat mode (boolean) @param partner name of the partner user (string) """ self.__private = private self.__privatePartner = partner self.editTopicButton.setEnabled(private) - + def setPrivateInfo(self, infoText): """ Public method to set some info text for private chat mode. - + @param infoText info text to be shown (string) """ if self.__private: self.topicLabel.setText(infoText) - + def handleMessage(self, line): """ Public method to handle the message sent by the server. - + @param line server message (string) @return flag indicating, if the message was handled (boolean) """ @@ -635,13 +659,13 @@ match = patternRe.match(line) if match is not None and patternFunc(match): return True - + return False - + def __message(self, match): """ Private method to handle messages to the channel. - + @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ @@ -655,91 +679,91 @@ if itm and itm.isIgnored(): # user should be ignored return True - + if match.group(4).startswith("\x01"): return self.__handleCtcp(match) - + self.addMessage(senderName, match.group(4)) if self.__private and not self.topicLabel.text(): - self.setPrivateInfo( - "{0} - {1}".format(match.group(1), match.group(2))) + self.setPrivateInfo("{0} - {1}".format(match.group(1), match.group(2))) return True - + return False - + def addMessage(self, sender, msg): """ Public method to add a message from external. - + @param sender nick name of the sender (string) @param msg message received from sender (string) """ self.__appendMessage( '<font color="{0}">{2} <b><</b><font color="{1}">{3}</font>' - '<b>></b> {4}</font>'.format( + "<b>></b> {4}</font>".format( Preferences.getIrc("ChannelMessageColour"), Preferences.getIrc("NickColour"), - ircTimestamp(), sender, ircFilter(msg))) + ircTimestamp(), + sender, + ircFilter(msg), + ) + ) if Preferences.getIrc("ShowNotifications"): if Preferences.getIrc("NotifyMessage"): self.__ui.showNotification( - UI.PixmapCache.getPixmap("irc48"), - self.tr("Channel Message"), msg) + UI.PixmapCache.getPixmap("irc48"), self.tr("Channel Message"), msg + ) elif ( - Preferences.getIrc("NotifyNick") and - self.__userName.lower() in msg.lower() + Preferences.getIrc("NotifyNick") + and self.__userName.lower() in msg.lower() ): self.__ui.showNotification( - UI.PixmapCache.getPixmap("irc48"), - self.tr("Nick mentioned"), msg) - + UI.PixmapCache.getPixmap("irc48"), self.tr("Nick mentioned"), msg + ) + def addUsers(self, users): """ Public method to add users to the channel. - + @param users list of user names to add (list of string) """ for user in users: itm = self.__findUser(user) if itm is None: IrcUserItem(user, self.usersList) - + def __userJoin(self, match): """ Private method to handle a user joining the channel. - + @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ if match.group(3).lower() == self.__name.lower(): if self.__userName != match.group(1): IrcUserItem(match.group(1), self.usersList) - msg = self.tr( - "{0} has joined the channel {1} ({2}).").format( - match.group(1), self.__name, match.group(2)) - self.__addManagementMessage( - IrcChannelWidget.JoinIndicator, msg) + msg = self.tr("{0} has joined the channel {1} ({2}).").format( + match.group(1), self.__name, match.group(2) + ) + self.__addManagementMessage(IrcChannelWidget.JoinIndicator, msg) else: - msg = self.tr( - "You have joined the channel {0} ({1}).").format( - self.__name, match.group(2)) - self.__addManagementMessage( - IrcChannelWidget.JoinIndicator, msg) - if ( - Preferences.getIrc("ShowNotifications") and - Preferences.getIrc("NotifyJoinPart") + msg = self.tr("You have joined the channel {0} ({1}).").format( + self.__name, match.group(2) + ) + self.__addManagementMessage(IrcChannelWidget.JoinIndicator, msg) + if Preferences.getIrc("ShowNotifications") and Preferences.getIrc( + "NotifyJoinPart" ): self.__ui.showNotification( - UI.PixmapCache.getPixmap("irc48"), - self.tr("Join Channel"), msg) + UI.PixmapCache.getPixmap("irc48"), self.tr("Join Channel"), msg + ) return True - + return False - + def __userPart(self, match): """ Private method to handle a user leaving the channel. - + @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ @@ -748,33 +772,31 @@ self.usersList.takeItem(self.usersList.row(itm)) del itm if match.lastindex == 2: - msg = self.tr("{0} has left {1}.").format( - match.group(1), self.__name) + msg = self.tr("{0} has left {1}.").format(match.group(1), self.__name) nmsg = msg - self.__addManagementMessage( - IrcChannelWidget.LeaveIndicator, msg) + self.__addManagementMessage(IrcChannelWidget.LeaveIndicator, msg) else: msg = self.tr("{0} has left {1}: {2}.").format( - match.group(1), self.__name, ircFilter(match.group(3))) + match.group(1), self.__name, ircFilter(match.group(3)) + ) nmsg = self.tr("{0} has left {1}: {2}.").format( - match.group(1), self.__name, match.group(3)) - self.__addManagementMessage( - IrcChannelWidget.LeaveIndicator, msg) - if ( - Preferences.getIrc("ShowNotifications") and - Preferences.getIrc("NotifyJoinPart") + match.group(1), self.__name, match.group(3) + ) + self.__addManagementMessage(IrcChannelWidget.LeaveIndicator, msg) + if Preferences.getIrc("ShowNotifications") and Preferences.getIrc( + "NotifyJoinPart" ): self.__ui.showNotification( - UI.PixmapCache.getPixmap("irc48"), - self.tr("Leave Channel"), nmsg) + UI.PixmapCache.getPixmap("irc48"), self.tr("Leave Channel"), nmsg + ) return True - + return False - + def __userQuit(self, match): """ Private method to handle a user logging off the server. - + @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ @@ -783,30 +805,27 @@ self.usersList.takeItem(self.usersList.row(itm)) del itm if match.lastindex == 1: - msg = self.tr("{0} has quit {1}.").format( - match.group(1), self.__name) - self.__addManagementMessage( - IrcChannelWidget.MessageIndicator, msg) + msg = self.tr("{0} has quit {1}.").format(match.group(1), self.__name) + self.__addManagementMessage(IrcChannelWidget.MessageIndicator, msg) else: msg = self.tr("{0} has quit {1}: {2}.").format( - match.group(1), self.__name, ircFilter(match.group(2))) - self.__addManagementMessage( - IrcChannelWidget.MessageIndicator, msg) - if ( - Preferences.getIrc("ShowNotifications") and - Preferences.getIrc("NotifyJoinPart") + match.group(1), self.__name, ircFilter(match.group(2)) + ) + self.__addManagementMessage(IrcChannelWidget.MessageIndicator, msg) + if Preferences.getIrc("ShowNotifications") and Preferences.getIrc( + "NotifyJoinPart" ): self.__ui.showNotification( - UI.PixmapCache.getPixmap("irc48"), - self.tr("Quit"), msg) - + UI.PixmapCache.getPixmap("irc48"), self.tr("Quit"), msg + ) + # always return False for other channels and server to process return False - + def __userNickChange(self, match): """ Private method to handle a nickname change of a user. - + @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ @@ -816,22 +835,24 @@ if match.group(1) == self.__userName: self.__addManagementMessage( IrcChannelWidget.MessageIndicator, - self.tr("You are now known as {0}.").format( - match.group(2))) + self.tr("You are now known as {0}.").format(match.group(2)), + ) self.__userName = match.group(2) else: self.__addManagementMessage( IrcChannelWidget.MessageIndicator, self.tr("User {0} is now known as {1}.").format( - match.group(1), match.group(2))) - + match.group(1), match.group(2) + ), + ) + # always return False for other channels and server to process return False - + def __userList(self, match): """ Private method to handle the receipt of a list of users of the channel. - + @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ @@ -844,32 +865,32 @@ itm = IrcUserItem(userName, self.usersList) for privilege in userPrivileges: itm.changePrivilege(privilege) - + self.__setEditTopicButton() return True - + return False def __userAway(self, match): """ Private method to handle a topic change of the channel. - + @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ if match.group(1).lower() == self.__name.lower(): self.__addManagementMessage( self.tr("Away"), - self.tr("{0} is away: {1}").format( - match.group(2), match.group(3))) + self.tr("{0} is away: {1}").format(match.group(2), match.group(3)), + ) return True - + return False - + def __setTopic(self, match): """ Private method to handle a topic change of the channel. - + @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ @@ -877,16 +898,18 @@ self.topicLabel.setText(match.group(2)) self.__addManagementMessage( IrcChannelWidget.MessageIndicator, - ircFilter(self.tr('The channel topic is: "{0}".').format( - match.group(2)))) + ircFilter( + self.tr('The channel topic is: "{0}".').format(match.group(2)) + ), + ) return True - + return False - + def __topicCreated(self, match): """ Private method to handle a topic created message. - + @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ @@ -895,32 +918,35 @@ IrcChannelWidget.MessageIndicator, self.tr("The topic was set by {0} on {1}.").format( match.group(2), - QDateTime.fromSecsSinceEpoch(int(match.group(3))) - .toString("yyyy-MM-dd hh:mm"))) + QDateTime.fromSecsSinceEpoch(int(match.group(3))).toString( + "yyyy-MM-dd hh:mm" + ), + ), + ) return True - + return False - + def __channelUrl(self, match): """ Private method to handle a channel URL message. - + @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ if match.group(1).lower() == self.__name.lower(): self.__addManagementMessage( IrcChannelWidget.MessageIndicator, - ircFilter(self.tr("Channel URL: {0}").format( - match.group(2)))) + ircFilter(self.tr("Channel URL: {0}").format(match.group(2))), + ) return True - + return False - + def __channelModes(self, match): """ Private method to handle a message reporting the channel modes. - + @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ @@ -934,29 +960,28 @@ continue elif modeChar == "k": parameter = modesParameters.pop(0) - modes.append(self.tr( - "password protected ({0})").format(parameter)) + modes.append(self.tr("password protected ({0})").format(parameter)) elif modeChar == "l": parameter = modesParameters.pop(0) - modes.append(self.tr( - "limited to %n user(s)", "", int(parameter))) + modes.append(self.tr("limited to %n user(s)", "", int(parameter))) elif modeChar in modesDict: modes.append(modesDict[modeChar]) else: modes.append(modeChar) - + self.__addManagementMessage( IrcChannelWidget.MessageIndicator, - self.tr("Channel modes: {0}.").format(", ".join(modes))) - + self.tr("Channel modes: {0}.").format(", ".join(modes)), + ) + return True - + return False - + def __channelCreated(self, match): """ Private method to handle a channel created message. - + @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ @@ -964,16 +989,19 @@ self.__addManagementMessage( IrcChannelWidget.MessageIndicator, self.tr("This channel was created on {0}.").format( - QDateTime.fromSecsSinceEpoch(int(match.group(2))) - .toString("yyyy-MM-dd hh:mm"))) + QDateTime.fromSecsSinceEpoch(int(match.group(2))).toString( + "yyyy-MM-dd hh:mm" + ) + ), + ) return True - + return False - + def __updateChannelModes(self, match): """ Private method to handle a message reporting the channel modes. - + @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ @@ -1000,35 +1028,35 @@ ).format(nick) else: message = self.tr( - "{0} removes the 'anonymous' mode from the" - " channel.").format(nick) + "{0} removes the 'anonymous' mode from the" " channel." + ).format(nick) elif mode == "b": if isPlus: - message = self.tr( - "{0} sets a ban on {1}.").format( - nick, modesParameters.pop(0)) + message = self.tr("{0} sets a ban on {1}.").format( + nick, modesParameters.pop(0) + ) else: - message = self.tr( - "{0} removes the ban on {1}.").format( - nick, modesParameters.pop(0)) + message = self.tr("{0} removes the ban on {1}.").format( + nick, modesParameters.pop(0) + ) elif mode == "c": if isPlus: message = self.tr( - "{0} sets the channel mode to 'no colors" - " allowed'.").format(nick) + "{0} sets the channel mode to 'no colors" " allowed'." + ).format(nick) else: message = self.tr( - "{0} sets the channel mode to 'allow color" - " codes'.").format(nick) + "{0} sets the channel mode to 'allow color" " codes'." + ).format(nick) elif mode == "e": if isPlus: - message = self.tr( - "{0} sets a ban exception on {1}.").format( - nick, modesParameters.pop(0)) + message = self.tr("{0} sets a ban exception on {1}.").format( + nick, modesParameters.pop(0) + ) else: message = self.tr( - "{0} removes the ban exception on {1}.").format( - nick, modesParameters.pop(0)) + "{0} removes the ban exception on {1}." + ).format(nick, modesParameters.pop(0)) elif mode == "i": if isPlus: message = self.tr( @@ -1036,24 +1064,24 @@ ).format(nick) else: message = self.tr( - "{0} removes the 'invite only' mode from the" - " channel.").format(nick) + "{0} removes the 'invite only' mode from the" " channel." + ).format(nick) elif mode == "k": if isPlus: - message = self.tr( - "{0} sets the channel key to '{1}'.").format( - nick, modesParameters.pop(0)) + message = self.tr("{0} sets the channel key to '{1}'.").format( + nick, modesParameters.pop(0) + ) else: - message = self.tr( - "{0} removes the channel key.").format(nick) + message = self.tr("{0} removes the channel key.").format(nick) elif mode == "l": if isPlus: message = self.tr( - "{0} sets the channel limit to %n nick(s).", "", - int(modesParameters.pop(0))).format(nick) + "{0} sets the channel limit to %n nick(s).", + "", + int(modesParameters.pop(0)), + ).format(nick) else: - message = self.tr( - "{0} removes the channel limit.").format(nick) + message = self.tr("{0} removes the channel limit.").format(nick) elif mode == "m": if isPlus: message = self.tr( @@ -1067,11 +1095,13 @@ if isPlus: message = self.tr( "{0} sets the channel mode to 'no messages from" - " outside'.").format(nick) + " outside'." + ).format(nick) else: message = self.tr( "{0} sets the channel mode to 'allow messages" - " from outside'.").format(nick) + " from outside'." + ).format(nick) elif mode == "p": if isPlus: message = self.tr( @@ -1103,32 +1133,33 @@ ).format(nick) elif mode == "t": if isPlus: - message = self.tr( - "{0} switches on 'topic protection'.").format(nick) + message = self.tr("{0} switches on 'topic protection'.").format( + nick + ) else: message = self.tr( "{0} switches off 'topic protection'." ).format(nick) elif mode == "I": if isPlus: - message = self.tr( - "{0} sets invitation mask {1}.").format( - nick, modesParameters.pop(0)) + message = self.tr("{0} sets invitation mask {1}.").format( + nick, modesParameters.pop(0) + ) else: message = self.tr( - "{0} removes the invitation mask {1}.").format( - nick, modesParameters.pop(0)) - + "{0} removes the invitation mask {1}." + ).format(nick, modesParameters.pop(0)) + self.__addManagementMessage(self.tr("Mode"), message) - + return True - + return False - + def __setUserPrivilege(self, match): """ Private method to handle a change of user privileges for the channel. - + @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ @@ -1140,39 +1171,41 @@ self.__addManagementMessage( IrcChannelWidget.MessageIndicator, self.tr("{0} sets mode for {1}: {2}.").format( - match.group(1), match.group(4), match.group(3))) + match.group(1), match.group(4), match.group(3) + ), + ) return True - + return False - + def __ignore(self, match): """ Private method to handle a channel message we are not interested in. - + @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ if match.group(1).lower() == self.__name.lower(): return True - + return False - + def __help(self, match): """ Private method to handle a help message. - + @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ self.__addManagementMessage( - self.tr("Help"), - "{0} {1}".format(match.group(1), ircFilter(match.group(2)))) + self.tr("Help"), "{0} {1}".format(match.group(1), ircFilter(match.group(2))) + ) return True - + def __handleCtcp(self, match): """ Private method to handle a CTCP channel command. - + @param match reference to the match object @return flag indicating, if the message was handled (boolean) """ @@ -1192,48 +1225,54 @@ self.__addManagementMessage( self.tr("CTCP"), self.tr("Received Version request from {0}.").format( - match.group(1))) + match.group(1) + ), + ) self.sendCtcpReply.emit(match.group(1), "VERSION " + msg) elif ctcpRequest == "ping": self.__addManagementMessage( self.tr("CTCP"), self.tr( - "Received CTCP-PING request from {0}," - " sending answer.").format(match.group(1))) - self.sendCtcpReply.emit( - match.group(1), "PING {0}".format(ctcpArg)) + "Received CTCP-PING request from {0}," " sending answer." + ).format(match.group(1)), + ) + self.sendCtcpReply.emit(match.group(1), "PING {0}".format(ctcpArg)) elif ctcpRequest == "clientinfo": self.__addManagementMessage( self.tr("CTCP"), self.tr( - "Received CTCP-CLIENTINFO request from {0}," - " sending answer.").format(match.group(1))) + "Received CTCP-CLIENTINFO request from {0}," " sending answer." + ).format(match.group(1)), + ) self.sendCtcpReply.emit( - match.group(1), "CLIENTINFO CLIENTINFO PING VERSION") + match.group(1), "CLIENTINFO CLIENTINFO PING VERSION" + ) else: self.__addManagementMessage( self.tr("CTCP"), - self.tr("Received unknown CTCP-{0} request from {1}.") - .format(ctcpRequest, match.group(1))) + self.tr("Received unknown CTCP-{0} request from {1}.").format( + ctcpRequest, match.group(1) + ), + ) return True - + return False - + def setUserPrivilegePrefix(self, prefixes): """ Public method to set the user privilege to prefix mapping. - + @param prefixes dictionary with privilege as key and prefix as value """ self.__prefixToPrivilege = {} for privilege, prefix in prefixes.items(): if prefix: self.__prefixToPrivilege[prefix] = privilege - + def __findUser(self, name): """ Private method to find the user in the list of users. - + @param name user name to search for (string) @return reference to the list entry (QListWidgetItem) """ @@ -1241,13 +1280,13 @@ itm = self.usersList.item(row) if itm.name() == name: return itm - + return None - + def __extractPrivilege(self, name): """ Private method to extract the user privileges out of the name. - + @param name user name and prefixes (string) @return list of privileges and user name (list of string, string) """ @@ -1258,13 +1297,13 @@ name = name[1:] if name[0] == ",": name = name[1:] - + return privileges, name - + def __addManagementMessage(self, indicator, message): """ Private method to add a channel management message to the list. - + @param indicator indicator to be shown (string) @param message message to be shown (string) """ @@ -1276,35 +1315,38 @@ color = Preferences.getIrc("ChannelInfoColour") self.__appendMessage( '<font color="{0}">{1} <b>[</b>{2}<b>]</b> {3}</font>'.format( - color, ircTimestamp(), indicator, message)) - + color, ircTimestamp(), indicator, message + ) + ) + def __appendMessage(self, message): """ Private slot to append a message. - + @param message message to be appended (string) """ if ( - self.__hidden and - self.__markerLine == "" and - Preferences.getIrc("MarkPositionWhenHidden") + self.__hidden + and self.__markerLine == "" + and Preferences.getIrc("MarkPositionWhenHidden") ): self.setMarkerLine() self.messages.append(message) - + def setMarkerLine(self): """ Public method to draw a line to mark the current position. """ self.unsetMarkerLine() self.__markerLine = ( - '<span style=" color:{0}; background-color:{1};">{2}</span>' - .format(Preferences.getIrc("MarkerLineForegroundColour"), - Preferences.getIrc("MarkerLineBackgroundColour"), - self.tr('--- New From Here ---')) + '<span style=" color:{0}; background-color:{1};">{2}</span>'.format( + Preferences.getIrc("MarkerLineForegroundColour"), + Preferences.getIrc("MarkerLineBackgroundColour"), + self.tr("--- New From Here ---"), + ) ) self.messages.append(self.__markerLine) - + def unsetMarkerLine(self): """ Public method to remove the marker line. @@ -1320,20 +1362,20 @@ self.messages.setHtml(txt) self.__markerLine = "" self.messages.moveCursor(QTextCursor.MoveOperation.End) - + def __clearMessages(self): """ Private slot to clear the contents of the messages display. """ self.messages.clear() - + def __copyMessages(self): """ Private slot to copy the selection of the messages display to the clipboard. """ self.messages.copy() - + def __copyAllMessages(self): """ Private slot to copy the contents of the messages display to the @@ -1343,7 +1385,7 @@ if txt: cb = QApplication.clipboard() cb.setText(txt) - + def __cutAllMessages(self): """ Private slot to cut the contents of the messages display to the @@ -1354,7 +1396,7 @@ cb = QApplication.clipboard() cb.setText(txt) self.messages.clear() - + def __saveMessages(self): """ Private slot to save the contents of the messages display. @@ -1369,11 +1411,12 @@ self, self.tr("Save Messages"), "", - self.tr( - "HTML Files (*.{0});;Text Files (*.txt);;All Files (*)") - .format(htmlExtension), + self.tr("HTML Files (*.{0});;Text Files (*.txt);;All Files (*)").format( + htmlExtension + ), None, - EricFileDialog.DontConfirmOverwrite) + EricFileDialog.DontConfirmOverwrite, + ) if fname: fpath = pathlib.Path(fname) if not fpath.suffix: @@ -1384,17 +1427,20 @@ res = EricMessageBox.yesNo( self, self.tr("Save Messages"), - self.tr("<p>The file <b>{0}</b> already exists." - " Overwrite it?</p>").format(fpath), - icon=EricMessageBox.Warning) + self.tr( + "<p>The file <b>{0}</b> already exists." + " Overwrite it?</p>" + ).format(fpath), + icon=EricMessageBox.Warning, + ) if not res: return - + try: txt = ( self.messages.toHtml() - if fpath.suffix.lower() in [".htm", ".html"] else - self.messages.toPlainText() + if fpath.suffix.lower() in [".htm", ".html"] + else self.messages.toPlainText() ) with fpath.open("w", encoding="utf-8") as f: f.write(txt) @@ -1404,56 +1450,60 @@ self.tr("Error saving Messages"), self.tr( """<p>The messages contents could not be written""" - """ to <b>{0}</b></p><p>Reason: {1}</p>""") - .format(fpath, str(err))) - + """ to <b>{0}</b></p><p>Reason: {1}</p>""" + ).format(fpath, str(err)), + ) + def __initMessagesMenu(self): """ Private slot to initialize the context menu of the messages pane. """ self.__messagesMenu = QMenu(self) self.__copyMessagesAct = self.__messagesMenu.addAction( - UI.PixmapCache.getIcon("editCopy"), - self.tr("Copy"), self.__copyMessages) + UI.PixmapCache.getIcon("editCopy"), self.tr("Copy"), self.__copyMessages + ) self.__messagesMenu.addSeparator() self.__cutAllMessagesAct = self.__messagesMenu.addAction( - UI.PixmapCache.getIcon("editCut"), - self.tr("Cut all"), self.__cutAllMessages) + UI.PixmapCache.getIcon("editCut"), self.tr("Cut all"), self.__cutAllMessages + ) self.__copyAllMessagesAct = self.__messagesMenu.addAction( UI.PixmapCache.getIcon("editCopy"), - self.tr("Copy all"), self.__copyAllMessages) + self.tr("Copy all"), + self.__copyAllMessages, + ) self.__messagesMenu.addSeparator() self.__clearMessagesAct = self.__messagesMenu.addAction( - UI.PixmapCache.getIcon("editDelete"), - self.tr("Clear"), self.__clearMessages) + UI.PixmapCache.getIcon("editDelete"), self.tr("Clear"), self.__clearMessages + ) self.__messagesMenu.addSeparator() self.__saveMessagesAct = self.__messagesMenu.addAction( - UI.PixmapCache.getIcon("fileSave"), - self.tr("Save"), self.__saveMessages) + UI.PixmapCache.getIcon("fileSave"), self.tr("Save"), self.__saveMessages + ) self.__messagesMenu.addSeparator() self.__setMarkerMessagesAct = self.__messagesMenu.addAction( - self.tr("Mark Current Position"), self.setMarkerLine) + self.tr("Mark Current Position"), self.setMarkerLine + ) self.__unsetMarkerMessagesAct = self.__messagesMenu.addAction( - self.tr("Remove Position Marker"), - self.unsetMarkerLine) - + self.tr("Remove Position Marker"), self.unsetMarkerLine + ) + self.on_messages_copyAvailable(False) - + @pyqtSlot(bool) def on_messages_copyAvailable(self, yes): """ Private slot to react to text selection/deselection of the messages edit. - + @param yes flag signaling the availability of selected text (boolean) """ self.__copyMessagesAct.setEnabled(yes) - + @pyqtSlot(QPoint) def on_messages_customContextMenuRequested(self, pos): """ Private slot to show the context menu of the messages pane. - + @param pos the position of the mouse pointer (QPoint) """ enable = not self.messages.document().isEmpty() @@ -1463,108 +1513,120 @@ self.__setMarkerMessagesAct.setEnabled(self.__markerLine == "") self.__unsetMarkerMessagesAct.setEnabled(self.__markerLine != "") self.__messagesMenu.popup(self.messages.mapToGlobal(pos)) - + def __whoIs(self): """ Private slot to get information about the selected user. """ self.__whoIsNick = self.usersList.selectedItems()[0].text() self.sendData.emit("WHOIS " + self.__whoIsNick) - + def __openPrivateChat(self): """ Private slot to open a chat with the selected user. """ user = self.usersList.selectedItems()[0].text() self.openPrivateChat.emit(user) - + def __sendUserMessage(self): """ Private slot to send a private message to a specific user. """ from EricWidgets import EricTextInputDialog - + user = self.usersList.selectedItems()[0].text() ok, message = EricTextInputDialog.getText( - self, self.tr("Send Message"), + self, + self.tr("Send Message"), self.tr("Enter the message to be sent:"), - minimumWidth=400) + minimumWidth=400, + ) if ok and message: self.__processUserMessage("/MSG {0} {1}".format(user, message)) - + def __sendUserQuery(self): """ Private slot to send a query message to a specific user. """ from EricWidgets import EricTextInputDialog - + user = self.usersList.selectedItems()[0].text() ok, message = EricTextInputDialog.getText( - self, self.tr("Send Query"), + self, + self.tr("Send Query"), self.tr("Enter the message to be sent:"), - minimumWidth=400) + minimumWidth=400, + ) if ok and message: self.__processUserMessage("/QUERY {0} {1}".format(user, message)) - + def __sendUserNotice(self): """ Private slot to send a notice message to a specific user. """ from EricWidgets import EricTextInputDialog - + user = self.usersList.selectedItems()[0].text() ok, message = EricTextInputDialog.getText( - self, self.tr("Send Notice"), + self, + self.tr("Send Notice"), self.tr("Enter the message to be sent:"), - minimumWidth=400) + minimumWidth=400, + ) if ok and message: self.__processUserMessage("/NOTICE {0} {1}".format(user, message)) - + def __pingUser(self): """ Private slot to send a ping to a specific user. """ user = self.usersList.selectedItems()[0].text() self.__processUserMessage("/PING {0}".format(user)) - + def __ignoreUser(self): """ Private slot to ignore a specific user. """ user = self.usersList.selectedItems()[0].text() self.__processUserMessage("/IGNORE {0}".format(user)) - + def __initUsersMenu(self): """ Private slot to initialize the users list context menu. """ self.__usersMenu = QMenu(self) - self.__whoIsAct = self.__usersMenu.addAction( - self.tr("Who Is"), self.__whoIs) + self.__whoIsAct = self.__usersMenu.addAction(self.tr("Who Is"), self.__whoIs) self.__usersMenu.addSeparator() self.__privateChatAct = self.__usersMenu.addAction( - self.tr("Private Chat"), self.__openPrivateChat) + self.tr("Private Chat"), self.__openPrivateChat + ) self.__usersMenu.addSeparator() self.__sendUserMessageAct = self.__usersMenu.addAction( - self.tr("Send Message"), self.__sendUserMessage) + self.tr("Send Message"), self.__sendUserMessage + ) self.__sendUserQueryAct = self.__usersMenu.addAction( - self.tr("Send Query"), self.__sendUserQuery) + self.tr("Send Query"), self.__sendUserQuery + ) self.__sendUserNoticeAct = self.__usersMenu.addAction( - self.tr("Send Notice"), self.__sendUserNotice) + self.tr("Send Notice"), self.__sendUserNotice + ) self.__usersMenu.addSeparator() self.__pingUserAct = self.__usersMenu.addAction( - self.tr("Send Ping"), self.__pingUser) + self.tr("Send Ping"), self.__pingUser + ) self.__ignoreUserAct = self.__usersMenu.addAction( - self.tr("Ignore User"), self.__ignoreUser) + self.tr("Ignore User"), self.__ignoreUser + ) self.__usersMenu.addSeparator() self.__usersListRefreshAct = self.__usersMenu.addAction( - self.tr("Refresh"), self.__sendAutoWhoCommand) - + self.tr("Refresh"), self.__sendAutoWhoCommand + ) + @pyqtSlot(QPoint) def on_usersList_customContextMenuRequested(self, pos): """ Private slot to show the context menu of the users list. - + @param pos the position of the mouse pointer (QPoint) """ enable = len(self.usersList.selectedItems()) > 0 @@ -1572,38 +1634,42 @@ itm = self.usersList.itemAt(pos) if itm and enablePrivate: enablePrivate = itm.text().lower() not in [ - "chanserv", self.__userName.lower()] + "chanserv", + self.__userName.lower(), + ] self.__whoIsAct.setEnabled(enable) self.__privateChatAct.setEnabled(enablePrivate) self.__usersListRefreshAct.setEnabled( - self.usersList.count() <= Preferences.getIrc("AutoUserInfoMax")) + self.usersList.count() <= Preferences.getIrc("AutoUserInfoMax") + ) self.__usersMenu.popup(self.usersList.mapToGlobal(pos)) - + def hideEvent(self, evt): """ Protected method handling hide events. - + @param evt reference to the hide event (QHideEvent) """ self.__hidden = True - + def showEvent(self, evt): """ Protected method handling show events. - + @param evt reference to the show event (QShowEvent) """ self.__hidden = False - + def initAutoWho(self): """ Public method to initialize the Auto Who system. """ if Preferences.getIrc("AutoUserInfoLookup"): self.__autoWhoTimer.setInterval( - Preferences.getIrc("AutoUserInfoInterval") * 1000) + Preferences.getIrc("AutoUserInfoInterval") * 1000 + ) self.__autoWhoTimer.start() - + @pyqtSlot() def __sendAutoWhoCommand(self): """ @@ -1612,12 +1678,12 @@ if self.usersList.count() <= Preferences.getIrc("AutoUserInfoMax"): self.__autoWhoRequested = True self.sendData.emit(self.__autoWhoTemplate.format(self.__name)) - + def __autoWhoEntry(self, match): """ Private method to handle a WHO entry returned by the server as requested automatically. - + @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ @@ -1628,13 +1694,13 @@ if itm: itm.parseWhoFlags(match.group(2)) return True - + return False - + def __whoEnd(self, match): """ Private method to handle the end of the WHO list. - + @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ @@ -1645,17 +1711,17 @@ else: self.__addManagementMessage( self.tr("Who"), - self.tr("End of WHO list for {0}.").format( - match.group(1))) + self.tr("End of WHO list for {0}.").format(match.group(1)), + ) return True - + return False - + def __whoEntry(self, match): """ Private method to handle a WHO entry returned by the server as requested manually. - + @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ @@ -1666,23 +1732,21 @@ # group(5) user flags # group(6) real name if match.group(1).lower() == self.__name.lower(): - away = ( - self.tr(" (Away)") - if match.group(5).startswith("G") else "" - ) + away = self.tr(" (Away)") if match.group(5).startswith("G") else "" self.__addManagementMessage( self.tr("Who"), self.tr("{0} is {1}@{2} ({3}){4}").format( - match.group(4), match.group(2), match.group(3), - match.group(6), away)) + match.group(4), match.group(2), match.group(3), match.group(6), away + ), + ) return True - + return False - + def __whoIsUser(self, match): """ Private method to handle the WHOIS user reply. - + @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ @@ -1695,15 +1759,17 @@ self.__addManagementMessage( self.tr("Whois"), self.tr("{0} is {1}@{2} ({3}).").format( - match.group(1), match.group(2), match.group(3), realName)) + match.group(1), match.group(2), match.group(3), realName + ), + ) return True - + return False - + def __whoIsChannels(self, match): """ Private method to handle the WHOIS channels reply. - + @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ @@ -1716,15 +1782,14 @@ halfopChannels = [] ownerChannels = [] adminChannels = [] - + # generate the list of channels the user is in channelList = match.group(2).split() for channel in channelList: if channel.startswith(("*", "&")): adminChannels.append(channel[1:]) - elif ( - channel.startswith(("!", "~")) and - self.__ircWidget.isChannelName(channel[1:]) + elif channel.startswith(("!", "~")) and self.__ircWidget.isChannelName( + channel[1:] ): ownerChannels.append(channel[1:]) elif channel.startswith("@+"): @@ -1737,46 +1802,58 @@ voiceChannels.append(channel[1:]) else: userChannels.append(channel) - + # show messages if userChannels: self.__addManagementMessage( self.tr("Whois"), self.tr("{0} is a user on channels: {1}").format( - match.group(1), " ".join(userChannels))) + match.group(1), " ".join(userChannels) + ), + ) if voiceChannels: self.__addManagementMessage( self.tr("Whois"), self.tr("{0} has voice on channels: {1}").format( - match.group(1), " ".join(voiceChannels))) + match.group(1), " ".join(voiceChannels) + ), + ) if halfopChannels: self.__addManagementMessage( self.tr("Whois"), self.tr("{0} is a halfop on channels: {1}").format( - match.group(1), " ".join(halfopChannels))) + match.group(1), " ".join(halfopChannels) + ), + ) if opChannels: self.__addManagementMessage( self.tr("Whois"), self.tr("{0} is an operator on channels: {1}").format( - match.group(1), " ".join(opChannels))) + match.group(1), " ".join(opChannels) + ), + ) if ownerChannels: self.__addManagementMessage( self.tr("Whois"), self.tr("{0} is owner of channels: {1}").format( - match.group(1), " ".join(ownerChannels))) + match.group(1), " ".join(ownerChannels) + ), + ) if adminChannels: self.__addManagementMessage( self.tr("Whois"), self.tr("{0} is admin on channels: {1}").format( - match.group(1), " ".join(adminChannels))) + match.group(1), " ".join(adminChannels) + ), + ) return True - + return False - + def __whoIsServer(self, match): """ Private method to handle the WHOIS server reply. - + @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ @@ -1787,15 +1864,17 @@ self.__addManagementMessage( self.tr("Whois"), self.tr("{0} is online via {1} ({2}).").format( - match.group(1), match.group(2), match.group(3))) + match.group(1), match.group(2), match.group(3) + ), + ) return True - + return False - + def __whoIsOperator(self, match): """ Private method to handle the WHOIS operator reply. - + @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ @@ -1805,20 +1884,20 @@ if match.group(2).lower().startswith("is an irc operator"): self.__addManagementMessage( self.tr("Whois"), - self.tr("{0} is an IRC Operator.").format( - match.group(1))) + self.tr("{0} is an IRC Operator.").format(match.group(1)), + ) else: self.__addManagementMessage( - self.tr("Whois"), - "{0} {1}".format(match.group(1), match.group(2))) + self.tr("Whois"), "{0} {1}".format(match.group(1), match.group(2)) + ) return True - + return False - + def __whoIsIdle(self, match): """ Private method to handle the WHOIS idle reply. - + @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ @@ -1830,11 +1909,11 @@ minutes = seconds // 60 hours = minutes // 60 days = hours // 24 - + signonTimestamp = int(match.group(3)) signonTime = QDateTime() signonTime.setTime_t(signonTimestamp) - + if days: daysString = self.tr("%n day(s)", "", days) hoursString = self.tr("%n hour(s)", "", hours) @@ -1846,9 +1925,15 @@ "{0} has been idle for {1}, {2}, {3}, and {4}.", "{0} = name of person, {1} = (x days)," " {2} = (x hours), {3} = (x minutes)," - " {4} = (x seconds)").format( - match.group(1), daysString, hoursString, minutesString, - secondsString)) + " {4} = (x seconds)", + ).format( + match.group(1), + daysString, + hoursString, + minutesString, + secondsString, + ), + ) elif hours: hoursString = self.tr("%n hour(s)", "", hours) minutesString = self.tr("%n minute(s)", "", minutes) @@ -1858,9 +1943,9 @@ self.tr( "{0} has been idle for {1}, {2}, and {3}.", "{0} = name of person, {1} = (x hours), " - "{2} = (x minutes), {3} = (x seconds)") - .format(match.group(1), hoursString, minutesString, - secondsString)) + "{2} = (x minutes), {3} = (x seconds)", + ).format(match.group(1), hoursString, minutesString, secondsString), + ) elif minutes: minutesString = self.tr("%n minute(s)", "", minutes) secondsString = self.tr("%n second(s)", "", seconds) @@ -1868,30 +1953,32 @@ self.tr("Whois"), self.tr( "{0} has been idle for {1} and {2}.", - "{0} = name of person, {1} = (x minutes), " - "{3} = (x seconds)") - .format(match.group(1), minutesString, secondsString)) + "{0} = name of person, {1} = (x minutes), " "{3} = (x seconds)", + ).format(match.group(1), minutesString, secondsString), + ) else: self.__addManagementMessage( self.tr("Whois"), - self.tr( - "{0} has been idle for %n second(s).", "", - seconds).format(match.group(1))) - + self.tr("{0} has been idle for %n second(s).", "", seconds).format( + match.group(1) + ), + ) + if not signonTime.isNull(): self.__addManagementMessage( self.tr("Whois"), self.tr("{0} has been online since {1}.").format( - match.group(1), - signonTime.toString("yyyy-MM-dd, hh:mm:ss"))) + match.group(1), signonTime.toString("yyyy-MM-dd, hh:mm:ss") + ), + ) return True - + return False - + def __whoIsEnd(self, match): """ Private method to handle the end of WHOIS reply. - + @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ @@ -1901,16 +1988,16 @@ self.__whoIsNick = "" self.__addManagementMessage( self.tr("Whois"), - self.tr("End of WHOIS list for {0}.").format( - match.group(1))) + self.tr("End of WHOIS list for {0}.").format(match.group(1)), + ) return True - + return False - + def __whoIsIdentify(self, match): """ Private method to handle the WHOIS identify and identified replies. - + @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ @@ -1919,16 +2006,16 @@ if match.group(1) == self.__whoIsNick: self.__addManagementMessage( self.tr("Whois"), - self.tr("{0} is an identified user.").format( - match.group(1))) + self.tr("{0} is an identified user.").format(match.group(1)), + ) return True - + return False - + def __whoIsHelper(self, match): """ Private method to handle the WHOIS helper reply. - + @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ @@ -1937,16 +2024,16 @@ if match.group(1) == self.__whoIsNick: self.__addManagementMessage( self.tr("Whois"), - self.tr("{0} is available for help.").format( - match.group(1))) + self.tr("{0} is available for help.").format(match.group(1)), + ) return True - + return False - + def __whoIsAccount(self, match): """ Private method to handle the WHOIS account reply. - + @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ @@ -1956,15 +2043,17 @@ self.__addManagementMessage( self.tr("Whois"), self.tr("{0} is logged in as {1}.").format( - match.group(1), match.group(2))) + match.group(1), match.group(2) + ), + ) return True - + return False - + def __whoIsActually(self, match): """ Private method to handle the WHOIS actually reply. - + @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ @@ -1974,17 +2063,18 @@ if match.group(1) == self.__whoIsNick: self.__addManagementMessage( self.tr("Whois"), - self.tr( - "{0} is actually using the host {1} (IP: {2}).").format( - match.group(1), match.group(2), match.group(3))) + self.tr("{0} is actually using the host {1} (IP: {2}).").format( + match.group(1), match.group(2), match.group(3) + ), + ) return True - + return False - + def __whoIsSecure(self, match): """ Private method to handle the WHOIS secure reply. - + @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ @@ -1992,16 +2082,16 @@ if match.group(1) == self.__whoIsNick: self.__addManagementMessage( self.tr("Whois"), - self.tr("{0} is using a secure connection.").format( - match.group(1))) + self.tr("{0} is using a secure connection.").format(match.group(1)), + ) return True - + return False - + def __whoIsConnection(self, match): """ Private method to handle the WHOIS connection reply. - + @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ @@ -2012,11 +2102,13 @@ self.__addManagementMessage( self.tr("Whois"), self.tr("{0} is connecting from {1} (IP: {2}).").format( - match.group(1), match.group(2), match.group(3))) + match.group(1), match.group(2), match.group(3) + ), + ) return True - + return False - + def __setEditTopicButton(self): """ Private method to set the visibility of the Edit Topic button. @@ -2024,7 +2116,7 @@ itm = self.__findUser(self.__userName) if itm: self.editTopicButton.setVisible(itm.canChangeTopic()) - + @pyqtSlot() def on_editTopicButton_clicked(self): """ @@ -2035,16 +2127,16 @@ self.tr("Edit Channel Topic"), self.tr("Enter the topic for this channel:"), QLineEdit.EchoMode.Normal, - self.topicLabel.text()) + self.topicLabel.text(), + ) if ok and topic != "": - self.sendData.emit("TOPIC {0} :{1}".format( - self.__name, topic)) - + self.sendData.emit("TOPIC {0} :{1}".format(self.__name, topic)) + @pyqtSlot(QUrl) def on_messages_anchorClicked(self, url): """ Private slot to open links in the default browser. - + @param url URL to be opened (QUrl) """ QDesktopServices.openUrl(url)