2250:810e9c7b61e3 | 2252:1fc32bd13be3 |
---|---|
7 Module implementing the IRC channel widget. | 7 Module implementing the IRC channel widget. |
8 """ | 8 """ |
9 | 9 |
10 import re | 10 import re |
11 | 11 |
12 from PyQt4.QtCore import pyqtSlot, pyqtSignal, QDateTime, QPoint | 12 from PyQt4.QtCore import pyqtSlot, pyqtSignal, QDateTime, QPoint, QFileInfo |
13 from PyQt4.QtGui import QWidget, QListWidgetItem, QIcon, QPainter, QMenu | 13 from PyQt4.QtGui import QWidget, QListWidgetItem, QIcon, QPainter, QMenu, QApplication |
14 | 14 |
15 from E5Gui import E5MessageBox | 15 from E5Gui import E5MessageBox, E5FileDialog |
16 from E5Gui.E5Application import e5App | 16 from E5Gui.E5Application import e5App |
17 | 17 |
18 from .Ui_IrcChannelWidget import Ui_IrcChannelWidget | 18 from .Ui_IrcChannelWidget import Ui_IrcChannelWidget |
19 | 19 |
20 from .IrcUtilities import ircFilter, ircTimestamp, getChannelModesDict | 20 from .IrcUtilities import ircFilter, ircTimestamp, getChannelModesDict |
140 """ | 140 """ |
141 Class implementing the IRC channel widget. | 141 Class implementing the IRC channel widget. |
142 | 142 |
143 @signal sendData(str) emitted to send a message to the channel | 143 @signal sendData(str) emitted to send a message to the channel |
144 @signal channelClosed(str) emitted after the user has left the channel | 144 @signal channelClosed(str) emitted after the user has left the channel |
145 @signal openPrivateChat(str) emitted to open a "channel" for private messages | |
145 """ | 146 """ |
146 sendData = pyqtSignal(str) | 147 sendData = pyqtSignal(str) |
147 channelClosed = pyqtSignal(str) | 148 channelClosed = pyqtSignal(str) |
149 openPrivateChat = pyqtSignal(str) | |
148 | 150 |
149 UrlRe = re.compile(r"""((?:http|ftp|https):\/\/[\w\-_]+(?:\.[\w\-_]+)+""" | 151 UrlRe = re.compile(r"""((?:http|ftp|https):\/\/[\w\-_]+(?:\.[\w\-_]+)+""" |
150 r"""(?:[\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?)""") | 152 r"""(?:[\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?)""") |
151 | 153 |
152 JoinIndicator = "-->" | 154 JoinIndicator = "-->" |
161 # H The user is not away. | 163 # H The user is not away. |
162 # G The user is set away. | 164 # G The user is set away. |
163 # * The user is an IRC operator. | 165 # * The user is an IRC operator. |
164 # @ The user is a channel op in the channel listed in the first field. | 166 # @ The user is a channel op in the channel listed in the first field. |
165 # + The user is voiced in the channel listed. | 167 # + The user is voiced in the channel listed. |
166 # TODO: add context menu to messages pane with these entries: | |
167 # Copy | |
168 # Copy Link Location | |
169 # Copy All | |
170 # Clear | |
171 # Save | |
172 # Remember Position | |
173 # TODO: Remember current position with <hr/> when widget is invisible | |
174 # TODO: Check away indication in the user list | 168 # TODO: Check away indication in the user list |
175 def __init__(self, parent=None): | 169 def __init__(self, parent=None): |
176 """ | 170 """ |
177 Constructor | 171 Constructor |
178 | 172 |
182 self.setupUi(self) | 176 self.setupUi(self) |
183 | 177 |
184 self.__ui = e5App().getObject("UserInterface") | 178 self.__ui = e5App().getObject("UserInterface") |
185 | 179 |
186 self.__initMessagesMenu() | 180 self.__initMessagesMenu() |
181 self.__initUsersMenu() | |
187 | 182 |
188 self.__name = "" | 183 self.__name = "" |
189 self.__userName = "" | 184 self.__userName = "" |
190 self.__partMessage = "" | 185 self.__partMessage = "" |
191 self.__prefixToPrivilege = {} | 186 self.__prefixToPrivilege = {} |
187 self.__private = False | |
188 self.__privatePartner = "" | |
192 | 189 |
193 self.__markerLine = "" | 190 self.__markerLine = "" |
191 self.__hidden = True | |
194 | 192 |
195 self.__patterns = [ | 193 self.__patterns = [ |
196 # :foo_!n=foo@foohost.bar.net PRIVMSG #eric-ide :some long message | 194 # :foo_!n=foo@foohost.bar.net PRIVMSG #eric-ide :some long message |
197 (re.compile(r":([^!]+).*\sPRIVMSG\s([^ ]+)\s:(.*)"), self.__message), | 195 (re.compile(r":([^!]+).*\sPRIVMSG\s([^ ]+)\s:(.*)"), self.__message), |
198 # :foo_!n=foo@foohost.bar.net JOIN :#eric-ide | 196 # :foo_!n=foo@foohost.bar.net JOIN :#eric-ide |
209 # :foo_!n=foo@foohost.bar.net NICK :newnick | 207 # :foo_!n=foo@foohost.bar.net NICK :newnick |
210 (re.compile(r":([^!]+).*\sNICK\s:(.*)"), self.__userNickChange), | 208 (re.compile(r":([^!]+).*\sNICK\s:(.*)"), self.__userNickChange), |
211 # :barty!n=foo@foohost.bar.net MODE #eric-ide +o foo_ | 209 # :barty!n=foo@foohost.bar.net MODE #eric-ide +o foo_ |
212 (re.compile(r":([^!]+).*\sMODE\s([^ ]+)\s([^ ]+)\s([^ ]+).*"), | 210 (re.compile(r":([^!]+).*\sMODE\s([^ ]+)\s([^ ]+)\s([^ ]+).*"), |
213 self.__setUserPrivilege), | 211 self.__setUserPrivilege), |
212 # :sturgeon.freenode.net 301 foo_ bar :Gone away for now | |
213 (re.compile(r":.*\s301\s([^ ]+)\s([^ ]+)\s:(.+)"), self.__userAway), | |
214 # :zelazny.freenode.net 324 foo_ #eric-ide +cnt | 214 # :zelazny.freenode.net 324 foo_ #eric-ide +cnt |
215 (re.compile(r":.*\s324\s.*\s([^ ]+)\s(.+)"), self.__channelModes), | 215 (re.compile(r":.*\s324\s.*\s([^ ]+)\s(.+)"), self.__channelModes), |
216 # :zelazny.freenode.net 328 foo_ #eric-ide :http://www.buggeroff.com/ | 216 # :zelazny.freenode.net 328 foo_ #eric-ide :http://www.buggeroff.com/ |
217 (re.compile(r":.*\s328\s.*\s([^ ]+)\s:(.+)"), self.__channelUrl), | 217 (re.compile(r":.*\s328\s.*\s([^ ]+)\s:(.+)"), self.__channelUrl), |
218 # :zelazny.freenode.net 329 foo_ #eric-ide 1353001005 | 218 # :zelazny.freenode.net 329 foo_ #eric-ide 1353001005 |
223 (re.compile(r":.*\s333\s.*\s([^ ]+)\s([^ ]+)\s(\d+)"), self.__topicCreated), | 223 (re.compile(r":.*\s333\s.*\s([^ ]+)\s([^ ]+)\s(\d+)"), self.__topicCreated), |
224 # :zelazny.freenode.net 353 foo_ @ #eric-ide :@user1 +user2 user3 | 224 # :zelazny.freenode.net 353 foo_ @ #eric-ide :@user1 +user2 user3 |
225 (re.compile(r":.*\s353\s.*\s.\s([^ ]+)\s:(.*)"), self.__userList), | 225 (re.compile(r":.*\s353\s.*\s.\s([^ ]+)\s:(.*)"), self.__userList), |
226 # :zelazny.freenode.net 366 foo_ #eric-ide :End of /NAMES list. | 226 # :zelazny.freenode.net 366 foo_ #eric-ide :End of /NAMES list. |
227 (re.compile(r":.*\s366\s.*\s([^ ]+)\s:(.*)"), self.__ignore), | 227 (re.compile(r":.*\s366\s.*\s([^ ]+)\s:(.*)"), self.__ignore), |
228 # :sturgeon.freenode.net 704 foo_ index :Help topics available to users: | |
229 (re.compile(r":.*\s70[456]\s[^ ]+\s([^ ]+)\s:(.*)"), self.__help), | |
228 ] | 230 ] |
229 | 231 |
230 @pyqtSlot() | 232 @pyqtSlot() |
231 def on_messageEdit_returnPressed(self): | 233 def on_messageEdit_returnPressed(self): |
232 """ | 234 """ |
238 '<font color="{0}">{2} <b><</b><font color="{1}">{3}</font>' | 240 '<font color="{0}">{2} <b><</b><font color="{1}">{3}</font>' |
239 '<b>></b> {4}</font>'.format( | 241 '<b>></b> {4}</font>'.format( |
240 Preferences.getIrc("ChannelMessageColour"), | 242 Preferences.getIrc("ChannelMessageColour"), |
241 Preferences.getIrc("OwnNickColour"), | 243 Preferences.getIrc("OwnNickColour"), |
242 ircTimestamp(), self.__userName, Utilities.html_encode(msg))) | 244 ircTimestamp(), self.__userName, Utilities.html_encode(msg))) |
243 self.sendData.emit("PRIVMSG " + self.__name + " :" + msg) | 245 if msg.startswith("/"): |
246 if self.__private: | |
247 E5MessageBox.information(self, | |
248 self.trUtf8("Send Message"), | |
249 self.trUtf8("""Messages starting with a '/' are not allowed""" | |
250 """ in private chats.""")) | |
251 else: | |
252 msgList = msg.split(None, 1) | |
253 cmd = msgList[0][1:].upper() | |
254 if cmd == "MSG": | |
255 cmd = "PRIVMSG" | |
256 msgList[0] = cmd | |
257 self.sendData.emit(" ".join(msgList)) | |
258 else: | |
259 if self.__private: | |
260 self.sendData.emit("PRIVMSG " + self.__privatePartner + " :" + msg) | |
261 else: | |
262 self.sendData.emit("PRIVMSG " + self.__name + " :" + msg) | |
244 self.messageEdit.clear() | 263 self.messageEdit.clear() |
245 | 264 |
246 def requestLeave(self): | 265 def requestLeave(self): |
247 """ | 266 """ |
248 Public method to leave the channel. | 267 Public method to leave the channel. |
309 | 328 |
310 @param message message to be used for PART messages (string) | 329 @param message message to be used for PART messages (string) |
311 """ | 330 """ |
312 self.__partMessage = message | 331 self.__partMessage = message |
313 | 332 |
333 def setPrivate(self, private, partner=""): | |
334 """ | |
335 Public method to set the private chat mode. | |
336 | |
337 @param private flag indicating private chat mode (boolean) | |
338 @param partner name of the partner user (string) | |
339 """ | |
340 self.__private = private | |
341 self.__privatePartner = partner | |
342 | |
314 def handleMessage(self, line): | 343 def handleMessage(self, line): |
315 """ | 344 """ |
316 Public method to handle the message sent by the server. | 345 Public method to handle the message sent by the server. |
317 | 346 |
318 @param line server message (string) | 347 @param line server message (string) |
333 @param match match object that matched the pattern | 362 @param match match object that matched the pattern |
334 @return flag indicating whether the message was handled (boolean) | 363 @return flag indicating whether the message was handled (boolean) |
335 """ | 364 """ |
336 if match.group(2).lower() == self.__name: | 365 if match.group(2).lower() == self.__name: |
337 msg = ircFilter(match.group(3)) | 366 msg = ircFilter(match.group(3)) |
338 self.messages.append( | 367 self.__appendMessage( |
339 '<font color="{0}">{2} <b><</b><font color="{1}">{3}</font>' | 368 '<font color="{0}">{2} <b><</b><font color="{1}">{3}</font>' |
340 '<b>></b> {4}</font>'.format( | 369 '<b>></b> {4}</font>'.format( |
341 Preferences.getIrc("ChannelMessageColour"), | 370 Preferences.getIrc("ChannelMessageColour"), |
342 Preferences.getIrc("NickColour"), | 371 Preferences.getIrc("NickColour"), |
343 ircTimestamp(), match.group(1), | 372 ircTimestamp(), match.group(1), |
350 self.__ui.showNotification(UI.PixmapCache.getPixmap("irc48.png"), | 379 self.__ui.showNotification(UI.PixmapCache.getPixmap("irc48.png"), |
351 self.trUtf8("Nick mentioned"), msg) | 380 self.trUtf8("Nick mentioned"), msg) |
352 return True | 381 return True |
353 | 382 |
354 return False | 383 return False |
384 | |
385 def addUsers(self, users): | |
386 """ | |
387 Public method to add users to the channel. | |
388 | |
389 @param users list of user names to add (list of string) | |
390 """ | |
391 for user in users: | |
392 itm = self.__findUser(user) | |
393 if itm is None: | |
394 IrcUserItem(user, self.usersList) | |
355 | 395 |
356 def __userJoin(self, match): | 396 def __userJoin(self, match): |
357 """ | 397 """ |
358 Private method to handle a user joining the channel. | 398 Private method to handle a user joining the channel. |
359 | 399 |
472 itm = self.__findUser(userName) | 512 itm = self.__findUser(userName) |
473 if itm is None: | 513 if itm is None: |
474 itm = IrcUserItem(userName, self.usersList) | 514 itm = IrcUserItem(userName, self.usersList) |
475 for privilege in userPrivileges: | 515 for privilege in userPrivileges: |
476 itm.changePrivilege(privilege) | 516 itm.changePrivilege(privilege) |
517 return True | |
518 | |
519 return False | |
520 | |
521 def __userAway(self, match): | |
522 """ | |
523 Private method to handle a topic change of the channel. | |
524 | |
525 @param match match object that matched the pattern | |
526 @return flag indicating whether the message was handled (boolean) | |
527 """ | |
528 if match.group(1).lower() == self.__name: | |
529 self.__addManagementMessage(self.trUtf8("Away"), | |
530 self.trUtf8("{0} is away: {1}").format(match.group(2), match.group(3))) | |
477 return True | 531 return True |
478 | 532 |
479 return False | 533 return False |
480 | 534 |
481 def __setTopic(self, match): | 535 def __setTopic(self, match): |
603 if match.group(1).lower() == self.__name: | 657 if match.group(1).lower() == self.__name: |
604 return True | 658 return True |
605 | 659 |
606 return False | 660 return False |
607 | 661 |
662 def __help(self, match): | |
663 """ | |
664 Private method to handle a help message. | |
665 | |
666 @param match match object that matched the pattern | |
667 @return flag indicating whether the message was handled (boolean) | |
668 """ | |
669 self.__addManagementMessage(self.trUtf8("Help"), | |
670 "{0} {1}".format(match.group(1), ircFilter(match.group(2)))) | |
671 return True | |
672 | |
608 def setUserPrivilegePrefix(self, prefixes): | 673 def setUserPrivilegePrefix(self, prefixes): |
609 """ | 674 """ |
610 Public method to set the user privilege to prefix mapping. | 675 Public method to set the user privilege to prefix mapping. |
611 | 676 |
612 @param prefixes dictionary with privilege as key and prefix as value | 677 @param prefixes dictionary with privilege as key and prefix as value |
659 color = Preferences.getIrc("JoinChannelColour") | 724 color = Preferences.getIrc("JoinChannelColour") |
660 elif indicator == self.LeaveIndicator: | 725 elif indicator == self.LeaveIndicator: |
661 color = Preferences.getIrc("LeaveChannelColour") | 726 color = Preferences.getIrc("LeaveChannelColour") |
662 else: | 727 else: |
663 color = Preferences.getIrc("ChannelInfoColour") | 728 color = Preferences.getIrc("ChannelInfoColour") |
664 self.messages.append( | 729 self.__appendMessage( |
665 '<font color="{0}">{1} <b>[</b>{2}<b>]</b> {3}</font>'.format( | 730 '<font color="{0}">{1} <b>[</b>{2}<b>]</b> {3}</font>'.format( |
666 color, ircTimestamp(), indicator, message)) | 731 color, ircTimestamp(), indicator, message)) |
732 | |
733 def __appendMessage(self, message): | |
734 """ | |
735 Private slot to append a message. | |
736 """ | |
737 if self.__hidden and self.__markerLine == "": | |
738 self.setMarkerLine() | |
739 self.messages.append(message) | |
667 | 740 |
668 def setMarkerLine(self): | 741 def setMarkerLine(self): |
669 """ | 742 """ |
670 Public method to draw a line to mark the current position. | 743 Public method to draw a line to mark the current position. |
671 """ | 744 """ |
689 else: | 762 else: |
690 txt = txt.replace(self.__markerLine, "") | 763 txt = txt.replace(self.__markerLine, "") |
691 self.messages.setHtml(txt) | 764 self.messages.setHtml(txt) |
692 self.__markerLine = "" | 765 self.__markerLine = "" |
693 | 766 |
767 def __clearMessages(self): | |
768 """ | |
769 Private slot to clear the contents of the messages display. | |
770 """ | |
771 self.messages.clear() | |
772 | |
773 def __copyMessages(self): | |
774 """ | |
775 Private slot to copy the selection of the messages display to the clipboard. | |
776 """ | |
777 self.messages.copy() | |
778 | |
779 def __cutMessages(self): | |
780 """ | |
781 Private slot to cut the selection of the messages display to the clipboard. | |
782 """ | |
783 self.messages.cut() | |
784 | |
785 def __copyAllMessages(self): | |
786 """ | |
787 Private slot to copy the contents of the messages display to the clipboard. | |
788 """ | |
789 txt = self.messages.toPlainText() | |
790 if txt: | |
791 cb = QApplication.clipboard() | |
792 cb.setText(txt) | |
793 | |
794 def __cutAllMessages(self): | |
795 """ | |
796 Private slot to cut the contents of the messages display to the clipboard. | |
797 """ | |
798 txt = self.messages.toPlainText() | |
799 if txt: | |
800 cb = QApplication.clipboard() | |
801 cb.setText(txt) | |
802 self.messages.clear() | |
803 | |
804 def __saveMessages(self): | |
805 """ | |
806 Private slot to save the contents of the messages display. | |
807 """ | |
808 hasText = not self.messages.document().isEmpty() | |
809 if hasText: | |
810 if Utilities.isWindowsPlatform(): | |
811 htmlExtension = "htm" | |
812 else: | |
813 htmlExtension = "html" | |
814 fname, selectedFilter = E5FileDialog.getSaveFileNameAndFilter( | |
815 self, | |
816 self.trUtf8("Save Messages"), | |
817 "", | |
818 self.trUtf8( | |
819 "HTML Files (*.{0});;Text Files (*.txt);;All Files (*)").format( | |
820 htmlExtension), | |
821 None, | |
822 E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite)) | |
823 if fname: | |
824 ext = QFileInfo(fname).suffix() | |
825 if not ext: | |
826 ex = selectedFilter.split("(*")[1].split(")")[0] | |
827 if ex: | |
828 fname += ex | |
829 ext = QFileInfo(fname).suffix() | |
830 if QFileInfo(fname).exists(): | |
831 res = E5MessageBox.yesNo(self, | |
832 self.trUtf8("Save Messages"), | |
833 self.trUtf8("<p>The file <b>{0}</b> already exists." | |
834 " Overwrite it?</p>").format(fname), | |
835 icon=E5MessageBox.Warning) | |
836 if not res: | |
837 return | |
838 fname = Utilities.toNativeSeparators(fname) | |
839 | |
840 try: | |
841 if ext.lower() in ["htm", "html"]: | |
842 txt = self.messages.toHtml() | |
843 else: | |
844 txt = self.messages.toPlainText() | |
845 f = open(fname, "w", encoding="utf-8") | |
846 f.write(txt) | |
847 f.close() | |
848 except IOError as err: | |
849 E5MessageBox.critical(self, | |
850 self.trUtf8("Error saving Messages"), | |
851 self.trUtf8("""<p>The messages contents could not be written""" | |
852 """ to <b>{0}</b></p><p>Reason: {1}</p>""")\ | |
853 .format(fname, str(err))) | |
854 | |
694 def __initMessagesMenu(self): | 855 def __initMessagesMenu(self): |
695 """ | 856 """ |
696 Private slot to initialize the context menu of the messages pane. | 857 Private slot to initialize the context menu of the messages pane. |
697 """ | 858 """ |
698 self.__messagesMenu = QMenu(self) | 859 self.__messagesMenu = QMenu(self) |
699 ## self.__cutMessagesAct = \ | 860 self.__cutMessagesAct = \ |
700 ## self.__messagesMenu.addAction( | 861 self.__messagesMenu.addAction( |
701 ## UI.PixmapCache.getIcon("editCut.png"), | 862 UI.PixmapCache.getIcon("editCut.png"), |
702 ## self.trUtf8("Cut"), self.__cutMessages) | 863 self.trUtf8("Cut"), self.__cutMessages) |
703 ## self.__copyMessagesAct = \ | 864 self.__copyMessagesAct = \ |
704 ## self.__messagesMenu.addAction( | 865 self.__messagesMenu.addAction( |
705 ## UI.PixmapCache.getIcon("editCopy.png"), | 866 UI.PixmapCache.getIcon("editCopy.png"), |
706 ## self.trUtf8("Copy"), self.__copyMessages) | 867 self.trUtf8("Copy"), self.__copyMessages) |
707 ## self.__messagesMenu.addSeparator() | 868 self.__messagesMenu.addSeparator() |
708 ## self.__cutAllMessagesAct = \ | 869 self.__cutAllMessagesAct = \ |
709 ## self.__messagesMenu.addAction( | 870 self.__messagesMenu.addAction( |
710 ## UI.PixmapCache.getIcon("editCut.png"), | 871 UI.PixmapCache.getIcon("editCut.png"), |
711 ## self.trUtf8("Cut all"), self.__cutAllMessages) | 872 self.trUtf8("Cut all"), self.__cutAllMessages) |
712 ## self.__copyAllMessagesAct = \ | 873 self.__copyAllMessagesAct = \ |
713 ## self.__messagesMenu.addAction( | 874 self.__messagesMenu.addAction( |
714 ## UI.PixmapCache.getIcon("editCopy.png"), | 875 UI.PixmapCache.getIcon("editCopy.png"), |
715 ## self.trUtf8("Copy all"), self.__copyAllMessages) | 876 self.trUtf8("Copy all"), self.__copyAllMessages) |
716 ## self.__messagesMenu.addSeparator() | 877 self.__messagesMenu.addSeparator() |
717 ## self.__clearMessagesAct = \ | 878 self.__clearMessagesAct = \ |
718 ## self.__messagesMenu.addAction( | 879 self.__messagesMenu.addAction( |
719 ## UI.PixmapCache.getIcon("editDelete.png"), | 880 UI.PixmapCache.getIcon("editDelete.png"), |
720 ## self.trUtf8("Clear"), self.__clearMessages) | 881 self.trUtf8("Clear"), self.__clearMessages) |
721 ## self.__messagesMenu.addSeparator() | 882 self.__messagesMenu.addSeparator() |
722 ## self.__saveMessagesAct = \ | 883 self.__saveMessagesAct = \ |
723 ## self.__messagesMenu.addAction( | 884 self.__messagesMenu.addAction( |
724 ## UI.PixmapCache.getIcon("fileSave.png"), | 885 UI.PixmapCache.getIcon("fileSave.png"), |
725 ## self.trUtf8("Save"), self.__saveMessages) | 886 self.trUtf8("Save"), self.__saveMessages) |
887 self.__messagesMenu.addSeparator() | |
726 self.__setMarkerMessagesAct = \ | 888 self.__setMarkerMessagesAct = \ |
727 self.__messagesMenu.addAction(self.trUtf8("Mark Current Position"), | 889 self.__messagesMenu.addAction(self.trUtf8("Mark Current Position"), |
728 self.setMarkerLine) | 890 self.setMarkerLine) |
729 self.__unsetMarkerMessagesAct = \ | 891 self.__unsetMarkerMessagesAct = \ |
730 self.__messagesMenu.addAction(self.trUtf8("Remove Position Marker"), | 892 self.__messagesMenu.addAction(self.trUtf8("Remove Position Marker"), |
731 self.unsetMarkerLine) | 893 self.unsetMarkerLine) |
894 | |
895 self.on_messages_copyAvailable(False) | |
896 | |
897 @pyqtSlot(bool) | |
898 def on_messages_copyAvailable(self, yes): | |
899 """ | |
900 Private slot to react to text selection/deselection of the messages edit. | |
901 | |
902 @param yes flag signaling the availability of selected text (boolean) | |
903 """ | |
904 self.__copyMessagesAct.setEnabled(yes) | |
905 self.__cutMessagesAct.setEnabled(yes) | |
732 | 906 |
733 @pyqtSlot(QPoint) | 907 @pyqtSlot(QPoint) |
734 def on_messages_customContextMenuRequested(self, pos): | 908 def on_messages_customContextMenuRequested(self, pos): |
735 """ | 909 """ |
736 Private slot to show the context menu of the messages pane. | 910 Private slot to show the context menu of the messages pane. |
737 """ | 911 |
912 @param pos the position of the mouse pointer (QPoint) | |
913 """ | |
914 enable = not self.messages.document().isEmpty() | |
915 self.__cutAllMessagesAct.setEnabled(enable) | |
916 self.__copyAllMessagesAct.setEnabled(enable) | |
917 self.__saveMessagesAct.setEnabled(enable) | |
738 self.__setMarkerMessagesAct.setEnabled(self.__markerLine == "") | 918 self.__setMarkerMessagesAct.setEnabled(self.__markerLine == "") |
739 self.__unsetMarkerMessagesAct.setEnabled(self.__markerLine != "") | 919 self.__unsetMarkerMessagesAct.setEnabled(self.__markerLine != "") |
740 self.__messagesMenu.popup(self.messages.mapToGlobal(pos)) | 920 self.__messagesMenu.popup(self.messages.mapToGlobal(pos)) |
741 | 921 |
922 def __whoIs(self): | |
923 """ | |
924 Private slot to get information about the selected user. | |
925 """ | |
926 # TODO: not implemented yet | |
927 return | |
928 | |
929 def __openPrivateChat(self): | |
930 """ | |
931 Private slot to open a chat with the selected user. | |
932 """ | |
933 user = self.usersList.selectedItems()[0].text() | |
934 self.openPrivateChat.emit(user) | |
935 | |
936 def __initUsersMenu(self): | |
937 """ | |
938 Private slot to initialize the users list context menu. | |
939 """ | |
940 self.__usersMenu = QMenu(self) | |
941 self.__usersMenu.addAction(self.trUtf8("Who Is"), self.__whoIs) | |
942 self.__usersMenu.addSeparator() | |
943 self.__privateChatAct = \ | |
944 self.__usersMenu.addAction(self.trUtf8("Private Chat"), | |
945 self.__openPrivateChat) | |
946 | |
742 @pyqtSlot(QPoint) | 947 @pyqtSlot(QPoint) |
743 def on_usersList_customContextMenuRequested(self, pos): | 948 def on_usersList_customContextMenuRequested(self, pos): |
744 """ | 949 """ |
745 Private slot to show the context menu of the users list. | 950 Private slot to show the context menu of the users list. |
746 """ | 951 |
747 # TODO: not implemented yet | 952 @param pos the position of the mouse pointer (QPoint) |
748 return | 953 """ |
954 self.__privateChatAct.setEnabled(not self.__private) | |
955 if len(self.usersList.selectedItems()) > 0: | |
956 self.__usersMenu.popup(self.usersList.mapToGlobal(pos)) | |
957 | |
958 def hideEvent(self, evt): | |
959 """ | |
960 Protected method handling hide events. | |
961 | |
962 @param evt reference to the hide event (QHideEvent) | |
963 """ | |
964 self.__hidden = True | |
965 | |
966 def showEvent(self, evt): | |
967 """ | |
968 Protected method handling show events. | |
969 | |
970 @param evt reference to the show event (QShowEvent) | |
971 """ | |
972 self.__hidden = False |