Hi all, I've been pulling my hair out for a while now and I hope someone here can help me. I'm working with PyQt (4) and Python 2.5, in a Linux environment. My aim is to have a basic Qt based IRC client. I'm aware of the IRC RFC and the ins and outs of that etc, so I'm not to worried there.

I thought the best way to do it would be like: [IRC framework/API]--->[something that links the two]<---[Qt GUI code], although I'm starting to have my doubts now.

The GUI I've built with Qt Designer, and isn't much of a problem. The API type module for IRC I've started mainly works (infact as a starting point I've borrowed it from elsewhere on the net and tweaked it to my needs), as in I can have an IRC object connect to a server, send messages, etc via the command line. It's the linking of the two I'm worried about - I was going for total seperation between presentation and underlying mechanics as far as is possible. I have many versions of the above scenario from hours of trying, but I'll go ahead and paste the code for the 3 main files described so far.

This is the 'API':

Qt Code:
  1. import sys
  2. import socket
  3. import string
  4. import threading
  5. import time
  6. import Queue
  7.  
  8. """
  9. class ReadFromServer():
  10.  
  11. def loop(self):
  12. while 1:
  13. try:
  14. data = self.irc.recv(4096)
  15. if data.find('PING') != -1:
  16. self.irc.send('PONG ' + data.split() [1] + '\r\n')
  17. if len(data) > 0:
  18. print data
  19. time.sleep(0.1)
  20. except:
  21. print 'Error: Possible interupt.'
  22. break
  23. """
  24.  
  25. """ Set up buffer for incoming data """
  26. incomingBuffer = Queue.Queue(5000)
  27.  
  28. class IRC:
  29.  
  30. recv_function = ''
  31. irc = ''
  32.  
  33. def __init__(self):
  34. self.irc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  35. self.recv_function = self.recv
  36.  
  37. def recvLoop(self):
  38. while 1:
  39. try:
  40. data = self.irc.recv(4096)
  41. if data.find('PING') != -1:
  42. self.irc.send('PONG ' + data.split() [1] + '\r\n')
  43. #if data.find('hi') != -1:
  44. #client.channelSend('#crasp', 'hai2u :)')
  45. if len(data) > 0:
  46. incomingBuffer.put(data)
  47. print data
  48. time.sleep(0.1)
  49. except:
  50. print 'Error: Possible interupt.'
  51. break
  52.  
  53. def newConnection(self, server, port, nick, ident, realName):
  54. self.server = server
  55. self.port = port
  56. self.nick = nick
  57. self.ident = ident
  58. self.realName = realName
  59.  
  60. self.irc.connect ( ( self.server, self.port ) )
  61. self.rawSend("NICK %s\r\n" % self.nick)
  62. self.rawSend("USER %s %s unused :%s\r\n" % (self.ident, self.server, self.realName))
  63.  
  64. def quit(self):
  65. self.rawSend('QUIT :')
  66.  
  67. def part(self):
  68. self.rawSend('PART :')
  69.  
  70. def join(self, channel):
  71. self.rawSend('JOIN ' + channel)
  72.  
  73. def channelSend(self, channel, text):
  74. self.rawSend('PRIVMSG ' + channel + ' :' + text)
  75.  
  76. def set_recv_function(self, f):
  77. self.recv_function = f
  78.  
  79. def recv(self, s):
  80. # default receive function
  81. print s
  82.  
  83. def rawSend(self, s):
  84. self.irc.send(s + '\r\n');
  85.  
  86. def my_receive(s):
  87. print s
  88. """
  89. client = IRC()
  90. client.newConnection('irc.oftc.net', 6667, 'crispycream', 'crisp', 'crisp')
  91. client.join('#crasp')
  92. client.channelSend('#crasp', 'blah')
  93. client.set_recv_function(my_receive)
  94. client.recvLoop()
  95.  
  96. while 1:
  97. if client.incomingBuffer.qsize() > 0:
  98. item = client.incomingBuffer.get()
  99. print item
  100. client.incomingBuffer.task_done()
  101. """
