author | skyhusker <skyhusker> | 2005-02-03 21:47:50 (UTC) |
---|---|---|
committer | skyhusker <skyhusker> | 2005-02-03 21:47:50 (UTC) |
commit | 8aaae9e3eca7853e9c693d2401f721d75209acf7 (patch) (side-by-side diff) | |
tree | 6f700d154fac8510b322242496604d0ad7589377 /noncore/net/opieirc | |
parent | 875b3b63624308f4e50f82e17db27edeb9609d6c (diff) | |
download | opie-8aaae9e3eca7853e9c693d2401f721d75209acf7.zip opie-8aaae9e3eca7853e9c693d2401f721d75209acf7.tar.gz opie-8aaae9e3eca7853e9c693d2401f721d75209acf7.tar.bz2 |
Added DCC receive support
-rw-r--r-- | noncore/net/opieirc/dccprogress.cpp | 75 | ||||
-rw-r--r-- | noncore/net/opieirc/dccprogress.h | 35 | ||||
-rw-r--r-- | noncore/net/opieirc/dcctransfer.cpp | 41 | ||||
-rw-r--r-- | noncore/net/opieirc/dcctransfer.h | 44 | ||||
-rw-r--r-- | noncore/net/opieirc/dcctransferrecv.cpp | 53 | ||||
-rw-r--r-- | noncore/net/opieirc/dcctransferrecv.h | 21 | ||||
-rw-r--r-- | noncore/net/opieirc/dcctransfertab.cpp | 81 | ||||
-rw-r--r-- | noncore/net/opieirc/dcctransfertab.h | 41 | ||||
-rw-r--r-- | noncore/net/opieirc/ircmessageparser.cpp | 24 | ||||
-rw-r--r-- | noncore/net/opieirc/ircservertab.cpp | 4 | ||||
-rw-r--r-- | noncore/net/opieirc/ircservertab.h | 1 | ||||
-rw-r--r-- | noncore/net/opieirc/ircsession.cpp | 5 | ||||
-rw-r--r-- | noncore/net/opieirc/ircsession.h | 4 | ||||
-rw-r--r-- | noncore/net/opieirc/mainwindow.cpp | 20 | ||||
-rw-r--r-- | noncore/net/opieirc/mainwindow.h | 8 | ||||
-rw-r--r-- | noncore/net/opieirc/opieirc.pro | 9 |
16 files changed, 456 insertions, 10 deletions
diff --git a/noncore/net/opieirc/dccprogress.cpp b/noncore/net/opieirc/dccprogress.cpp new file mode 100644 index 0000000..28277f7 --- a/dev/null +++ b/noncore/net/opieirc/dccprogress.cpp @@ -0,0 +1,75 @@ +#include <qprogressbar.h> +#include <qlabel.h> +#include <qvbox.h> + +#include "dcctransfer.h" +#include "dcctransferrecv.h" +#include "dccprogress.h" + +DCCProgress::DCCProgress(DCCTransfer::Type type, Q_UINT32 ip4Addr, Q_UINT16 port, + const QString &filename, const QString &nickname, unsigned int size, QWidget *parent, char *name, WFlags f) + : QWidget(parent, name, f), m_vbox(new QVBox(this)), + m_label(new QLabel(m_vbox)), + m_bar(new QProgressBar(m_vbox)) +{ + + if (DCCTransfer::Recv == type) + m_transfer = new DCCTransferRecv(ip4Addr, port, filename, size); + + + connect(m_transfer, SIGNAL(progress(int)), this, SLOT(slotSetProgress(int))); + connect(m_transfer, SIGNAL(finished(DCCTransfer *, DCCTransfer::EndCode)), + this, SLOT(slotFinished(DCCTransfer *, DCCTransfer::EndCode))); + + m_label->setText(tr("Receiving file %1 from %2...").arg(m_transfer->filename()).arg(nickname)); + + m_label->show(); + m_bar->show(); + show(); + +} + +bool DCCProgress::finished() +{ + return ( m_transfer == 0); +} + +void DCCProgress::cancel() +{ + if (m_transfer) + m_transfer->cancel(); +} + +void DCCProgress::slotSetProgress(int progress) +{ + m_bar->setProgress(progress); +} + +void DCCProgress::slotFinished(DCCTransfer *transfer, DCCTransfer::EndCode code) +{ + if(transfer != m_transfer) + // WTF!! + return; + + QString msg; + + switch(code) { + case DCCTransfer::Successfull: + msg = tr("Successfully received %1").arg(m_transfer->filename()); + break; + case DCCTransfer::SelfAborted: + msg = tr("Aborted"); + break; + case DCCTransfer::PeerAborted: + msg = tr("Peer Aborted"); + break; + case DCCTransfer::Timeout: + msg = tr("Timeout"); + break; + } + + m_label->setText(msg); + delete m_transfer; + m_transfer = 0; +} + diff --git a/noncore/net/opieirc/dccprogress.h b/noncore/net/opieirc/dccprogress.h new file mode 100644 index 0000000..81b922e --- a/dev/null +++ b/noncore/net/opieirc/dccprogress.h @@ -0,0 +1,35 @@ +#ifndef DCCPROGRESS_H +#define DCCPROGRESS_H + + +#include <qwidget.h> + +#include "dcctransfer.h" + +class QProgressBar; +class QLabel; +class QVBox; + +class DCCProgress: public QWidget { + + Q_OBJECT +public: + DCCProgress(DCCTransfer::Type type, Q_UINT32 ip4Addr, Q_UINT16 port, + const QString &filename, const QString &nickname, unsigned int size, + QWidget *parent = 0, char *name = 0, WFlags f = 0); + + bool finished(); + void cancel(); + +public slots: + void slotSetProgress(int progress); + void slotFinished(DCCTransfer *transfer, DCCTransfer::EndCode code); + +private: + QVBox *m_vbox; + QLabel *m_label; + QProgressBar *m_bar; + DCCTransfer *m_transfer; +}; + +#endif diff --git a/noncore/net/opieirc/dcctransfer.cpp b/noncore/net/opieirc/dcctransfer.cpp new file mode 100644 index 0000000..cfa9f74 --- a/dev/null +++ b/noncore/net/opieirc/dcctransfer.cpp @@ -0,0 +1,41 @@ +#include <qsocket.h> +#include <qfile.h> + +#include "dcctransfer.h" + + +DCCTransfer::DCCTransfer(Q_UINT32 ip4Addr, Q_UINT16 port, const QString &filename, unsigned int size) + : m_socket(new QSocket), m_file(new QFile), m_bufSize(4096), m_buffer(new char[m_bufSize]), + m_ip4Addr(ip4Addr), m_port(port), m_totalSize(size), m_processedSize(0) +{ + m_file->setName(filename); +} + +DCCTransfer::~DCCTransfer() +{ + if(m_socket) + delete m_socket; + if(m_file) { + m_file->close(); + delete m_file; + } + if(m_buffer) + delete []m_buffer; +} + + +void DCCTransfer::cancel() +{ + if(m_socket) + m_socket->close(); + + emit(finished(DCCTransfer::SelfAborted)); +} + +QString DCCTransfer::filename() +{ + if(!m_file) + return QString::null; + + return m_file->name().mid(m_file->name().findRev('/') + 1); +} diff --git a/noncore/net/opieirc/dcctransfer.h b/noncore/net/opieirc/dcctransfer.h new file mode 100644 index 0000000..775ed24 --- a/dev/null +++ b/noncore/net/opieirc/dcctransfer.h @@ -0,0 +1,44 @@ +#ifndef DCCTRANSFER_H +#define DCCTRANSFER_H + +#include <qobject.h> + +class QSocket; +class QFile; +class QString; + +class DCCTransfer: public QObject { + Q_OBJECT +public: + enum Type { Send, Recv }; + enum EndCode { Successfull, SelfAborted, PeerAborted, Timeout }; + + DCCTransfer(Q_UINT32 ip4Addr, Q_UINT16 port, const QString &filename, unsigned int size); + virtual ~DCCTransfer(); + + void cancel(); + + QString filename(); + +signals: + virtual void finished(DCCTransfer *transfer, EndCode code); + virtual void progress(int progress); + +protected slots: + virtual void slotProcess() = 0; + virtual void slotFinished() = 0; + +protected: + QSocket *m_socket; + QFile *m_file; + unsigned int m_bufSize; + char *m_buffer; + Q_UINT32 m_ip4Addr; + Q_UINT16 m_port; + unsigned int m_totalSize; + unsigned int m_processedSize; + bool m_cancel; + bool m_timeout; +}; + +#endif diff --git a/noncore/net/opieirc/dcctransferrecv.cpp b/noncore/net/opieirc/dcctransferrecv.cpp new file mode 100644 index 0000000..58e8d09 --- a/dev/null +++ b/noncore/net/opieirc/dcctransferrecv.cpp @@ -0,0 +1,53 @@ +#include <netinet/in.h> + +#include <qfile.h> +#include <qsocket.h> +#include <qhostaddress.h> + +#include <opie2/odebug.h> + + +#include "dcctransferrecv.h" + + +DCCTransferRecv::DCCTransferRecv(Q_UINT32 ip4Addr, Q_UINT16 port, const QString &filename, unsigned int size) + : DCCTransfer(ip4Addr, port, filename, size) +{ + QHostAddress ip(ip4Addr); + m_socket->connectToHost(ip.toString(), m_port); + connect(m_socket, SIGNAL(readyRead()), this, SLOT(slotProcess())); + connect(m_socket, SIGNAL(connectionClosed()), this, SLOT(slotFinished())); + + m_file->open(IO_WriteOnly); +} + + +void DCCTransferRecv::slotProcess() +{ + int availableBytes = m_socket->bytesAvailable(); + int receivedBytes = 0; + + while(receivedBytes < availableBytes) { + int bytes = m_socket->readBlock(m_buffer, m_bufSize); + receivedBytes += bytes; + m_file->writeBlock(m_buffer, bytes); + } + + m_file->flush(); + m_processedSize += availableBytes; + unsigned long value = htonl(m_processedSize); + m_socket->writeBlock((char*)&value, sizeof(unsigned long)); + + emit (progress((m_processedSize * 100) / m_totalSize)); +} + +void DCCTransferRecv::slotFinished() +{ + m_file->close(); + + if(m_processedSize == m_totalSize) + emit(finished(this, DCCTransfer::Successfull)); + else + emit(finished(this, DCCTransfer::PeerAborted)); +} + diff --git a/noncore/net/opieirc/dcctransferrecv.h b/noncore/net/opieirc/dcctransferrecv.h new file mode 100644 index 0000000..bfc55ef --- a/dev/null +++ b/noncore/net/opieirc/dcctransferrecv.h @@ -0,0 +1,21 @@ +#ifndef DCCTRANSFERRECV_H +#define DCCTRANSFERRECV_H + +#include "dcctransfer.h" + + +class DCCTransferRecv: public DCCTransfer { + Q_OBJECT +public: + DCCTransferRecv(Q_UINT32 ip4Addr, Q_UINT16 port, const QString &filename, unsigned int size); + +signals: + void finished(DCCTransfer *transfer, DCCTransfer::EndCode code); + +public slots: + void slotProcess(); + void slotFinished(); +}; + +#endif + diff --git a/noncore/net/opieirc/dcctransfertab.cpp b/noncore/net/opieirc/dcctransfertab.cpp new file mode 100644 index 0000000..ea0ff1f --- a/dev/null +++ b/noncore/net/opieirc/dcctransfertab.cpp @@ -0,0 +1,81 @@ +#include <qlist.h> +#include <qlabel.h> +#include <qstring.h> +#include <qvbox.h> +#include <qmessagebox.h> + +#include "dcctransfer.h" +#include "dccprogress.h" +#include "mainwindow.h" +#include "dcctransfertab.h" + +#include <stdio.h> + +DCCTransferTab::DCCTransferTab(QWidget *parent, const char *name, WFlags f) + :IRCTab(parent, name, f), m_hbox(new QHBox(this)), m_parent(static_cast<MainWindow*>(parent)) +{ + m_description->setText(""); + m_layout->add(m_hbox); + m_hbox->show(); +} + +DCCTransferTab::~DCCTransferTab() +{ + if(m_hbox) + delete m_hbox; +} + +QString DCCTransferTab::title() +{ + return "DCC"; +} + +void DCCTransferTab::remove() +{ + //Clean finished transfers + for(QListIterator <DCCProgress> it(m_progressList); it.current(); ++it) { + DCCProgress *current = it.current(); + if (current->finished()) { + m_progressList.remove(current); + current->hide(); + delete current; + } + } + + if (m_progressList.count() > 0) { + int retval = QMessageBox::information( parentWidget() , tr("DCC Transfers in Progress"), + tr( "There are transfers in progress. <br>If you close this tab, they will be canceled." + "<br>Do you want to close it anyway?"), + tr("&Close"), tr("&Don't Close")); + if ( retval != 0 ) { + return; + } + //Cancel active transfers (user accepted) + for(QListIterator <DCCProgress> itr(m_progressList); itr.current(); ++itr) { + DCCProgress *current = itr.current(); + m_progressList.remove(current); + current->hide(); + current->cancel(); + delete current; + } + } + + //Remove + m_parent->killTab(this); +} + +bool DCCTransferTab::confirm(QWidget *parent, const QString &nickname, const QString &filename, unsigned int size) +{ + int retval = QMessageBox::information(parent, tr("DCC Transfer from %1").arg(nickname), + tr( "%1 is trying to send you the file %2\n(%3 bytes)").arg(nickname).arg(filename).arg(size), + tr("&Accept"), tr("&Reject")); + + return ( 0 == retval); + +} + +void DCCTransferTab::addTransfer(DCCTransfer::Type type, Q_UINT32 ip4Addr, Q_UINT16 port, + const QString &filename, const QString &nickname, unsigned int size) +{ + m_progressList.append(new DCCProgress(type, ip4Addr, port, filename, nickname, size, this)); +} diff --git a/noncore/net/opieirc/dcctransfertab.h b/noncore/net/opieirc/dcctransfertab.h new file mode 100644 index 0000000..a21323d --- a/dev/null +++ b/noncore/net/opieirc/dcctransfertab.h @@ -0,0 +1,41 @@ +#ifndef DCCTRANSFERTAB_H +#define DCCTRANSFERTAB_H + +#include "dcctransfer.h" +#include "irctab.h" + +template <class T> class QList; + +class DCCProgress; +class IRCSession; +class QString; +class QHBox; +class MainWindow; + +class DCCTransferTab: public IRCTab { + Q_OBJECT +public: + + DCCTransferTab(QWidget *parent = 0, const char *name = 0, WFlags f = 0); + ~DCCTransferTab(); + virtual QString DCCTransferTab::title(); + virtual IRCSession* DCCTransferTab::session(){return 0;}; + virtual void DCCTransferTab::appendText(QString){}; + virtual void DCCTransferTab::remove(); + virtual void DCCTransferTab::settingsChanged() {}; + void addTransfer(DCCTransfer::Type type, Q_UINT32 ip4Addr, + Q_UINT16 port, const QString &filename, + const QString &nickname, unsigned int size); + static bool confirm(QWidget *parent = 0, + const QString &nickname = QString::null, + const QString &filename = QString::null, + unsigned int size = 0); +private: + QHBox *m_hbox; + QList <DCCProgress> m_progressList; + MainWindow *m_parent; + +}; + +#endif + diff --git a/noncore/net/opieirc/ircmessageparser.cpp b/noncore/net/opieirc/ircmessageparser.cpp index ad9de2b..939cdae 100644 --- a/noncore/net/opieirc/ircmessageparser.cpp +++ b/noncore/net/opieirc/ircmessageparser.cpp @@ -1,55 +1,60 @@ #include <qtextstream.h> #include <qdatetime.h> +#include <opie2/ofiledialog.h> +#include <opie2/ofileselector.h> +#include <opie2/odebug.h> + #include "ircmessageparser.h" #include "ircversion.h" #include "ircchannelperson.h" -//#include "transferreceiver.h" +#include "dcctransfertab.h" +#include "ircservertab.h" /* Lookup table for literal commands */ IRCLiteralMessageParserStruct IRCMessageParser::literalParserProcTable[] = { { "PING", FUNC(parseLiteralPing) }, { "NOTICE", FUNC(parseLiteralNotice) }, { "JOIN", FUNC(parseLiteralJoin) }, { "PRIVMSG", FUNC(parseLiteralPrivMsg) }, { "NICK", FUNC(parseLiteralNick) }, { "PART", FUNC(parseLiteralPart) }, { "QUIT", FUNC(parseLiteralQuit) }, { "ERROR", FUNC(parseLiteralError) }, { "ERROR:", FUNC(parseLiteralError) }, { "MODE", FUNC(parseLiteralMode) }, { "KICK", FUNC(parseLiteralKick) }, { "TOPIC", FUNC(parseLiteralTopic) }, { 0 , 0 } }; /* Lookup table for literal commands */ IRCCTCPMessageParserStruct IRCMessageParser::ctcpParserProcTable[] = { { "PING", FUNC(parseCTCPPing) }, { "VERSION", FUNC(parseCTCPVersion) }, { "ACTION", FUNC(parseCTCPAction) }, { "DCC", FUNC(parseCTCPDCC) }, { 0 , 0 } }; /* Lookup table for numerical commands * According to: * http://www.faqs.org/rfcs/rfc1459.html * http://www.faqs.org/rfcs/rfc2812.html */ IRCNumericalMessageParserStruct IRCMessageParser::numericalParserProcTable[] = { { 1, "%1", "1", FUNC(parseNumericalServerName) }, // RPL_WELCOME { 2, "%1", "1", 0 }, // RPL_YOURHOST { 3, "%1", "1", 0 }, // RPL_CREATED { 4, QT_TR_NOOP("Server %1 version %2 supports usermodes '%3' and channelmodes '%4'"), "1:4", FUNC(parseNumericalServerFeatures) }, // RPL_MYINFO { 5, 0, 0, FUNC(parseNumericalServerProtocol) }, // RPL_BOUNCE, RPL_PROTOCTL { 250, "%1", "1", 0 }, // RPL_STATSCONN { 251, "%1", "1", 0 }, // RPL_LUSERCLIENT { 252, QT_TR_NOOP("There are %1 operators connected"), "1", 0 }, // RPL_LUSEROP { 253, QT_TR_NOOP("There are %1 unknown connection(s)"), "1", 0 }, // RPL_LUSERUNKNOWN { 254, QT_TR_NOOP("There are %1 channels formed"), "1", 0 }, // RPL_LUSERCHANNELS { 255, "%1", "1", 0 }, // RPL_LUSERME { 263, QT_TR_NOOP("Please wait a while and try again"), 0, 0 }, // RPL_TRYAGAIN { 265, "%1", "1", 0 }, // RPL_LOCALUSERS { 266, "%1", "1", 0 }, // RPL_GLOBALUSERS @@ -416,102 +421,115 @@ void IRCMessageParser::parseCTCPVersion(IRCMessage *message) { if(message->isCTCPRequest()) { m_session->m_connection->sendCTCPReply(mask.nick(), "VERSION", APP_VERSION " " APP_COPYSTR); output.setMessage(tr("Received a CTCP VERSION request from ") + mask.nick()); } else { output.setMessage("Received CTCP VERSION reply from " + mask.nick() + ":" + message->param(0)); } emit outputReady(output); } void IRCMessageParser::parseCTCPAction(IRCMessage *message) { IRCPerson mask(message->prefix()); QString dest = message->ctcpDestination(); if (dest.startsWith("#")) { IRCChannel *channel = m_session->getChannel(dest.lower()); if (channel) { IRCChannelPerson *person = channel->getPerson(mask.nick()); if (person) { IRCOutput output(OUTPUT_CHANACTION, "*" + mask.nick() + message->param(0)); output.addParam(channel); output.addParam(person); emit outputReady(output); } else { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("CTCP ACTION with unknown person - Desynchronized?"))); } } else { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("CTCP ACTION with unknown channel - Desynchronized?"))); } } else { if (message->ctcpDestination() == m_session->m_server->nick()) { IRCPerson *person = m_session->getPerson(mask.nick()); if (!person) { /* Person not yet known, create and add to the current session */ person = new IRCPerson(message->prefix()); m_session->addPerson(person); } IRCOutput output(OUTPUT_QUERYACTION, "*" + mask.nick() + message->param(0)); output.addParam(person); emit outputReady(output); } else { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("CTCP ACTION with bad recipient"))); } } } void IRCMessageParser::parseCTCPDCC(IRCMessage *message) { QStringList params = QStringList::split(' ', message->param(0).stripWhiteSpace()); + + if(params[0] == "SEND") { + QString nickname = IRCPerson(message->prefix()).nick(); if( params.count() != 5) { - emit outputReady(IRCOutput(OUTPUT_ERROR, tr("Malformed DCC request from ") + IRCPerson(message->prefix()).nick())); + emit outputReady(IRCOutput(OUTPUT_ERROR, tr("Malformed DCC request from %1").arg(nickname))); return; } + bool accepted = DCCTransferTab::confirm(static_cast<QWidget*>(m_session->parent()), nickname, params[1], params[4].toUInt()); + if(!accepted) + return; + QString filename = Opie::Ui::OFileDialog::getSaveFileName(Opie::Ui::OFileSelector::EXTENDED_ALL, + QString::null, params[1], MimeTypes(), 0, tr("Save As")); + if(filename.isEmpty()) + return; - //TransferReceiver *foo = new TransferReceiver(params[2].toUInt(), params[3].toUInt(), params[1], params[4].toUInt()); + odebug << "Receiving file " << filename << " from " << nickname << oendl; + static_cast<IRCServerTab*>(m_session->parent())->mainwindow()->addDCC(DCCTransfer::Recv, params[2].toUInt(), params[3].toUInt(), + filename, nickname, params[4].toUInt()); + } } void IRCMessageParser::parseLiteralMode(IRCMessage *message) { IRCPerson mask(message->prefix()); if (message->param(0).startsWith("#")) { IRCChannel *channel = m_session->getChannel(message->param(0).lower()); if (channel) { QString temp, parameters = message->allParameters().right(message->allParameters().length() - channel->channelname().length() - 1); QTextIStream stream(¶meters); bool set = FALSE; while (!stream.atEnd()) { stream >> temp; if (temp.startsWith("+")) { set = TRUE; temp = temp.right(1); } else if (temp.startsWith("-")) { set = FALSE; temp = temp.right(1); } else { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("Mode change has unknown type"))); return; } if (temp == "o") { stream >> temp; IRCChannelPerson *person = channel->getPerson(temp); if (person) { IRCOutput output(OUTPUT_CHANPERSONMODE, person->setOp(mask.nick(), set)); output.addParam(channel); output.addParam(person); emit outputReady(output); } else { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("Mode change with unknown person - Desynchronized?"))); } } else if (temp == "v") { stream >> temp; IRCChannelPerson *person = channel->getPerson(temp); if (person) { IRCOutput output(OUTPUT_CHANPERSONMODE, person->setVoice(mask.nick(), set)); output.addParam(channel); output.addParam(person); emit outputReady(output); diff --git a/noncore/net/opieirc/ircservertab.cpp b/noncore/net/opieirc/ircservertab.cpp index 62a06e8..d3c0448 100644 --- a/noncore/net/opieirc/ircservertab.cpp +++ b/noncore/net/opieirc/ircservertab.cpp @@ -368,48 +368,52 @@ void IRCServerTab::display(IRCOutput output) { } break; case OUTPUT_NICKCHANGE: { QString *nick = static_cast<QString*>(output.getParam(0)); if(!nick) { appendText("<font color=\"" + m_notificationColor + "\">"+output.htmlMessage()+"</font><br>"); break; } QListIterator<IRCChannelTab> it(m_channelTabs); for (; it.current(); ++it) { if (it.current()->list()->hasPerson(*nick)) { it.current()->appendText("<font color=\"" + m_notificationColor + "\">"+output.htmlMessage()+"</font><br>"); } } delete nick; } break; case OUTPUT_OTHERJOIN: case OUTPUT_OTHERKICK: case OUTPUT_CHANPERSONMODE: case OUTPUT_OTHERPART: { IRCChannelTab *channelTab = getTabForChannel((IRCChannel *)output.getParam(0)); channelTab->appendText("<font color=\"" + m_notificationColor + "\">"+output.htmlMessage()+"</font><br>"); channelTab->list()->update(); } break; case OUTPUT_CTCP: appendText("<font color=\"" + m_notificationColor + "\">" + output.htmlMessage() + "</font><br>"); break; case OUTPUT_ERROR: appendText("<font color=\"" + m_errorColor + "\">" + output.htmlMessage() + "</font><br>"); break; case OUTPUT_TITLE: m_description->setText(output.message()); break; default: appendText("<font color=\"" + m_serverColor + "\">" + output.htmlMessage() + "</font><br>"); break; } } void IRCServerTab::slotUpdateChannels() { QListIterator<IRCChannelTab> it(m_channelTabs); for (; it.current(); ++it) { it.current()->list()->update(); } } +MainWindow *IRCServerTab::mainwindow() { + return m_mainWindow; +} + diff --git a/noncore/net/opieirc/ircservertab.h b/noncore/net/opieirc/ircservertab.h index 42f6f57..fe48a3b 100644 --- a/noncore/net/opieirc/ircservertab.h +++ b/noncore/net/opieirc/ircservertab.h @@ -1,82 +1,83 @@ /* OpieIRC - An embedded IRC client Copyright (C) 2002 Wenzel Jakob This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __IRCSERVERTAB_H #define __IRCSERVERTAB_H #include <qpe/qpeapplication.h> #include <qpe/qcopenvelope_qws.h> #include "irctab.h" #include "ircsession.h" #include "mainwindow.h" #include "ircchanneltab.h" #include "ircquerytab.h" #include "ircmisc.h" class IRCServerTab : public IRCTab { Q_OBJECT public: static bool containsPing(const QString& text, IRCServerTab *tab); /* IRCTab implementation */ IRCServerTab(IRCServer server, MainWindow *mainWindow, QWidget *parent = 0, const char *name = 0, WFlags f = 0); ~IRCServerTab(); QString title(); IRCSession *session(); IRCServer *server(); + MainWindow *mainwindow(); /* Start the server session */ void doConnect(); // QString *mynick(); /* Remove tabs from the internal tab lists */ void removeChannelTab(IRCChannelTab *tab); void removeQueryTab(IRCQueryTab *tab); /* Return tabs from the internal tab lists */ IRCChannelTab *getTabForChannel(IRCChannel *channel); IRCQueryTab *getTabForQuery(IRCPerson *person); /* Add tabs to the internal tab lists */ void addQueryTab(IRCQueryTab *tab); /* Execute a user command such as /join, /msg etc */ void executeCommand(IRCTab *tab, QString line); protected: void appendText(QString text); public slots: void scrolling(); void remove(); void processCommand(); void settingsChanged(); void slotUpdateChannels(); protected slots: void display(IRCOutput output); protected: int m_lines; bool m_close; IRCServer m_server; IRCSession *m_session; MainWindow *m_mainWindow; QTextView *m_textview; IRCHistoryLineEdit *m_field; /* Channel tabs associated with this server tab */ QList<IRCChannelTab> m_channelTabs; /* Query tabs associated with this server tab */ QList<IRCQueryTab> m_queryTabs; }; #endif /* __IRCSERVERTAB_H */ diff --git a/noncore/net/opieirc/ircsession.cpp b/noncore/net/opieirc/ircsession.cpp index fd8ba72..c8d7869 100644 --- a/noncore/net/opieirc/ircsession.cpp +++ b/noncore/net/opieirc/ircsession.cpp @@ -1,59 +1,60 @@ #include "ircsession.h" #include "ircmessageparser.h" #include "ircchannelperson.h" #include "ircversion.h" -IRCSession::IRCSession(QWidget *parent, IRCServer *server) { +IRCSession::IRCSession(QObject *parent, IRCServer *server) + : QObject(parent) +{ m_server = server; m_connection = new IRCConnection(m_server); m_parser = new IRCMessageParser(this); - m_parent = parent; connect(m_connection, SIGNAL(messageArrived(IRCMessage*)), this, SLOT(handleMessage(IRCMessage*))); connect(m_parser, SIGNAL(outputReady(IRCOutput)), this, SIGNAL(outputReady(IRCOutput))); connect(m_connection, SIGNAL(outputReady(IRCOutput)), this, SIGNAL(outputReady(IRCOutput))); } IRCSession::~IRCSession() { /* We want this to get deleted automatically */ m_channels.setAutoDelete(TRUE); m_people.setAutoDelete(TRUE); delete m_parser; delete m_connection; } void IRCSession::beginSession() { m_connection->doConnect(); } void IRCSession::join(QString channelname) { m_connection->sendLine("JOIN " + channelname); } void IRCSession::quit(){ m_connection->sendLine("QUIT :[OI] I'm too good to need a reason"); } void IRCSession::quit(QString message){ m_connection->sendLine("QUIT :" + message); } void IRCSession::topic(IRCChannel *channel, QString message){ m_connection->sendLine("TOPIC :" + channel->channelname() + " " + message); } void IRCSession::mode(IRCChannel *channel, QString message){ m_connection->sendLine("MODE " + channel->channelname() + " " + message); } void IRCSession::mode(IRCPerson *person, QString message){ m_connection->sendLine("MODE " + person->nick() + " " + message); } void IRCSession::mode(QString message){ m_connection->sendLine("MODE " + message); } void IRCSession::raw(QString message){ m_connection->sendLine(message); diff --git a/noncore/net/opieirc/ircsession.h b/noncore/net/opieirc/ircsession.h index 7c91893..23a2540 100644 --- a/noncore/net/opieirc/ircsession.h +++ b/noncore/net/opieirc/ircsession.h @@ -1,96 +1,96 @@ /* OpieIRC - An embedded IRC client Copyright (C) 2002 Wenzel Jakob This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __IRCSESSION_H #define __IRCSESSION_H #include <qstring.h> #include <qlist.h> #include "ircserver.h" #include "ircconnection.h" #include "ircmessage.h" #include "ircchannel.h" #include "ircoutput.h" class IRCMessageParser; +class IRCServerTab; /* The IRCSession stores all information relating to the connection to one IRC server. IRCSession makes it possible to run multiple IRC server connections from within the same program */ class IRCSession : public QObject { friend class IRCMessageParser; Q_OBJECT public: - IRCSession(QWidget *parent, IRCServer *server); + IRCSession(QObject *parent, IRCServer *server); ~IRCSession(); void join(QString channel); void quit(QString message); void quit(); void raw(QString message); void topic(IRCChannel *channel, QString message); void mode(IRCChannel *channel, QString message); void mode(IRCPerson *person, QString message); void mode(QString message); void part(IRCChannel *channel); void op(IRCChannel *channel, IRCPerson *person); void kick(IRCChannel *channel, IRCPerson *person); void kick(IRCChannel *channel, IRCPerson *person, QString message); void beginSession(); bool isSessionActive(); void endSession(); bool isLoggedIn(); void sendMessage(IRCPerson *person, QString message); void sendMessage(IRCChannel *channel, QString message); void sendAction(IRCPerson *person, QString message); void sendAction(IRCChannel *channel, QString message); void updateNickname(const QString &oldNickname, const QString &newNickname); void setValidUsermodes(const QString &modes); void setValidChannelmodes(const QString &modes); void whois(const QString &nickname); void sendCTCPPing(const QString &nickname); void sendCTCPRequest(const QString &nickname, const QString &type, const QString &args); void sendCTCPReply(const QString &nickname, const QString &type, const QString &args); IRCChannel *getChannel(QString channelname); IRCPerson *getPerson(QString nickname); protected: void addPerson(IRCPerson *person); void addChannel(IRCChannel *channel); void removeChannel(IRCChannel *channel); void removePerson(IRCPerson *person); void getChannelsByPerson(IRCPerson *person, QList<IRCChannel> &channels); protected slots: void handleMessage(IRCMessage *message); signals: void outputReady(IRCOutput output); void updateChannels(); protected: IRCServer *m_server; IRCConnection *m_connection; IRCMessageParser *m_parser; QList<IRCChannel> m_channels; QList<IRCPerson> m_people; QString m_validUsermodes; QString m_validChannelmodes; - QWidget *m_parent; }; #endif /* __IRCSESSION_H */ diff --git a/noncore/net/opieirc/mainwindow.cpp b/noncore/net/opieirc/mainwindow.cpp index 1811a0c..3d60107 100644 --- a/noncore/net/opieirc/mainwindow.cpp +++ b/noncore/net/opieirc/mainwindow.cpp @@ -1,139 +1,159 @@ #include <qmenubar.h> #include <qpe/resource.h> #include <opie2/odebug.h> #include <qwhatsthis.h> #include "mainwindow.h" #include "ircservertab.h" +#include "dcctransfertab.h" #include "ircserverlist.h" #include "ircsettings.h" +#include <stdio.h> + + QString MainWindow::appCaption() { return QObject::tr("Opie IRC"); } MainWindow::MainWindow(QWidget *parent, const char *name, WFlags) : QMainWindow(parent, name, WStyle_ContextHelp) { setCaption(tr("IRC Client")); m_tabWidget = new IRCTabWidget(this); QWhatsThis::add(m_tabWidget, tr("Server connections, channels, queries and other things will be placed here")); connect(m_tabWidget, SIGNAL(currentChanged(QWidget*)), this, SLOT(selected(QWidget*))); setCentralWidget(m_tabWidget); setToolBarsMovable(FALSE); QMenuBar *menuBar = new QMenuBar(this); QPopupMenu *irc = new QPopupMenu(this); menuBar->insertItem(tr("IRC"), irc); QAction *a = new QAction(tr("New connection"), Resource::loadPixmap("pass"), QString::null, 0, this, 0); connect(a, SIGNAL(activated()), this, SLOT(newConnection())); a->setWhatsThis(tr("Create a new connection to an IRC server")); a->addTo(irc); a = new QAction(tr("Settings"), Resource::loadPixmap("SettingsIcon"), QString::null, 0, this, 0); a->setWhatsThis(tr("Configure OpieIRC's behavior and appearance")); connect(a, SIGNAL(activated()), this, SLOT(settings())); a->addTo(irc); + m_dccTab = 0; loadSettings(); } /*IRCTabWidget MainWindow::getTabWidget(){ return m_tabWidget; } */ void MainWindow::loadSettings() { Config config("OpieIRC"); config.setGroup("OpieIRC"); IRCTab::m_backgroundColor = config.readEntry("BackgroundColor", "#FFFFFF"); IRCTab::m_textColor = config.readEntry("TextColor", "#000000"); IRCTab::m_errorColor = config.readEntry("ErrorColor", "#FF0000"); IRCTab::m_selfColor = config.readEntry("SelfColor", "#CC0000"); IRCTab::m_otherColor = config.readEntry("OtherColor", "#0000BB"); IRCTab::m_serverColor = config.readEntry("ServerColor", "#0000FF"); IRCTab::m_notificationColor = config.readEntry("NotificationColor", "#AA3300"); IRCTab::m_maxLines = config.readNumEntry("Lines", 100); IRCTab::setUseTimeStamps( config.readBoolEntry("DisplayTime", false ) ); } void MainWindow::selected(QWidget *) { m_tabWidget->setTabColor(m_tabWidget->currentPageIndex(), black); emit updateScroll(); } void MainWindow::addTab(IRCTab *tab) { connect(tab, SIGNAL(changed(IRCTab*)), this, SLOT(changeEvent(IRCTab*))); connect(tab, SIGNAL(ping (const QString&)), this, SLOT(slotPing(const QString&))); connect(tab, SIGNAL(nextTab()), this, SLOT(slotNextTab())); connect(tab, SIGNAL(prevTab()), this, SLOT(slotPrevTab())); m_tabWidget->addTab(tab, tab->title()); m_tabWidget->showPage(tab); tab->setID(m_tabWidget->currentPageIndex()); m_tabs.append(tab); } void MainWindow::changeEvent(IRCTab *tab) { if (tab->id() != m_tabWidget->currentPageIndex()) m_tabWidget->setTabColor(tab->id(), blue); } void MainWindow::killTab(IRCTab *tab, bool imediate) { + if (tab == m_dccTab) + m_dccTab = 0; + m_toDelete.append( tab ); if ( imediate ) slotKillTabsLater(); else QTimer::singleShot(0, this, SLOT(slotKillTabsLater()) ); } void MainWindow::slotKillTabsLater() { for ( QListIterator<IRCTab> it(m_toDelete); it.current(); ++it ) { m_tabWidget->removePage( it.current() ); odebug << it.current() << oendl; m_tabs.remove( it.current() ); } m_toDelete.setAutoDelete( true ); m_toDelete.clear(); m_toDelete.setAutoDelete( false ); } void MainWindow::newConnection() { IRCServerList list(this, "ServerList", TRUE); if (list.exec() == QDialog::Accepted && list.hasServer()) { IRCServerTab *serverTab = new IRCServerTab(list.server(), this, m_tabWidget); addTab(serverTab); serverTab->doConnect(); } } void MainWindow::settings() { IRCSettings settings(this, "Settings", TRUE); if (settings.exec() == QDialog::Accepted) { QListIterator<IRCTab> it(m_tabs); for (; it.current(); ++it) { /* Inform all tabs about the new settings */ it.current()->settingsChanged(); } } } void MainWindow::slotNextTab() { int i = m_tabWidget->currentPageIndex (); m_tabWidget->setCurrentPage ( i+1 ); int j = m_tabWidget->currentPageIndex (); if ( i == j ) m_tabWidget->setCurrentPage ( 1 ); } void MainWindow::slotPrevTab() { int i = m_tabWidget->currentPageIndex (); if ( i > 1 ) m_tabWidget->setCurrentPage ( i-1 ); } void MainWindow::slotPing( const QString& /*channel*/ ) { raise(); } +void MainWindow::addDCC(DCCTransfer::Type type, Q_UINT32 ip4Addr, Q_UINT16 port, + const QString &filename, const QString &nickname, unsigned int size) { + + if (!m_dccTab) { + m_dccTab = new DCCTransferTab(this); + addTab(m_dccTab); + m_dccTab->show(); + } + + m_dccTab->addTransfer(type, ip4Addr, port, filename, nickname, size); +} + diff --git a/noncore/net/opieirc/mainwindow.h b/noncore/net/opieirc/mainwindow.h index abf205d..873a685 100644 --- a/noncore/net/opieirc/mainwindow.h +++ b/noncore/net/opieirc/mainwindow.h @@ -1,61 +1,67 @@ /* OpieIRC - An embedded IRC client Copyright (C) 2002 Wenzel Jakob This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __MAINWINDOW_H #define __MAINWINDOW_H #include <qmainwindow.h> #include <qaction.h> #include <qlist.h> -#include "mainwindow.h" + +#include "dcctransfer.h" #include "ircmisc.h" #include "irctab.h" +class DCCTransferTab; + class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = 0, const char *name = 0, WFlags f = 0); // IRCTabWidget getTabWidget(); void addTab(IRCTab *tab); void killTab(IRCTab *tab, bool now = false); static QString appName() { return QString::fromLatin1("opieirc"); } static QString appCaption(); + void addDCC(DCCTransfer::Type type, Q_UINT32 ip4Addr, Q_UINT16 port, + const QString &filename, const QString &nickname, unsigned int size); signals: void updateScroll(); protected slots: void newConnection(); void settings(); void selected(QWidget *); void changeEvent(IRCTab *); void slotNextTab(); void slotPrevTab(); void slotPing(const QString&); void slotKillTabsLater(); protected: void loadSettings(); protected: IRCTabWidget *m_tabWidget; QList<IRCTab> m_tabs; QList<IRCTab> m_toDelete; + DCCTransferTab *m_dccTab; }; #endif /* __MAINWINDOW_H */ diff --git a/noncore/net/opieirc/opieirc.pro b/noncore/net/opieirc/opieirc.pro index 1ef9be2..5e91450 100644 --- a/noncore/net/opieirc/opieirc.pro +++ b/noncore/net/opieirc/opieirc.pro @@ -1,30 +1,35 @@ CONFIG = qt warn_on quick-app HEADERS = ircchannel.h ircconnection.h \ ircmessage.h \ ircmessageparser.h ircoutput.h \ ircperson.h ircserver.h ircsession.h \ mainwindow.h irctab.h ircservertab.h \ ircchanneltab.h ircchannellist.h \ ircserverlist.h ircservereditor.h \ ircquerytab.h ircsettings.h ircmisc.h \ - ircchannelperson.h + ircchannelperson.h dcctransfertab.h \ + dccprogress.h dcctransfer.h \ + dcctransferrecv.h SOURCES = ircchannel.cpp ircconnection.cpp \ ircmessage.cpp \ ircmessageparser.cpp ircoutput.cpp \ ircperson.cpp ircserver.cpp \ ircsession.cpp main.cpp mainwindow.cpp \ irctab.cpp ircservertab.cpp \ ircchanneltab.cpp ircchannellist.cpp \ ircserverlist.cpp ircservereditor.cpp \ ircquerytab.cpp ircsettings.cpp ircmisc.cpp \ - ircchannelperson.cpp + ircchannelperson.cpp dcctransfertab.cpp \ + dccprogress.cpp dcctransfer.cpp \ + dcctransferrecv.cpp + INCLUDEPATH += $(OPIEDIR)/include DEPENDPATH += $(OPIEDIR)/include PRECOMPILED_HEADER = stable.h LIBS += -lqpe -lopiecore2 -lopieui2 -lqtaux2 TARGET = opieirc include( $(OPIEDIR)/include.pro ) |