Sun, 09 Dec 2012 16:18:17 +0100
Added a specialized line edit for entering IRC messages, which supports a non-persistent edit history.
Improved the "private IRC chat" support.
--- a/Network/IRC/IrcChannelWidget.py Sun Dec 09 13:01:15 2012 +0100 +++ b/Network/IRC/IrcChannelWidget.py Sun Dec 09 16:18:17 2012 +0100 @@ -205,7 +205,8 @@ self.__patterns = [ # :foo_!n=foo@foohost.bar.net PRIVMSG #eric-ide :some long message - (re.compile(r":([^!]+).*\sPRIVMSG\s([^ ]+)\s:(.*)"), self.__message), + # :foo_!n=foo@foohost.bar.net PRIVMSG bar_ :some long 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), # :foo_!n=foo@foohost.bar.net PART #eric-ide :part message @@ -299,7 +300,8 @@ self.trUtf8("""Do you really want to leave the IRC channel <b>{0}</b>?""")\ .format(self.__name)) if ok: - self.sendData.emit("PART " + self.__name + " :" + self.__partMessage) + if not self.__private: + self.sendData.emit("PART " + self.__name + " :" + self.__partMessage) self.channelClosed.emit(self.__name) def name(self): @@ -368,6 +370,15 @@ self.__private = private self.__privatePartner = partner + 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. @@ -390,27 +401,40 @@ @param match match object that matched the pattern @return flag indicating whether the message was handled (boolean) """ - if match.group(2).lower() == self.__name: - msg = ircFilter(match.group(3)) - self.__appendMessage( - '<font color="{0}">{2} <b><</b><font color="{1}">{3}</font>' - '<b>></b> {4}</font>'.format( - Preferences.getIrc("ChannelMessageColour"), - Preferences.getIrc("NickColour"), - ircTimestamp(), match.group(1), - msg)) - if Preferences.getIrc("ShowNotifications"): - if Preferences.getIrc("NotifyMessage"): - self.__ui.showNotification(UI.PixmapCache.getPixmap("irc48.png"), - self.trUtf8("Channel Message"), msg) - elif Preferences.getIrc("NotifyNick") and \ - self.__userName.lower() in msg.lower(): - self.__ui.showNotification(UI.PixmapCache.getPixmap("irc48.png"), - self.trUtf8("Nick mentioned"), msg) + # group(1) sender user name + # group(2) sender user@host + # group(3) target nick + # group(4) message + if match.group(3).lower() == self.__name: + self.addMessage(match.group(1), match.group(4)) + if self.__private and not self.topicLabel.text(): + 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( + Preferences.getIrc("ChannelMessageColour"), + Preferences.getIrc("NickColour"), + ircTimestamp(), sender, ircFilter(msg))) + if Preferences.getIrc("ShowNotifications"): + if Preferences.getIrc("NotifyMessage"): + self.__ui.showNotification(UI.PixmapCache.getPixmap("irc48.png"), + self.trUtf8("Channel Message"), msg) + elif Preferences.getIrc("NotifyNick") and \ + self.__userName.lower() in msg.lower(): + self.__ui.showNotification(UI.PixmapCache.getPixmap("irc48.png"), + self.trUtf8("Nick mentioned"), msg) + def addUsers(self, users): """ Public method to add users to the channel.
--- a/Network/IRC/IrcChannelWidget.ui Sun Dec 09 13:01:15 2012 +0100 +++ b/Network/IRC/IrcChannelWidget.ui Sun Dec 09 16:18:17 2012 +0100 @@ -69,7 +69,7 @@ </widget> </item> <item> - <widget class="E5ClearableLineEdit" name="messageEdit"> + <widget class="IrcMessageEdit" name="messageEdit"> <property name="toolTip"> <string>Enter a message, send by pressing Return or Enter</string> </property> @@ -82,9 +82,9 @@ </widget> <customwidgets> <customwidget> - <class>E5ClearableLineEdit</class> + <class>IrcMessageEdit</class> <extends>QLineEdit</extends> - <header>E5Gui/E5LineEdit.h</header> + <header>Network/IRC/IrcMessageEdit.h</header> </customwidget> </customwidgets> <tabstops>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Network/IRC/IrcMessageEdit.py Sun Dec 09 16:18:17 2012 +0100 @@ -0,0 +1,126 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2012 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a specialized line edit for entering IRC messages. +""" + +from PyQt4.QtCore import Qt + +from E5Gui.E5LineEdit import E5LineEdit, E5ClearableLineEdit + + +class IrcMessageEdit(E5ClearableLineEdit): + """ + Class implementing a specialized line edit for entering IRC messages. + """ + MaxHistory = 100 + + def __init__(self, parent=None, inactiveText="", side=E5LineEdit.RightSide): + """ + Constructor + + @param parent reference to the parent widget (QWidget) + @keyparam inactiveText text to be shown on inactivity (string) + @keyparam side side the clear button should be shown at (E5LineEdit.RightSide, + E5LineEdit.LeftSide) + """ + super().__init__(parent, inactiveText, side) + + self.__historyList = [""] # initialize with one empty line + self.__historyLine = 0 + + def setText(self, text): + """ + Public method to set the text. + + Note: This reimplementation ensures, that the cursor is at the end of the text. + + @param text text to be set (string) + """ + super().setText(text) + self.setCursorPosition(len(text)) + + def keyPressEvent(self, evt): + """ + Protected method implementing special key handling. + + @param evt reference to the event (QKeyEvent) + """ + key = evt.key() + if key == Qt.Key_Up: + self.__getHistory(True) + return + elif key == Qt.Key_Down: + self.__getHistory(False) + return + elif key in [Qt.Key_Return, Qt.Key_Enter]: + if self.text(): + self.__addHistory(self.text()) + elif evt.text() == chr(21): + # ^U: clear the text + self.setText("") + + super().keyPressEvent(evt) + + def wheelEvent(self, evt): + """ + Protected slot to support wheel events. + + @param reference to the wheel event (QWheelEvent) + """ + if evt.delta() > 0: + self.__getHistory(True) + elif evt.delta() < 0: + self.__getHistory(False) + + super().wheelEvent(evt) + + def __addHistory(self, txt): + """ + Private method to add an entry to the history. + + @param txt text to be added to the history (string) + """ + # Only add the entry, if it is not the same as last time + if len(self.__historyList) == 1 or \ + (len(self.__historyList) > 1 and self.__historyList[1] != txt): + # Replace empty first entry and add new empty first entry + self.__historyList[0] = txt + self.__historyList.insert(0, "") + # Keep history below the defined limit + del self.__historyList[IrcMessageEdit.MaxHistory:] + + self.__historyLine = 0 + + def __getHistory(self, up): + """ + Private method to move in the history. + + @param up flag indicating the direction (boolean) + """ + # preserve the current text, if it is not empty + if self.text(): + self.__historyList[self.__historyLine] = self.text() + + if up: + self.__historyLine += 1 + # If the position was moved past the end of the history, go to the last entry + if self.__historyLine == len(self.__historyList): + self.__historyLine -= 1 + return + else: + # If the position is at the top of the history, arrow-down shall add the text + # to the history and clear the line edit for new input + if self.__historyLine == 0: + if self.text(): + self.__addHistory(self.text()) + self.setText("") + else: + # If the position is not at the top of the history, decrement it + self.__historyLine -= 1 + + # replace the text of the line edit with the selected history entry + self.setText(self.__historyList[self.__historyLine])
--- a/Network/IRC/IrcWidget.py Sun Dec 09 13:01:15 2012 +0100 +++ b/Network/IRC/IrcWidget.py Sun Dec 09 16:18:17 2012 +0100 @@ -77,6 +77,8 @@ self.__socket = None self.__patterns = [ + # :foo_!n=foo@foohost.bar.net PRIVMSG bar_ :some long message + (re.compile(r":([^!]+)!([^ ]+)\sPRIVMSG\s([^ ]+)\s:(.*)"), self.__query), # :foo.bar.net COMMAND some message (re.compile(r""":([^ ]+)\s+([A-Z]+)\s+(.+)"""), self.__handleNamedMessage), # :foo.bar.net 123 * :info @@ -267,6 +269,25 @@ self.__leaveButton.setEnabled(True) self.channelsWidget.setTabsClosable(True) + def __query(self, match): + """ + Private method to handle a new private connection. + + @param reference to the match object + @return flag indicating, if the message was handled (boolean) + """ + # group(1) sender user name + # group(2) sender user@host + # group(3) target nick + # group(4) message + self.__openPrivate(match.group(1)) + # the above call sets the new channel as the current widget + channel = self.channelsWidget.currentWidget() + channel.addMessage(match.group(1), match.group(4)) + channel.setPrivateInfo("{0} - {1}".format(match.group(1), match.group(2))) + + return True + @pyqtSlot(str) def __openPrivate(self, name): """
--- a/eric5.e4p Sun Dec 09 13:01:15 2012 +0100 +++ b/eric5.e4p Sun Dec 09 16:18:17 2012 +0100 @@ -1067,6 +1067,7 @@ <Source>Network/IRC/IrcChannelEditDialog.py</Source> <Source>Network/IRC/IrcServerEditDialog.py</Source> <Source>Network/IRC/IrcIdentitiesEditDialog.py</Source> + <Source>Network/IRC/IrcMessageEdit.py</Source> </Sources> <Forms> <Form>PyUnit/UnittestDialog.ui</Form>