To copy to clipboard, switch view to plain text mode 
This is the Qt Designed code:

Qt Code:
  1. # -*- coding: utf-8 -*-
  2.  
  3. # Form implementation generated from reading ui file 'crispircmainwindow.ui'
  4. #
  5. # Created: Sun Jan 25 04:03:58 2009
  6. # by: PyQt4 UI code generator 4.4.4
  7. #
  8. # WARNING! All changes made in this file will be lost!
  9.  
  10. from PyQt4 import QtCore, QtGui
  11.  
  12. class Ui_CrispIRCMainWindow(object):
  13. def setupUi(self, CrispIRCMainWindow):
  14. CrispIRCMainWindow.setObjectName("CrispIRCMainWindow")
  15. CrispIRCMainWindow.resize(531, 479)
  16. sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
  17. sizePolicy.setHorizontalStretch(0)
  18. sizePolicy.setVerticalStretch(0)
  19. sizePolicy.setHeightForWidth(CrispIRCMainWindow.sizePolicy().hasHeightForWidth())
  20. CrispIRCMainWindow.setSizePolicy(sizePolicy)
  21. self.centralwidget = QtGui.QWidget(CrispIRCMainWindow)
  22. self.centralwidget.setObjectName("centralwidget")
  23. self.widget = QtGui.QWidget(self.centralwidget)
  24. self.widget.setGeometry(QtCore.QRect(0, 0, 531, 431))
  25. self.widget.setObjectName("widget")
  26. self.gridLayout = QtGui.QGridLayout(self.widget)
  27. self.gridLayout.setObjectName("gridLayout")
  28. self.displayBrowser = QtGui.QTextBrowser(self.widget)
  29. self.displayBrowser.setObjectName("displayBrowser")
  30. self.gridLayout.addWidget(self.displayBrowser, 0, 0, 1, 2)
  31. self.connectButton = QtGui.QPushButton(self.widget)
  32. self.connectButton.setObjectName("connectButton")
  33. self.gridLayout.addWidget(self.connectButton, 1, 0, 1, 1)
  34. self.disconnectButton = QtGui.QPushButton(self.widget)
  35. self.disconnectButton.setObjectName("disconnectButton")
  36. self.gridLayout.addWidget(self.disconnectButton, 1, 1, 1, 1)
  37. CrispIRCMainWindow.setCentralWidget(self.centralwidget)
  38. self.statusbar = QtGui.QStatusBar(CrispIRCMainWindow)
  39. self.statusbar.setObjectName("statusbar")
  40. CrispIRCMainWindow.setStatusBar(self.statusbar)
  41. self.menubar = QtGui.QMenuBar(CrispIRCMainWindow)
  42. self.menubar.setGeometry(QtCore.QRect(0, 0, 531, 25))
  43. self.menubar.setObjectName("menubar")
  44. self.menuFile = QtGui.QMenu(self.menubar)
  45. self.menuFile.setObjectName("menuFile")
  46. self.menu_Edit = QtGui.QMenu(self.menubar)
  47. self.menu_Edit.setObjectName("menu_Edit")
  48. CrispIRCMainWindow.setMenuBar(self.menubar)
  49. self.actionBlah = QtGui.QAction(CrispIRCMainWindow)
  50. self.actionBlah.setObjectName("actionBlah")
  51. self.actionBlaaah = QtGui.QAction(CrispIRCMainWindow)
  52. self.actionBlaaah.setObjectName("actionBlaaah")
  53. self.action_Preferences = QtGui.QAction(CrispIRCMainWindow)
  54. self.action_Preferences.setObjectName("action_Preferences")
  55. self.menuFile.addAction(self.actionBlah)
  56. self.menuFile.addSeparator()
  57. self.menuFile.addAction(self.actionBlaaah)
  58. self.menu_Edit.addAction(self.action_Preferences)
  59. self.menubar.addAction(self.menuFile.menuAction())
  60. self.menubar.addAction(self.menu_Edit.menuAction())
  61.  
  62. self.retranslateUi(CrispIRCMainWindow)
  63. QtCore.QMetaObject.connectSlotsByName(CrispIRCMainWindow)
  64.  
  65. def retranslateUi(self, CrispIRCMainWindow):
  66. CrispIRCMainWindow.setWindowTitle(QtGui.QApplication.translate("CrispIRCMainWindow", "Crisp IRC", None, QtGui.QApplication.UnicodeUTF8))
  67. self.connectButton.setText(QtGui.QApplication.translate("CrispIRCMainWindow", "Connect", None, QtGui.QApplication.UnicodeUTF8))
  68. self.disconnectButton.setText(QtGui.QApplication.translate("CrispIRCMainWindow", "Disconnect", None, QtGui.QApplication.UnicodeUTF8))
  69. self.menuFile.setTitle(QtGui.QApplication.translate("CrispIRCMainWindow", "&File", None, QtGui.QApplication.UnicodeUTF8))
  70. self.menu_Edit.setTitle(QtGui.QApplication.translate("CrispIRCMainWindow", "&Edit", None, QtGui.QApplication.UnicodeUTF8))
  71. self.actionBlah.setText(QtGui.QApplication.translate("CrispIRCMainWindow", "Blah", None, QtGui.QApplication.UnicodeUTF8))
  72. self.actionBlaaah.setText(QtGui.QApplication.translate("CrispIRCMainWindow", "Blaaah", None, QtGui.QApplication.UnicodeUTF8))
  73. self.action_Preferences.setText(QtGui.QApplication.translate("CrispIRCMainWindow", "&Preferences", None, QtGui.QApplication.UnicodeUTF8))
To copy to clipboard, switch view to plain text mode 
And finally, crucially, this is the code that attempts to link the two together.

Qt Code:
  1. from PyQt4.QtCore import *
  2. from PyQt4.QtGui import *
  3.  
  4. import time
  5.  
  6. import ui_crispircmainwindow
  7. import crisp_irc
  8.  
  9. MAC = "qt_mac_set_native_menubar" in dir()
  10.  
  11. class CrispIRCMainWindow(QMainWindow, ui_crispircmainwindow.Ui_CrispIRCMainWindow, crisp_irc.IRC):
  12.  
  13. def __init__(self, parent=None):
  14. super(CrispIRCMainWindow, self).__init__(parent)
  15. self.__index = 0
  16. self.setupUi(self)
  17.  
  18. @pyqtSignature("")
  19. def on_connectButton_clicked(self):
  20. self.displayBrowser.append('Connecting...')
  21. client = crisp_irc.IRC()
  22. client.newConnection('irc.oftc.net', 6667, 'crispycream', 'crisp', 'crisp')
  23. client.join('#crasp')
  24. client.channelSend('#crasp', 'blah')
  25. client.set_recv_function(crisp_irc.my_receive)
  26. client.recvLoop()
  27.  
  28. if crisp_irc.incomingBuffer.qsize() > 0:
  29. item = crisp_irc.incomingBuffer.get()
  30. print item
  31. crisp_irc.incomingBuffer.task_done()
  32.  
  33. #if irc._incomingBuffer.qsize() > 0:
  34. # self.displayBrowser.append('BUFFER LARGER THAN ZERO')
  35.  
  36. @pyqtSignature("")
  37. def on_disconnectButton_clicked(self):
  38. self.displayBrowser.append('(Not really) Quitting...')
  39.  
  40. if __name__ == "__main__":
  41. import sys
  42.  
  43. app = QApplication(sys.argv)
  44. form = CrispIRCMainWindow()
  45.  
  46. form.show()
  47. app.exec_()
To copy to clipboard, switch view to plain text mode