crisp
25th January 2009, 05:42
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':
import sys
import socket
import string
import threading
import time
import Queue
"""
class ReadFromServer():
def loop(self):
while 1:
try:
data = self.irc.recv(4096)
if data.find('PING') != -1:
self.irc.send('PONG ' + data.split() [1] + '\r\n')
if len(data) > 0:
print data
time.sleep(0.1)
except:
print 'Error: Possible interupt.'
break
"""
""" Set up buffer for incoming data """
incomingBuffer = Queue.Queue(5000)
class IRC:
recv_function = ''
irc = ''
def __init__(self):
self.irc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.recv_function = self.recv
def recvLoop(self):
while 1:
try:
data = self.irc.recv(4096)
if data.find('PING') != -1:
self.irc.send('PONG ' + data.split() [1] + '\r\n')
#if data.find('hi') != -1:
#client.channelSend('#crasp', 'hai2u :)')
if len(data) > 0:
incomingBuffer.put(data)
print data
time.sleep(0.1)
except:
print 'Error: Possible interupt.'
break
def newConnection(self, server, port, nick, ident, realName):
self.server = server
self.port = port
self.nick = nick
self.ident = ident
self.realName = realName
self.irc.connect ( ( self.server, self.port ) )
self.rawSend("NICK %s\r\n" % self.nick)
self.rawSend("USER %s %s unused :%s\r\n" % (self.ident, self.server, self.realName))
def quit(self):
self.rawSend('QUIT :')
def part(self):
self.rawSend('PART :')
def join(self, channel):
self.rawSend('JOIN ' + channel)
def channelSend(self, channel, text):
self.rawSend('PRIVMSG ' + channel + ' :' + text)
def set_recv_function(self, f):
self.recv_function = f
def recv(self, s):
# default receive function
print s
def rawSend(self, s):
self.irc.send(s + '\r\n');
def my_receive(s):
print s
"""
client = IRC()
client.newConnection('irc.oftc.net', 6667, 'crispycream', 'crisp', 'crisp')
client.join('#crasp')
client.channelSend('#crasp', 'blah')
client.set_recv_function(my_receive)
client.recvLoop()
while 1:
if client.incomingBuffer.qsize() > 0:
item = client.incomingBuffer.get()
print item
client.incomingBuffer.task_done()
"""
This is the Qt Designed code:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'crispircmainwindow.ui'
#
# Created: Sun Jan 25 04:03:58 2009
# by: PyQt4 UI code generator 4.4.4
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
class Ui_CrispIRCMainWindow(object):
def setupUi(self, CrispIRCMainWindow):
CrispIRCMainWindow.setObjectName("CrispIRCMainWindow")
CrispIRCMainWindow.resize(531, 479)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(CrispIRCMainWindow.si zePolicy().hasHeightForWidth())
CrispIRCMainWindow.setSizePolicy(sizePolicy)
self.centralwidget = QtGui.QWidget(CrispIRCMainWindow)
self.centralwidget.setObjectName("centralwidget")
self.widget = QtGui.QWidget(self.centralwidget)
self.widget.setGeometry(QtCore.QRect(0, 0, 531, 431))
self.widget.setObjectName("widget")
self.gridLayout = QtGui.QGridLayout(self.widget)
self.gridLayout.setObjectName("gridLayout")
self.displayBrowser = QtGui.QTextBrowser(self.widget)
self.displayBrowser.setObjectName("displayBrowser")
self.gridLayout.addWidget(self.displayBrowser, 0, 0, 1, 2)
self.connectButton = QtGui.QPushButton(self.widget)
self.connectButton.setObjectName("connectButton")
self.gridLayout.addWidget(self.connectButton, 1, 0, 1, 1)
self.disconnectButton = QtGui.QPushButton(self.widget)
self.disconnectButton.setObjectName("disconnectButton")
self.gridLayout.addWidget(self.disconnectButton, 1, 1, 1, 1)
CrispIRCMainWindow.setCentralWidget(self.centralwi dget)
self.statusbar = QtGui.QStatusBar(CrispIRCMainWindow)
self.statusbar.setObjectName("statusbar")
CrispIRCMainWindow.setStatusBar(self.statusbar)
self.menubar = QtGui.QMenuBar(CrispIRCMainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 531, 25))
self.menubar.setObjectName("menubar")
self.menuFile = QtGui.QMenu(self.menubar)
self.menuFile.setObjectName("menuFile")
self.menu_Edit = QtGui.QMenu(self.menubar)
self.menu_Edit.setObjectName("menu_Edit")
CrispIRCMainWindow.setMenuBar(self.menubar)
self.actionBlah = QtGui.QAction(CrispIRCMainWindow)
self.actionBlah.setObjectName("actionBlah")
self.actionBlaaah = QtGui.QAction(CrispIRCMainWindow)
self.actionBlaaah.setObjectName("actionBlaaah")
self.action_Preferences = QtGui.QAction(CrispIRCMainWindow)
self.action_Preferences.setObjectName("action_Preferences")
self.menuFile.addAction(self.actionBlah)
self.menuFile.addSeparator()
self.menuFile.addAction(self.actionBlaaah)
self.menu_Edit.addAction(self.action_Preferences)
self.menubar.addAction(self.menuFile.menuAction())
self.menubar.addAction(self.menu_Edit.menuAction() )
self.retranslateUi(CrispIRCMainWindow)
QtCore.QMetaObject.connectSlotsByName(CrispIRCMain Window)
def retranslateUi(self, CrispIRCMainWindow):
CrispIRCMainWindow.setWindowTitle(QtGui.QApplicati on.translate("CrispIRCMainWindow", "Crisp IRC", None, QtGui.QApplication.UnicodeUTF8))
self.connectButton.setText(QtGui.QApplication.tran slate("CrispIRCMainWindow", "Connect", None, QtGui.QApplication.UnicodeUTF8))
self.disconnectButton.setText(QtGui.QApplication.t ranslate("CrispIRCMainWindow", "Disconnect", None, QtGui.QApplication.UnicodeUTF8))
self.menuFile.setTitle(QtGui.QApplication.translat e("CrispIRCMainWindow", "&File", None, QtGui.QApplication.UnicodeUTF8))
self.menu_Edit.setTitle(QtGui.QApplication.transla te("CrispIRCMainWindow", "&Edit", None, QtGui.QApplication.UnicodeUTF8))
self.actionBlah.setText(QtGui.QApplication.transla te("CrispIRCMainWindow", "Blah", None, QtGui.QApplication.UnicodeUTF8))
self.actionBlaaah.setText(QtGui.QApplication.trans late("CrispIRCMainWindow", "Blaaah", None, QtGui.QApplication.UnicodeUTF8))
self.action_Preferences.setText(QtGui.QApplication .translate("CrispIRCMainWindow", "&Preferences", None, QtGui.QApplication.UnicodeUTF8))
And finally, crucially, this is the code that attempts to link the two together.
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import time
import ui_crispircmainwindow
import crisp_irc
MAC = "qt_mac_set_native_menubar" in dir()
class CrispIRCMainWindow(QMainWindow, ui_crispircmainwindow.Ui_CrispIRCMainWindow, crisp_irc.IRC):
def __init__(self, parent=None):
super(CrispIRCMainWindow, self).__init__(parent)
self.__index = 0
self.setupUi(self)
@pyqtSignature("")
def on_connectButton_clicked(self):
self.displayBrowser.append('Connecting...')
client = crisp_irc.IRC()
client.newConnection('irc.oftc.net', 6667, 'crispycream', 'crisp', 'crisp')
client.join('#crasp')
client.channelSend('#crasp', 'blah')
client.set_recv_function(crisp_irc.my_receive)
client.recvLoop()
if crisp_irc.incomingBuffer.qsize() > 0:
item = crisp_irc.incomingBuffer.get()
print item
crisp_irc.incomingBuffer.task_done()
#if irc._incomingBuffer.qsize() > 0:
# self.displayBrowser.append('BUFFER LARGER THAN ZERO')
@pyqtSignature("")
def on_disconnectButton_clicked(self):
self.displayBrowser.append('(Not really) Quitting...')
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
form = CrispIRCMainWindow()
form.show()
app.exec_()
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':
import sys
import socket
import string
import threading
import time
import Queue
"""
class ReadFromServer():
def loop(self):
while 1:
try:
data = self.irc.recv(4096)
if data.find('PING') != -1:
self.irc.send('PONG ' + data.split() [1] + '\r\n')
if len(data) > 0:
print data
time.sleep(0.1)
except:
print 'Error: Possible interupt.'
break
"""
""" Set up buffer for incoming data """
incomingBuffer = Queue.Queue(5000)
class IRC:
recv_function = ''
irc = ''
def __init__(self):
self.irc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.recv_function = self.recv
def recvLoop(self):
while 1:
try:
data = self.irc.recv(4096)
if data.find('PING') != -1:
self.irc.send('PONG ' + data.split() [1] + '\r\n')
#if data.find('hi') != -1:
#client.channelSend('#crasp', 'hai2u :)')
if len(data) > 0:
incomingBuffer.put(data)
print data
time.sleep(0.1)
except:
print 'Error: Possible interupt.'
break
def newConnection(self, server, port, nick, ident, realName):
self.server = server
self.port = port
self.nick = nick
self.ident = ident
self.realName = realName
self.irc.connect ( ( self.server, self.port ) )
self.rawSend("NICK %s\r\n" % self.nick)
self.rawSend("USER %s %s unused :%s\r\n" % (self.ident, self.server, self.realName))
def quit(self):
self.rawSend('QUIT :')
def part(self):
self.rawSend('PART :')
def join(self, channel):
self.rawSend('JOIN ' + channel)
def channelSend(self, channel, text):
self.rawSend('PRIVMSG ' + channel + ' :' + text)
def set_recv_function(self, f):
self.recv_function = f
def recv(self, s):
# default receive function
print s
def rawSend(self, s):
self.irc.send(s + '\r\n');
def my_receive(s):
print s
"""
client = IRC()
client.newConnection('irc.oftc.net', 6667, 'crispycream', 'crisp', 'crisp')
client.join('#crasp')
client.channelSend('#crasp', 'blah')
client.set_recv_function(my_receive)
client.recvLoop()
while 1:
if client.incomingBuffer.qsize() > 0:
item = client.incomingBuffer.get()
print item
client.incomingBuffer.task_done()
"""
This is the Qt Designed code:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'crispircmainwindow.ui'
#
# Created: Sun Jan 25 04:03:58 2009
# by: PyQt4 UI code generator 4.4.4
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
class Ui_CrispIRCMainWindow(object):
def setupUi(self, CrispIRCMainWindow):
CrispIRCMainWindow.setObjectName("CrispIRCMainWindow")
CrispIRCMainWindow.resize(531, 479)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(CrispIRCMainWindow.si zePolicy().hasHeightForWidth())
CrispIRCMainWindow.setSizePolicy(sizePolicy)
self.centralwidget = QtGui.QWidget(CrispIRCMainWindow)
self.centralwidget.setObjectName("centralwidget")
self.widget = QtGui.QWidget(self.centralwidget)
self.widget.setGeometry(QtCore.QRect(0, 0, 531, 431))
self.widget.setObjectName("widget")
self.gridLayout = QtGui.QGridLayout(self.widget)
self.gridLayout.setObjectName("gridLayout")
self.displayBrowser = QtGui.QTextBrowser(self.widget)
self.displayBrowser.setObjectName("displayBrowser")
self.gridLayout.addWidget(self.displayBrowser, 0, 0, 1, 2)
self.connectButton = QtGui.QPushButton(self.widget)
self.connectButton.setObjectName("connectButton")
self.gridLayout.addWidget(self.connectButton, 1, 0, 1, 1)
self.disconnectButton = QtGui.QPushButton(self.widget)
self.disconnectButton.setObjectName("disconnectButton")
self.gridLayout.addWidget(self.disconnectButton, 1, 1, 1, 1)
CrispIRCMainWindow.setCentralWidget(self.centralwi dget)
self.statusbar = QtGui.QStatusBar(CrispIRCMainWindow)
self.statusbar.setObjectName("statusbar")
CrispIRCMainWindow.setStatusBar(self.statusbar)
self.menubar = QtGui.QMenuBar(CrispIRCMainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 531, 25))
self.menubar.setObjectName("menubar")
self.menuFile = QtGui.QMenu(self.menubar)
self.menuFile.setObjectName("menuFile")
self.menu_Edit = QtGui.QMenu(self.menubar)
self.menu_Edit.setObjectName("menu_Edit")
CrispIRCMainWindow.setMenuBar(self.menubar)
self.actionBlah = QtGui.QAction(CrispIRCMainWindow)
self.actionBlah.setObjectName("actionBlah")
self.actionBlaaah = QtGui.QAction(CrispIRCMainWindow)
self.actionBlaaah.setObjectName("actionBlaaah")
self.action_Preferences = QtGui.QAction(CrispIRCMainWindow)
self.action_Preferences.setObjectName("action_Preferences")
self.menuFile.addAction(self.actionBlah)
self.menuFile.addSeparator()
self.menuFile.addAction(self.actionBlaaah)
self.menu_Edit.addAction(self.action_Preferences)
self.menubar.addAction(self.menuFile.menuAction())
self.menubar.addAction(self.menu_Edit.menuAction() )
self.retranslateUi(CrispIRCMainWindow)
QtCore.QMetaObject.connectSlotsByName(CrispIRCMain Window)
def retranslateUi(self, CrispIRCMainWindow):
CrispIRCMainWindow.setWindowTitle(QtGui.QApplicati on.translate("CrispIRCMainWindow", "Crisp IRC", None, QtGui.QApplication.UnicodeUTF8))
self.connectButton.setText(QtGui.QApplication.tran slate("CrispIRCMainWindow", "Connect", None, QtGui.QApplication.UnicodeUTF8))
self.disconnectButton.setText(QtGui.QApplication.t ranslate("CrispIRCMainWindow", "Disconnect", None, QtGui.QApplication.UnicodeUTF8))
self.menuFile.setTitle(QtGui.QApplication.translat e("CrispIRCMainWindow", "&File", None, QtGui.QApplication.UnicodeUTF8))
self.menu_Edit.setTitle(QtGui.QApplication.transla te("CrispIRCMainWindow", "&Edit", None, QtGui.QApplication.UnicodeUTF8))
self.actionBlah.setText(QtGui.QApplication.transla te("CrispIRCMainWindow", "Blah", None, QtGui.QApplication.UnicodeUTF8))
self.actionBlaaah.setText(QtGui.QApplication.trans late("CrispIRCMainWindow", "Blaaah", None, QtGui.QApplication.UnicodeUTF8))
self.action_Preferences.setText(QtGui.QApplication .translate("CrispIRCMainWindow", "&Preferences", None, QtGui.QApplication.UnicodeUTF8))
And finally, crucially, this is the code that attempts to link the two together.
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import time
import ui_crispircmainwindow
import crisp_irc
MAC = "qt_mac_set_native_menubar" in dir()
class CrispIRCMainWindow(QMainWindow, ui_crispircmainwindow.Ui_CrispIRCMainWindow, crisp_irc.IRC):
def __init__(self, parent=None):
super(CrispIRCMainWindow, self).__init__(parent)
self.__index = 0
self.setupUi(self)
@pyqtSignature("")
def on_connectButton_clicked(self):
self.displayBrowser.append('Connecting...')
client = crisp_irc.IRC()
client.newConnection('irc.oftc.net', 6667, 'crispycream', 'crisp', 'crisp')
client.join('#crasp')
client.channelSend('#crasp', 'blah')
client.set_recv_function(crisp_irc.my_receive)
client.recvLoop()
if crisp_irc.incomingBuffer.qsize() > 0:
item = crisp_irc.incomingBuffer.get()
print item
crisp_irc.incomingBuffer.task_done()
#if irc._incomingBuffer.qsize() > 0:
# self.displayBrowser.append('BUFFER LARGER THAN ZERO')
@pyqtSignature("")
def on_disconnectButton_clicked(self):
self.displayBrowser.append('(Not really) Quitting...')
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
form = CrispIRCMainWindow()
form.show()
app.exec_()