[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-devel
Subject:    segmentation fault
From:       Grégoire_Alexandre <gregoire.alex () easynet ! be>
Date:       2005-02-10 17:45:07
Message-ID: 200502101845.07198.gregoire.alex () easynet ! be
[Download RAW message or body]

Hi guys !

I got a problem when closing a window ( a QMainWindow ) in an MDI widget. Here 
are the files that cause the problem. It's a segmentation fault

And here is the output :
Destructor called : closing channels and sending QUIT cmd to serv
Destroying #gentoo
item removed
Leaving #gentoo
unregistering channel
channel unregistered
Part cmd sent
item destroyed
Segmentation fault

Thanks for help,
Alex

["beChannel.cpp" (text/x-c++src)]

// beIRC stuff
#include "beChannel.h"
#include "beConsole.h"
#include "beLineView.h"
// kvirc stuff
#define HAVE_CONFIG_H
#include "config.h"
#include <kvirc/3.0.1/kvi_app.h>
#include <kvirc/3.0.1/kvi_ircserverdb.h>
#include <kvirc/3.0.1/kvi_confignames.h>
// Qt stuff
#include <qlistbox.h>
#include <qregexp.h>


beChannel::beChannel(QWidget * parent, const QString & channel, beConsole * console) \
: beMDIWindow(parent, "beChannel", Qt::WDestructiveClose) {
	m_windowType = beMDIWindow::Channel;
	m_channel = channel;
	QString srvname = "";
	if(console)
	{
		m_pConsole = console;
		m_pConsole->registerChannel(this);
		srvname = console->server().hostname();
	}
	QString name = "beChannel "+srvname+" "+channel;
	setName(name);
	
	QStyleSheetItem * item = new QStyleSheetItem( m_pLineView->styleSheet(), "user" );
	item->setColor( "black" );
	item->setFontWeight( QFont::Bold );
	
	connect ( this, SIGNAL( userInput(const QString &) ), this, SLOT ( say(const QString \
&) ) ); // 	append("Welcome to "+channel);
	m_pListBox->show();
	setCaption(channel);
	show();
}

beChannel::~beChannel()
{
// 	delete m_pConsole;
	if(m_pConsole)
	{
		qDebug("Leaving "+m_channel);
		m_pConsole->unregisterChannel(this);
		qDebug("channel unregistered");
		m_pConsole->send("PART :"+m_channel);
		qDebug("Part cmd sent");
	}
}

QString beChannel::channel() const
{
	return m_channel;
}

void beChannel::say(const QString & msg)
{
	// should replace me with the username of this program user
	append("<user>me</user> "+msg);
	m_pConsole->send("PRIVMSG "+m_channel+" :"+msg);
}

void beChannel::msg(const QString & user, const QString & msg)
{
	append("<user>"+user+"</user> "+msg);
}

void beChannel::userJoin(const QString & username)
{
	QString nick_pattern = "[A-Za-z0-9|_\\-{}\\[\\]\\^`@+]+"; // no .
	
	append(QString("%1 has joined the channel").arg(username));
	QRegExp rx("^("+nick_pattern+")!");
	int pos;
	if( (pos = rx.search(username)) != -1)
		addUser(rx.cap(1));
	else
		qDebug(tr("Huh ... no username?"));
}

void beChannel::userLeaved(const QString & username)
{
	QString nick_pattern = "[A-Za-z0-9|_\\-{}\\[\\]\\^`@+]+"; // no .
	
	append(QString("%1 has leaved the channel").arg(username));
	QRegExp rx("^("+nick_pattern+")!");
	int pos;
	if( (pos = rx.search(username)) != -1)
		delUser(rx.cap(1));
	else
		qDebug(tr("Huh ... no username?"));
}

void beChannel::addUser(const QString & username, bool sort)
{
	// bool sort : sort the list box after inserting item
	// nice to disable if there are a lot of insert, especially when joining
	// crowded channels... and sorting with beChannel::sortUserList()
	
	if(!m_pListBox)
	{
		qWarning(tr("Error: beChannel must have a non nul pointer to a QListBox"));
		return;
	}
	// avoids inserting already existing items ( user )
	QListBoxItem * item = m_pListBox->findItem(username, Qt::ExactMatch);
	if(!item)
	{
// 		qDebug("Inserting "+username);
		m_pListBox->insertItem(username);
		if(sort) m_pListBox->sort(true);
	}
	else
		qDebug("Not inserting "+username);
}

void beChannel::delUser(const QString & username)
{
	if(!m_pListBox)
	{
		qWarning(tr("Error: beChannel must have a non nul pointer to a QListBox"));
		return;
	}
	QListBoxItem * item = m_pListBox->findItem(username, Qt::ExactMatch);
	if(!item)
		qWarning("This nick ("+username+") doesnt exist... not deleting it");
	else
	{
// 		qDebug("Deleting "+username);
		m_pListBox->removeItem(m_pListBox->index(item));
	}
}

void beChannel::sortUserList()
{
	m_pListBox->sort(true);
}

void beChannel::resetUserList()
{
	m_pListBox->clear();
}


["beConsole.cpp" (text/x-c++src)]

// beIRC stuff
#include "beConsole.h"
#include "beChannel.h"
// kvirc stuff
#define HAVE_CONFIG_H
#include "config.h"
#include <kvirc/3.0.1/kvi_app.h>
#include <kvirc/3.0.1/kvi_ircserverdb.h>
#include <kvirc/3.0.1/kvi_confignames.h>
// QT Stuff
#include <qregexp.h>
#include <qsocket.h>
#include <qstring.h>
#include <qwidget.h>
#include <qvaluelist.h>

extern KVIRC_API KviIrcServerDataBase           * g_pIrcServerDataBase;

beConsole::beConsole(QWidget * parent,const char * name) : \
beMDIWindow(parent,name,Qt::WDestructiveClose) {
	m_windowType = beMDIWindow::Console;

	KviIrcNetwork * net = g_pIrcServerDataBase->currentNetwork();

	if(net)m_pSrv = net->currentServer();
	QString srvname = m_pSrv->hostname();
	setCaption(srvname);
	connect ( this, SIGNAL( userInput(const QString &) ), this, SLOT ( send(const \
QString &) ) );  connect ( this, SIGNAL( receivedNumericReply(int, const QString &, \
const QString &)), this, SLOT ( handleNumericReply(int, const QString &, const \
QString&)));  connect ( this, SIGNAL( receivedUserMsg(QString,const QString \
&,QString) ), this, SLOT ( handleUserMsg(QString, const QString &,QString)));  
	resetOnNameReply = true; // shall I clean the chan user list when I receive a \
RPL_NAMREPLY ?  
	// inserting all actions that the server may send to us QMap<QString, UserActions>
	m_actions.insert("PART",PART);
}

beConsole::~beConsole()
{
	qDebug("Destructor called : closing channels and sending QUIT cmd to serv");
	QMap<QString, beChannel*>::Iterator it;
	beChannel* tmp;
	for ( it = m_channels.begin(); it != m_channels.end(); ++it ) {
		if(it == 0) break;
		qDebug("Destroying "+it.data()->channel());
		tmp = it.data();
		m_channels.remove(it);
		qDebug("item removed");
		delete tmp;
		qDebug("item destroyed");
	}

	QString cmd = "QUIT :bof\n";
	m_pQSocket->writeBlock( cmd.latin1(), cmd.length() );
}

bool beConsole::connectToServer()
{
	if(!m_pSrv) { return false; }
	// \n for new liens
	// \t for tabs
	append("<mytag>Connecting to server...</mytag>");

	m_pQSocket = new QSocket(this);
	connect( m_pQSocket, SIGNAL( hostFound() ), this, SLOT( hostFound() ) );
	connect( m_pQSocket, SIGNAL( connected() ), this, SLOT( connected() ) );
	connect( m_pQSocket, SIGNAL( readyRead() ), this, SLOT(socketReadyRead()) );
	connect( m_pQSocket, SIGNAL( connectionClosed() ), this, SLOT( disconnected() ));
	m_pQSocket->connectToHost( m_pSrv->hostname(), m_pSrv->port() );
	return true;
}


void beConsole::hostFound()
{
	append("<mytag>Host found ...</mytag>");
}

void beConsole::connected()
{
	append("<mytag>Connected to "+m_pSrv->hostname()+"</mytag>");
	QString cmd;
	cmd = "USER blackeagle 0 "+m_pSrv->hostname()+" :Using beIRC 0.0.11\n";
	m_pQSocket->writeBlock( cmd.latin1(), cmd.length() );
	cmd = "NICK blackeagle645\n";
	m_pQSocket->writeBlock( cmd.latin1(), cmd.length() );
}

void beConsole::socketReadyRead()
{
// 	append("<mytag>Socket is ready to read</mytag>");
	while ( m_pQSocket->canReadLine() ) {

		QString msg = m_pQSocket->readLine();
		/* BEGIN removing \n from what the server sends */
		msg.truncate(msg.length() - 1); // chop off the \n
// 		QRegExp rxA("(.*)\n$");
// 		rxA.search( msg );
// 		append( rxA.cap(1) );
		append( msg );
		/* END removing \n */
		/* BEGIN ping pong fast reply */
		QRegExp rx("^PING :([0-9]+)");
		int pos;
		if( (pos = rx.search(msg)) != -1)
		{
			QString cmd = "PONG :"+rx.cap(1)+"\n";
			m_pQSocket->writeBlock( cmd.latin1(), cmd.length() );
			continue;
        	}
		/* END ping pong fast reply */
		
		// nice one huh ? ;) damn I love regexps !
		rx.setPattern(":([A-Za-z0-9|_-`]+)!(~)?([A-Za-z0-9|_-`]+)@([A-Za-z0-9.-]+) PRIVMSG \
(#[A-Za-z0-9]+) :(.*)");  if( (pos = rx.search(msg)) != -1)
		{
			msgForChan(rx.cap(1),rx.cap(5),rx.cap(6));
			continue;
		}
		
		
		QString num_replies_pattern = "[0-9]+";
		QString user_cmd_pattern = "JOIN|PART|QUIT|NOTICE|NICK"; // incomplete list
// 		QString nick_pattern = "[A-Za-z0-9|_\-`@+]+"; // no .
		QString nick_pattern = "[A-Za-z0-9|_\\-{}\\[\\]\\^`@+]+";
		QString dns_pattern = "[A-Za-z0-9.\\-]+";
		QString user_pattern = nick_pattern+"!~?"+nick_pattern+"@"+dns_pattern;
		QString channel_pattern = "[A-Za-z0-9~!#\\-_@]+";
		QString join_pattern = "("+user_pattern+") JOIN :("+channel_pattern+")";
		rx.setPattern(":"+join_pattern);
		if( (pos = rx.search(msg)) != -1)
		{
			userJoinedChan(rx.cap(1),rx.cap(2));
			continue;
        	}
		
		rx.setPattern(":("+user_pattern+") ("+user_cmd_pattern+") (.*)");
		if( (pos = rx.search(msg)) != -1)
		{
			emit receivedUserMsg(rx.cap(1),rx.cap(2),rx.cap(3));
			continue;
		}
		
		rx.setPattern("^:"+dns_pattern+" ("+num_replies_pattern+") ("+nick_pattern+") \
(.*)");  if( (pos = rx.search(msg)) != -1)
		{
			emit receivedNumericReply(rx.cap(1).toInt(),rx.cap(2),rx.cap(3));
			continue;
        	}
	}
}

void beConsole::disconnected()
{
	append("<mytag>Disconnected from server</mytag>");
}

void beConsole::send(const QString & command)
{
	append("<command>"+command+"</command>");
// 	command.append("\n");
	QString tmp = command+"\n";
	m_pQSocket->writeBlock( tmp.latin1(), tmp.length() );
}

KviIrcServer beConsole::server()
{
	return *m_pSrv;
}

void beConsole::registerChannel(beChannel * channel)
{
	m_channels.insert(channel->channel(),channel);
}

void beConsole::unregisterChannel(beChannel * channel)
{
	qDebug("unregistering channel");
	m_channels.remove(channel->channel());
}

void beConsole::msgForChan(const QString & user, const QString & chan, QString msg)
{
	beChannel* channel = m_channels[chan.lower()];
	if(!channel)
	{
		qDebug("No channel matching found : should create a new one !");
		
		QWidget* workspace = (QWidget*)this->parent()->parent();
		if(qstrcmp(workspace->className(),"QWorkspace") != 0)
		{
			Q_ASSERT(qstrcmp(workspace->className(),"QWorkspace") == 0);
			return;
		}
		channel = new beChannel(workspace,chan.lower(),this);
	}
// 	msg.truncate(msg.length() - 1); // removes the \n
	channel->msg(user,msg);
}

void beConsole::userJoinedChan(const QString & user, const QString & chan)
{
	qDebug("user joined chan");
	beChannel* channel = m_channels[chan.lower()];
	if(!channel)
	{
		qDebug("No channel matching found : should create a new one !");
		
		QWidget* workspace = (QWidget*)this->parent()->parent();
		if(qstrcmp(workspace->className(),"QWorkspace") != 0)
		{
			Q_ASSERT(qstrcmp(workspace->className(),"QWorkspace") == 0);
			return;
		}
		channel = new beChannel(workspace,chan.lower(),this);
	}
	channel->userJoin(user);
}

void beConsole::userLeavedChan(const QString & user, const QString & chan)
{
	qDebug("user leaved chan \""+chan+"\"");
	beChannel* channel = m_channels[chan.lower()];
	Q_ASSERT(!channel); // this means that we closed a window without sending PART cmd \
which is impossible  if(channel != 0)
		channel->userLeaved(user);
}

void beConsole::handleNumericReply(int num, const QString & user, const QString & \
args) {
	switch(num)
	{
		case 353:
		{
			nameReply(args);
			return;
		}
		case 366: 
		{
			resetOnNameReply = true;
			return;
		}
		default :
		{
			qDebug("Unhandled numeric reply");
			return;
		}
	}
}

void beConsole::handleUserMsg(QString user,const QString & action,QString msg)
{
	QString channel_pattern = "#[A-Za-z0-9~!#\\-_@]+";
	int pos = 0;
	
	UserAction atype = m_actions[action];
	switch(atype)
	{
		case PART:
		{
			qDebug("Part detected..");
// 			qDebug(msg);
			QString regexp = "("+channel_pattern+")";
			QRegExp rx(regexp);
			if( (pos = rx.search(msg)) != -1)
			{
				userLeavedChan(user,rx.cap(1));
		        }
			return;
		}
		default :
		{
			qDebug("Unhandled user message "+action);
			return;
		}
	}
}

void beConsole::nameReply(const QString & args)
{
	qDebug("nameReply");
	QString channel_pattern = "[A-Za-z0-9~!#\\-_@]+";
	QString nick_pattern = "[A-Za-z0-9|_\\-{}\\[\\]\\^`@+]+"; // no spaces in nicks
	QRegExp rx("=?@? ("+channel_pattern+") :(.*)");
	int pos;
	if( (pos = rx.search(args)) == -1)
	{
		qDebug("No matches for nameReply RegExp");
		return;
	}
	QString chan = rx.cap(1);
	QString nicks = rx.cap(2);
	
	beChannel* channel = m_channels[chan.lower()];
	if(!channel)
	{
		qDebug("No channel matching found : should create a new one !");
		
		QWidget* workspace = (QWidget*)this->parent()->parent();
		if(qstrcmp(workspace->className(),"QWorkspace") != 0)
		{
			Q_ASSERT(qstrcmp(workspace->className(),"QWorkspace") == 0);
			return;
		}
		channel = new beChannel(workspace,chan.lower(),this);
	}
	if(resetOnNameReply)
	{
		channel->resetUserList();
		resetOnNameReply = false;
	}
	
// 	qDebug("nameReply for channel "+chan.lower());
// 	qDebug("nameReply - nicks : "+nicks);
	rx.setPattern(nick_pattern);
	while ( (pos = rx.search(nicks, pos)) != -1 ) 
	{
            pos += rx.matchedLength();
	    channel->addUser(rx.cap(0),false); // do not sort the user list on each insert
        }
	channel->sortUserList(); // sorting the user list at the end
}


["beChannel.h" (text/x-chdr)]

#ifndef BE_CHANNEL_H
#define BE_CHANNEL_H

#include "beMDIWindow.h"

class QString;
class beConsole;

class beChannel : public beMDIWindow
{
	friend class beIRC;
	friend class beConsole;
	Q_OBJECT
	Q_PROPERTY( QString m_channel READ channel );
public :
	beChannel(QWidget * parent = 0, const QString & channel = 0, beConsole * console = 0);
	~beChannel();
	
	beLineView* lineview() { return m_pLineView; }

	QString channel() const;
	void msg(const QString & user,const QString & msg);
	void userJoin(const QString & username);
	void userLeaved(const QString & username);
	void addUser(const QString & username, bool sort = true);
	void delUser(const QString & username);
private slots:
	void say(const QString & msg);
protected :
	void sortUserList();
	void resetUserList();
private :
	
	beConsole* m_pConsole;
	QString m_channel;
	
};

#endif // ifndef BE_CHANNEL_H

["beConsole.h" (text/x-chdr)]

#ifndef BE_CONSOLE_H
#define BE_CONSOLE_H

#include "beMDIWindow.h"

class KviIrcServer;
class QString;
class beConsole;

class beConsole : beMDIWindow
{
	friend class beIRC;
	friend class beChannel;
	Q_OBJECT
public :
	beConsole(QWidget * parent = 0, const char * name = 0);
	~beConsole();
	
	KviIrcServer server();
	void registerChannel(beChannel * channel);
	void unregisterChannel(beChannel * channel);

	enum UserAction { JOIN, PART, QUIT, NICK, MODE };
protected :
	bool connectToServer();
private slots :
	virtual void hostFound();
	virtual void connected();
	virtual void socketReadyRead();
	virtual void disconnected();
	void send(const QString & command);
	void msgForChan(const QString & user, const QString & chan, QString msg);
	void userJoinedChan(const QString & user, const QString & chan);
	void userLeavedChan(const QString & user, const QString & chan);
	void handleNumericReply(int num, const QString & user, const QString & args);
	void handleUserMsg(QString user,const QString & action,QString msg);
	void nameReply(const QString & args);
signals :
	void receivedNumericReply(int num, const QString & user, const QString & args);
	void receivedUserMsg(QString user, const QString & action, QString msg);
private :
	KviIrcServer  *m_pSrv;
// 	KviProxy      * prx;
	
	QSocket * m_pQSocket;
	QMap<QString, beChannel*> m_channels;
	QMap<QString, UserAction> m_actions;
	bool resetOnNameReply;
};

#endif


>> Visit http://mail.kde.org/mailman/listinfo/kde-devel#unsub to unsubscribe <<


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic