[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