Mercurial > octave-nkf
changeset 13679:e272af3f252d
Renamed qirc to irc.
author | Jacob Dawid <jacob.dawid@googlemail.com> |
---|---|
date | Sun, 25 Sep 2011 21:13:59 +0200 |
parents | 117ae3cb156e |
children | 3a2b09503fed |
files | gui/octave-gui.pro gui/src/irc/IRCClientImpl.cpp gui/src/irc/IRCClientImpl.h gui/src/irc/IRCClientInterface.h gui/src/irc/IRCCodes.h gui/src/irc/IRCWidget.cpp gui/src/irc/IRCWidget.h gui/src/irc/Makefile.am gui/src/qirc/IRCClientImpl.cpp gui/src/qirc/IRCClientImpl.h gui/src/qirc/IRCClientInterface.h gui/src/qirc/IRCCodes.h gui/src/qirc/IRCWidget.cpp gui/src/qirc/IRCWidget.h gui/src/qirc/Makefile.am |
diffstat | 15 files changed, 1898 insertions(+), 1898 deletions(-) [+] |
line wrap: on
line diff
--- a/gui/octave-gui.pro Sun Sep 25 21:12:47 2011 +0200 +++ b/gui/octave-gui.pro Sun Sep 25 21:13:59 2011 +0200 @@ -65,7 +65,7 @@ src/FileEditorMdiSubWindow.cpp \ src/BrowserWidget.cpp \ src/ImageViewerMdiSubWindow.cpp \ - src/qirc/IRCWidget.cpp \ + src/irc/IRCWidget.cpp \ src/SettingsDialog.cpp \ src/OctaveGUI.cpp \ src/ResourceManager.cpp \ @@ -73,7 +73,7 @@ src/backend/OctaveCallbackThread.cpp \ src/backend/OctaveLink.cpp \ src/backend/OctaveMainThread.cpp \ - src/qirc/IRCClientImpl.cpp \ + src/irc/IRCClientImpl.cpp \ src/terminal/TerminalEmulation.cpp \ src/terminal/LinuxTerminalEmulation.cpp \ src/backend/ReadlineAdapter.cpp \ @@ -92,15 +92,15 @@ src/FileEditorMdiSubWindow.h \ src/BrowserWidget.h \ src/ImageViewerMdiSubWindow.h \ - src/qirc/IRCWidget.h \ + src/irc/IRCWidget.h \ src/SettingsDialog.h \ src/ResourceManager.h \ src/CommandLineParser.h \ src/backend/OctaveCallbackThread.h \ src/backend/OctaveLink.h \ src/backend/OctaveMainThread.h \ - src/qirc/IRCClientInterface.h \ - src/qirc/IRCClientImpl.h \ + src/irc/IRCClientInterface.h \ + src/irc/IRCClientImpl.h \ src/terminal/TerminalEmulation.h \ src/terminal/LinuxTerminalEmulation.h \ src/backend/ReadlineAdapter.h \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gui/src/irc/IRCClientImpl.cpp Sun Sep 25 21:13:59 2011 +0200 @@ -0,0 +1,511 @@ +/* OctaveGUI - A graphical user interface for Octave + * Copyright (C) 2011 Jacob Dawid (jacob.dawid@googlemail.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "IRCClientImpl.h" + +IRCServerMessage::IRCServerMessage (const QString& serverMessage) +{ + if (serverMessage.isEmpty ()) + return; + + int position = 0; + QString buffer; + + m_nick = ""; + m_user = ""; + m_host = ""; + + // A server message starting with a prefix indicates + // a prefix. A prefix has the format: + // :nick!user@host + // followed by a space character. + if (serverMessage.startsWith (":")) + { + position++; + while ((position < serverMessage.size ()) + &&(serverMessage.at (position) != '!') + && !serverMessage.at (position).isSpace ()) + { + buffer.append (serverMessage.at (position)); + position++; + } + m_nick = buffer, buffer.clear (), position++; + + // If it belongs to the prefix, it must be concatenanted neatlessly without + // any spaces. + if (!serverMessage.at (position - 1).isSpace ()) + { + while ((position < serverMessage.size ()) + && serverMessage.at (position) != '@') + { + buffer.append (serverMessage.at (position)); + position++; + } + m_user = buffer, buffer.clear (), position++; + } + + // If it belongs to the prefix, it must be concatenanted neatlessly without + // any spaces. + if (!serverMessage.at (position - 1).isSpace ()) + { + while ((position < serverMessage.size ()) + && serverMessage.at (position) != ' ') + { + buffer.append (serverMessage.at (position)); + position++; + } + m_host = buffer, buffer.clear (), position++; + } + } + + // The next part is the command. The command can either be numeric + // or a written command. + while ((position < serverMessage.size ()) + && !serverMessage.at (position).isSpace ()) + { + buffer.append (serverMessage.at (position)); + position++; + } + m_command = buffer.toUpper (), buffer.clear (), position++; + m_codeNumber = m_command.toInt (&m_isNumeric); + + // Next: a list of parameters. If any of these parameters + // starts with a colon, we have to read everything that follows + // as a single parameter. + bool readUntilEnd = false; + while (position < serverMessage.size ()) + { + if (buffer.isEmpty () && !readUntilEnd && (serverMessage.at (position) == ':')) + { + readUntilEnd = true; + } + else + { + if (readUntilEnd) + { + buffer.append (serverMessage.at (position)); + } + else + { + if (serverMessage.at (position).isSpace ()) + { + if (!buffer.isEmpty ()) + { + m_parameters.append (buffer); + buffer.clear (); + } + } + else + { + buffer.append (serverMessage.at (position)); + } + } + } + position++; + } + + if (!buffer.isEmpty ()) + { + // We need to chop off \r\n here. + buffer.chop (2); + m_parameters.append (buffer); + } +} + +int +IRCServerMessage::numericValue () +{ + if (m_isNumeric) + return m_codeNumber; + return -1; +} + +QString +IRCServerMessage::parameter (int index) +{ + if (index >= 0 && index < m_parameters.size ()) + return m_parameters.at (index); + return ""; +} + + +IRCChannelProxyImpl::IRCChannelProxyImpl (IRCClientInterface *clientInterface, const QString& channelName, QObject *parent) + : IRCChannelProxyInterface (clientInterface, channelName, parent), + m_clientInterface (clientInterface) +{ + m_channelName = channelName; + connect (clientInterface, SIGNAL (nicknameChanged (QString,QString)), + this, SLOT (handleNickChange (QString,QString))); +} + +QTextDocument * +IRCChannelProxyImpl::conversationModel () +{ + return &m_conversationModel; +} + +QStringListModel * +IRCChannelProxyImpl::userListModel () +{ + return &m_userListModel; +} + +QString +IRCChannelProxyImpl::channelName () +{ + return m_channelName; +} + +void +IRCChannelProxyImpl::setNickList (const QStringList &nickList) +{ + m_userList = nickList; + m_userListModel.setStringList (nickList); +} + +void +IRCChannelProxyImpl::sendMessage (const QString& message) +{ + QStringList arguments; + arguments << m_channelName; + arguments << message; + m_clientInterface->sendIRCCommand (IRCCommand::PrivateMessage, arguments); +} + +void +IRCChannelProxyImpl::sendJoinRequest () +{ + m_clientInterface->sendIRCCommand (IRCCommand::Join, QStringList (m_channelName)); +} + + +void +IRCChannelProxyImpl::leave (const QString& reason) +{ + Q_UNUSED (reason); +} + +void +IRCChannelProxyImpl::handleNickChange (const QString &oldNick, const QString &newNick) +{ + m_userList = m_userListModel.stringList (); + m_userList.removeAll (oldNick); + m_userList.append (newNick); + m_userListModel.setStringList (m_userList); +} + +void +IRCChannelProxyImpl::handleJoin (const QString &nick) +{ + m_userList = m_userListModel.stringList (); + m_userList.append (nick); + m_userListModel.setStringList (m_userList); +} + +IRCClientImpl::IRCClientImpl (QObject *parent) + : IRCClientInterface (parent) +{ + m_loggedIn = false; + connect (&m_tcpSocket, SIGNAL (connected ()), this, SLOT (handleConnected ())); + connect (&m_tcpSocket, SIGNAL (disconnected ()), this, SLOT (handleDisconnected ())); + connect (&m_tcpSocket, SIGNAL (readyRead ()), this, SLOT (handleReadyRead ())); +} + +IRCClientImpl::~IRCClientImpl () +{ + foreach (IRCChannelProxyInterface *ircChannelProxy, m_channels) + { + delete ircChannelProxy; + } +} + +void +IRCClientImpl::connectToHost (const QHostAddress& host, int port, const QString& initialNick) +{ + m_host = host; + m_nickname = initialNick; + m_tcpSocket.connectToHost(host, port); +} + +void +IRCClientImpl::disconnect () +{ + m_tcpSocket.disconnect (); +} + +void +IRCClientImpl::reconnect () +{ + disconnect (); + connectToHost (m_host, m_port, m_nickname); +} + +bool +IRCClientImpl::isConnected () +{ + return m_connected; +} + +bool +IRCClientImpl::isLoggedIn () +{ + return m_loggedIn; +} + +const QHostAddress& +IRCClientImpl::host() +{ + return m_host; +} + +int +IRCClientImpl::port() +{ + return m_port; +} + +IRCChannelProxyInterface * +IRCClientImpl::ircChannelProxy (const QString &channel) +{ + if (!m_channels.contains (channel)) + m_channels[channel] = new IRCChannelProxyImpl(this, channel); + return m_channels[channel]; +} + +void +IRCClientImpl::sendNicknameChangeRequest (const QString &nickname) +{ + sendIRCCommand (IRCCommand::Nick, QStringList (nickname)); +} + +void +IRCClientImpl::sendPrivateMessage (const QString &recipient, const QString &message) +{ + QStringList arguments; + arguments << recipient; + arguments << message; + sendIRCCommand (IRCCommand::PrivateMessage, arguments); +} + +const QString& +IRCClientImpl::nickname () +{ + return m_nickname; +} + +void +IRCClientImpl::handleConnected () +{ + m_connected = true; + QStringList arguments; + arguments << "na" << "0" << "0" << "na"; + sendIRCCommand (IRCCommand::User, arguments); + sendNicknameChangeRequest (m_nickname); + emit connected (m_host.toString ()); +} + +void +IRCClientImpl::handleDisconnected () +{ + m_connected = false; + emit disconnected (); +} + +void +IRCClientImpl::handleReadyRead () +{ + QByteArray line; + do + { + line = m_tcpSocket.readLine(); + if (line.size ()) + handleIncomingLine(QString::fromUtf8(line.data ())); + else + break; + } + while (true); +} + +void +IRCClientImpl::handleNicknameChanged (const QString &oldNick, const QString &newNick) +{ + // Check if our nickname changed. + if (oldNick == m_nickname) + { + m_nickname = newNick; + emit userNicknameChanged (m_nickname); + } + emit nicknameChanged (oldNick, newNick); +} + +void +IRCClientImpl::handleUserJoined (const QString &nick, const QString &channel) +{ + ircChannelProxy (channel)->handleJoin (nick); + emit userJoined (nick, channel); +} + +void +IRCClientImpl::handleUserQuit (const QString &nick, const QString &reason) +{ + emit userQuit (nick, reason); +} + +void +IRCClientImpl::handleIncomingLine (const QString &line) +{ + if (m_connected && !line.isEmpty()) + { + IRCServerMessage ircServerMessage(line); + if (ircServerMessage.isNumeric () == true) + { + switch (ircServerMessage.numericValue ()) + { + case IRCReply::Welcome: + m_loggedIn = true; + emit userNicknameChanged (nickname ()); + emit loggedIn (nickname ()); + break; + case IRCError::NicknameInUse: + case IRCError::NickCollision: + // If we are already logged in, the user attempted to + // switch to a username that is already existing. + // In that case warn him. + if (isLoggedIn ()) + { + emit error ("The nickname is already in use."); + } + // Otherwise we are attempting to log in to the server. + // Change the nick so that we can at least log in. + else + { + m_nickname += "_"; + sendNicknameChangeRequest (m_nickname); + } + break; + case IRCError::PasswordMismatch: + emit error ("The password you provided is not correct."); + break; + case IRCReply::MessageOfTheDayStart: + case IRCReply::MessageOfTheDay: + case IRCReply::MessageOfTheDayEnd: + case IRCError::NoMessageOfTheDay: + break; + case IRCReply::NoTopic: + case IRCReply::Topic: + break; + case IRCReply::NameReply: + QString channel = ircServerMessage.parameter (2); + QString nickList = ircServerMessage.parameter (3); + emit debugMessage (nickList); + ircChannelProxy (channel)->setNickList (nickList.split (QRegExp ("\\s+"), QString::SkipEmptyParts)); + break; + } + } + else + { + QString command = ircServerMessage.command (); + if (command == IRCCommand::Nick) + { + handleNicknameChanged (ircServerMessage.nick(), ircServerMessage.parameter (0)); + } + else if (command == IRCCommand::Quit) + { + handleUserQuit (ircServerMessage.nick (), ircServerMessage.parameter (0)); + } + else if (command == IRCCommand::Join) + { + handleUserJoined(ircServerMessage.nick (), ircServerMessage.parameter (0)); + } + else if (command == IRCCommand::Part) + { + emit debugMessage ("WRITEME: Received part."); + //emit part (ircEvent.getNick ().toStdString ().c_str (), + // ircEvent.getParam (0).toStdString ().c_str (), + // ircEvent.getParam (1).toStdString ().c_str ()); + } + else if (command == IRCCommand::Mode) + { + emit debugMessage ("WRITEME: Received mode."); + //emit mode (&ircEvent); + } + else if (command == IRCCommand::Topic) + { + emit debugMessage + (QString("WRITEME: Received topic: %1") + .arg (ircServerMessage.parameter (0))); + } + else if (command == IRCCommand::Kick) + { + emit debugMessage ("WRITEME: Received kick command."); + } + else if (command == IRCCommand::Invite) + { + emit debugMessage ("WRITEME: Received invite command."); + + } + else if (command == IRCCommand::PrivateMessage) + { + emit message (ircServerMessage.parameter (0), ircServerMessage.nick (), ircServerMessage.parameter (1)); + } + else if (command == IRCCommand::Notice) + { + emit notification (ircServerMessage.nick ().toStdString ().c_str (), + ircServerMessage.parameter (1).toStdString ().c_str ()); + } + else if (command == IRCCommand::Ping) + { + sendIRCCommand (IRCCommand::Pong, QStringList (m_nickname)); + } + else if (command == IRCCommand::Error) + { + emit error (ircServerMessage.parameter (0)); + } + else + { + emit debugMessage (QString("FIXME: Received unknown reply: %1").arg(command)); + } + } + } +} + +void +IRCClientImpl::sendLine (const QString &line) +{ + if (m_connected) + m_tcpSocket.write ( (line + + "\r\n").toUtf8 ()); +} + +void +IRCClientImpl::sendIRCCommand (const QString &command, const QStringList &arguments) +{ + QString line = command; + for (int i = 0; i < arguments.size (); i++) + { + bool applyColon = false; + // Usually all parameters are separated by spaces. + // The last parameter of the message may contain spaces, it is usually used + // to transmit messages. In order to parse it correctly, if needs to be prefixed + // with a colon, so the server knows to ignore all forthcoming spaces and has to treat + // all remaining characters as a single parameter. If we detect any whitespace in the + // last argument, prefix it with a colon: + if ((i == arguments.size () - 1) && arguments.at (i).contains (QRegExp("\\s"))) + applyColon = true; + line += QString (" %1%2").arg (applyColon ? ":" : "").arg (arguments.at (i)); + } + sendLine (line); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gui/src/irc/IRCClientImpl.h Sun Sep 25 21:13:59 2011 +0200 @@ -0,0 +1,355 @@ +/* OctaveGUI - A graphical user interface for Octave + * Copyright (C) 2011 Jacob Dawid (jacob.dawid@googlemail.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef IRCCLIENTIMPL_H +#define IRCCLIENTIMPL_H + +#include <QTcpSocket> +#include <QHostInfo> +#include <QStringList> +#include <QTextDocument> +#include <QStringListModel> +#include "IRCClientInterface.h" + +/** + * \namespace IRCCommand + * This namespace includes all IRC commands. + */ +namespace IRCCommand +{ + const QString Password = "PASS"; + const QString Nick = "NICK"; + const QString User = "USER"; + const QString Operation = "OPER"; + const QString Service = "SERVICE"; + const QString Quit = "QUIT"; + const QString ServerQuit = "SQUIT"; + + const QString Join = "JOIN"; + const QString Part = "PART"; + const QString Mode = "MODE"; + const QString Topic = "TOPIC"; + const QString Names = "NAMES"; + const QString List = "LIST"; + const QString Invite = "INVITE"; + const QString Kick = "KICK"; + + const QString PrivateMessage = "PRIVMSG"; + const QString Notice = "NOTICE"; + + const QString MessageOfTheDay = "MOTD"; + const QString ListUsers = "LUSERS"; + const QString Version = "VERSION"; + const QString Stats = "STATS"; + const QString Links = "LINKS"; + const QString Time = "TIME"; + const QString Command = "CONNECT"; + const QString Trace = "TRACE"; + const QString Admin = "ADMIN"; + const QString Info = "INFO"; + + const QString ServerList = "SERVLIST"; + const QString ServerQuery = "SQUERY"; + + const QString Who = "WHO"; + const QString WhoIs = "WHOIS"; + const QString WhoWas = "WHOWAS"; + + const QString Kill = "KILL"; + const QString Ping = "PING"; + const QString Pong = "PONG"; + const QString Error = "ERROR"; + + const QString Away = "AWAY"; + const QString Rehash = "REHASH"; + const QString Die = "DIE"; + const QString Restart = "RESTART"; + const QString Summon = "SUMMON"; + const QString Users = "USERS"; + const QString OperatorWall = "OPERWALL"; + const QString UserHost = "USERHOST"; + const QString IsOn = "ISON"; +}; + +/** + * \namespace IRCReply + * This namespace includes all numeric IRC replies. + */ +namespace IRCReply +{ + const int Welcome = 1; + const int YourHost = 2; + const int Created = 3; + const int MyInfo = 4; + const int ReplyBounce = 5; + const int UserHost = 302; + const int IsOn = 303; + const int Away = 301; + const int UnAway = 305; + const int NoAway = 306; + const int WhoIsUser = 311; + const int WhoIsServer = 312; + const int WhoIsOperator = 313; + const int WhoIsIdle = 317; + const int EndOfWhoIs = 318; + const int WhoIsChannels = 319; + const int WhoWasUser = 314; + const int EndOfWhoWas = 369; + const int ListStart = 321; + const int List = 322; + const int ListEnd = 323; + const int UniqueOpIs = 325; + const int ChannelModeIs = 324; + const int NoTopic = 331; + const int Topic = 332; + const int Inviting = 341; + const int Summoning = 342; + const int InviteList = 346; + const int EndOfInviteList = 347; + const int ExceptList = 348; + const int EndOfExceptList = 349; + const int Version = 351; + const int WhoReply = 352; + const int EndOfWho = 315; + const int NameReply = 353; + const int EndOfNames = 366; + const int Links = 364; + const int EndOfLinks = 367; + const int BanList = 368; + const int Info = 371; + const int EndOfInfo = 374; + const int MessageOfTheDayStart = 375; + const int MessageOfTheDay = 372; + const int MessageOfTheDayEnd = 376; + const int YouAreOperator = 381; + const int Rehashing = 382; + const int YouAreService = 383; + const int Time = 391; + const int UserStart = 392; + const int Users = 393; + const int EndOfUsers = 394; + const int NoUsers = 395; + const int TraceLink = 200; + const int TraceConnecting = 201; + const int TraceHandshake = 202; + const int TraceUnknown = 203; + const int TraceOperator = 204; + const int TraceUser = 205; + const int TraceServer = 206; + const int TraceService = 207; + const int TraceNewType = 208; + const int TraceClass = 209; + const int TraceConnect = 210; + const int TraceLog = 261; + const int TraceEnd = 262; + const int StatsLinkInfo = 211; + const int StatsCommands = 212; + const int EndOfStats = 219; + const int StatsUptime = 242; + const int StatsOnline = 243; + const int UModeIs = 221; + const int ServerList = 234; + const int ServerListEnd = 235; + const int ListUserClient = 251; + const int ListUserOperator = 252; + const int ListUserUnknown = 253; + const int ListUserChannels = 254; + const int ListUserMe = 255; + const int AdminMe = 256; + const int AdminLoc1 = 257; + const int AdminLoc2 = 258; + const int AdminEmail = 259; + const int TryAgain = 263; +}; + +/** + * \namespace IRCError + * This namespace includes all numeric IRC errors. + */ +namespace IRCError +{ + const int NoSuchNick = 401; + const int NoSuchServer = 402; + const int NoSuchChannel = 403; + const int CannotSendToChannel = 404; + const int TooManyChannels = 405; + const int WasNoSuchNick = 406; + const int TooManyTargets = 407; + const int NoSuchService = 408; + const int NoOrigin = 409; + const int NoRecipient = 411; + const int NoTextToSend = 412; + const int NoTopLevel = 413; + const int WildTopLevel = 414; + const int BasMask = 415; + const int UnknownCommand = 421; + const int NoMessageOfTheDay = 422; + const int NoAdminInfo = 423; + const int FileError = 424; + const int NoNickNameGiven = 431; + const int ErroneusNick = 432; + const int NicknameInUse = 433; + const int NickCollision = 436; + const int UnavailResource = 437; + const int UserNotInChannel = 441; + const int NotOnChannel = 442; + const int UserOnChannel = 443; + const int NoLogin = 444; + const int SummonDisabled = 445; + const int UsersDisabled = 446; + const int NotRegistered = 451; + const int NeedMoreParams = 461; + const int AlreadyRegistered = 462; + const int NoPermissionForHost = 463; + const int PasswordMismatch = 464; + const int YouAreBannedCreep = 465; + const int YouWillBeBanned = 466; + const int KeySet = 467; + const int ChannelIsFull = 471; + const int UnknownMode = 472; + const int InviteOnlyChannel = 473; + const int BannedFromChannel = 474; + const int BadChannelKey = 475; + const int BadChannelMask = 476; + const int NoChannelModes = 477; + const int BanListFull = 478; + const int NoPrivileges = 481; + const int ChannelOperatorPrivilegesNeeded = 482; + const int CannotKillServer = 483; + const int Restricted = 484; + const int UniqueOperatorPrivilegesNeeded = 485; + const int NoOperatorHost = 491; + const int YourModeListUnknownFlag = 501; + const int UsersDontMatch = 502; +}; + +/** + * \class IRCServerMessage + * The IRCServerMessage class is a wrapper for server messages. + * It parses the server message into its single bits and makes these + * available through Getter-methods. + */ +class IRCServerMessage +{ +public: + IRCServerMessage (const QString& serverMessage); + + bool isNumeric () + { return m_isNumeric; } + + QString nick () + { return m_nick; } + + QString command () + { return m_command; } + + int numericValue (); + QString parameter (int index); + +private: + int m_codeNumber; + bool m_isNumeric; + QString m_nick; + QString m_user; + QString m_host; + QString m_command; + QStringList m_parameters; +}; + +/** + * \class IRCChannelProxyImpl + * Implements a handle to an IRC channel. This is usually provided by the + * the IRC client class. + */ +class IRCChannelProxyImpl : public IRCChannelProxyInterface +{ + Q_OBJECT +public: + IRCChannelProxyImpl (IRCClientInterface *clientInterface, const QString& channelName, QObject *parent = 0); + QTextDocument *conversationModel (); + QStringListModel *userListModel (); + QString channelName (); + + void setNickList (const QStringList &nickList); + void sendMessage (const QString& message); + void sendJoinRequest (); + void leave (const QString &reason); +public slots: + void handleNickChange (const QString& oldNick, const QString& newNick); + void handleJoin (const QString& nick); +private: + QString m_channelName; + QStringList m_userList; + QStringListModel m_userListModel; + QTextDocument m_conversationModel; + IRCClientInterface *m_clientInterface; +}; + +/** + * \class IRCClientImpl + * Implements an IRC client. This class can maintain a connection to one server. + * In order to interface an IRC channel, use the ircChannelProxy-method to retrieve + * a handle. + */ +class IRCClientImpl : public IRCClientInterface +{ + Q_OBJECT +public: + IRCClientImpl (QObject *parent = 0); + ~IRCClientImpl (); + + const QString& nickname (); + bool isConnected (); + bool isLoggedIn (); + const QHostAddress& host(); + int port(); + IRCChannelProxyInterface *ircChannelProxy(const QString& channel); + void sendIRCCommand (const QString& command, const QStringList& arguments); + +public slots: + void connectToHost (const QHostAddress& host, int port, const QString& initialNick); + void disconnect (); + void reconnect (); + + void sendNicknameChangeRequest (const QString &nickname); + void sendPrivateMessage (const QString &recipient, const QString &message); + +signals: + void debugMessage (const QString& message); + +private slots: + void handleConnected (); + void handleDisconnected (); + void handleReadyRead (); + +private: + void handleNicknameChanged (const QString& oldNick, const QString& newNick); + void handleUserJoined (const QString& nick, const QString& channel); + void handleUserQuit (const QString& nick, const QString& reason); + void handleIncomingLine (const QString& line); + void sendLine (const QString& line); + + QHostAddress m_host; + int m_port; + QString m_nickname; + bool m_connected; + bool m_loggedIn; + QTcpSocket m_tcpSocket; + QMap<QString, IRCChannelProxyInterface*> m_channels; +}; + +#endif // IRCCLIENTIMPL_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gui/src/irc/IRCClientInterface.h Sun Sep 25 21:13:59 2011 +0200 @@ -0,0 +1,221 @@ +/* OctaveGUI - A graphical user interface for Octave + * Copyright (C) 2011 Jacob Dawid (jacob.dawid@googlemail.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef IRCCLIENTINTERFACE_H +#define IRCCLIENTINTERFACE_H + +#include <QString> +#include <QObject> +#include <QHostAddress> +#include <QTextDocument> +#include <QStringListModel> + +class IRCClientInterface; +/** + * \class IRCChannelProxyInterface + * Interface for a handle to an IRC channel. + */ +class IRCChannelProxyInterface : public QObject +{ + Q_OBJECT +public: + IRCChannelProxyInterface (IRCClientInterface *, const QString&, QObject *parent = 0) : QObject (parent) { } + virtual ~IRCChannelProxyInterface () { } + + /** Returns the conversation model part. */ + virtual QTextDocument *conversationModel () = 0; + + /** Returns a string list model for the user list. */ + virtual QStringListModel *userListModel () = 0; + + /** Returns the name of this channel. */ + virtual QString channelName () = 0; + + /** + * Overwrites the current nick list by settings a new nick list. + * \arg nickList The new nick list to set. + */ + virtual void setNickList (const QStringList& nickList) = 0; + + /** + * Sends a public message onto this channel. + * \arg message The message that should be sent. + */ + virtual void sendMessage (const QString& message) = 0; + + /** Requests to join this channel. */ + virtual void sendJoinRequest () = 0; + + /** + * Requests to leave this channel. + * \arg reason Reason for leaving the channel. + */ + virtual void leave (const QString& reason) = 0; + +public slots: + virtual void handleNickChange (const QString& oldNick, const QString& newNick) = 0; + virtual void handleJoin (const QString& nick) = 0; +}; + +/** + * \class IRCClientInterface + * IRC Clients need to implement this interface. + */ +class IRCClientInterface : public QObject +{ + Q_OBJECT +public: + IRCClientInterface (QObject *parent = 0) : QObject (parent) { } + virtual ~IRCClientInterface () { } + + /** Returns the current nickname of this client. */ + virtual const QString& nickname () = 0; + + /** Returns true if connected to the server. */ + virtual bool isConnected () = 0; + + /** + * Returns true if logged in to the server. + * Note: There is a small difference between isConnected and isLoggedIn. + * isConnected returns true if there is a physical connection to the server. + * isLoggedIn only returns true if the server has already accepted you + * and you are ready to log into channels. + */ + virtual bool isLoggedIn () = 0; + + /** Returns the current host address. */ + virtual const QHostAddress& host() = 0; + + /** Returns the current port. */ + virtual int port() = 0; + + /** + * Returns a handle to an IRC channel. + * Note: Retrieving a handle does not mean you have joined this channel. + * \arg channel The channel to retrieve a handle for. + */ + virtual IRCChannelProxyInterface *ircChannelProxy(const QString& channel) = 0; + + /** + * Send an IRC command to the server. + * \arg command Command to send. + * \arg arguments Arguments to send. + */ + virtual void sendIRCCommand (const QString& command, const QStringList& arguments) = 0; + +public slots: + /** + * Connects to a host. + * \arg host The host to connect tp. + * \arg port The port on which to connect to the host. + * \arg initialNick The initial nick to use when attempting to login. + */ + virtual void connectToHost (const QHostAddress& host, int port, const QString& initialNick) = 0; + + /** Disconnects from the host. */ + virtual void disconnect () = 0; + + /** Reconnects to the host. */ + virtual void reconnect () = 0; + + /** + * Sends a request to change the nickname. + * \arg nickname The new nickname to be requested. + */ + virtual void sendNicknameChangeRequest (const QString& nickname) = 0; + + /** + * Sends a private message. + * \arg recipient The nickname or channel that message should be sent to. + * \arg message The message that should be sent. + */ + virtual void sendPrivateMessage (const QString& recipient, const QString& message) = 0; + +signals: + /** + * Sent upon the arrival of a new message. + * \arg channel The channel this message was sent from. + * \arg sender The nickname of the sender. + * \arg message The message that has been sent. + */ + void newMessage (const QString& channel, const QString& sender, const QString& message); + void message (const QString& channel, const QString& sender, const QString& message); + + /** + * Sent when the connection to a server has been established. + * \arg server The name of the server that the connection has been established to. + */ + void connected (const QString& server); + + /** Sent when the connection to the server has been interrupted. */ + void disconnected (); + + /** + * Sent when an error occurs. + * \arg message A descriptive message of the error that occured. + */ + void error (const QString& message); + + /** + * Sent when a notification arrives. + * \arg sender The source of the notification. + * \arg message The notification. + */ + void notification (const QString& sender, const QString& message); + + /** + * Sent when a nickname changed. + * \arg oldNick The previous nickname. + * \arg newNick The new nickname. + */ + void nicknameChanged (const QString& oldNick, const QString& newNick); + + /** + * Sent when the nickname of this client changed. + * \arg nick The new nickname of this client. + */ + void userNicknameChanged (const QString& nick); + + /** + * Sent when a user has joined a channel. + * \arg nick Nickname of the user that joined the channel. + * \arg channel Channel that this user joined. + */ + void userJoined (const QString& nick, const QString& channel); + + /** + * Sent when a user quits. + * \arg nick Nickname of the user that quit. + * \arg reason Reason of the user to quit. + */ + void userQuit (const QString& nick, const QString& reason); + + /** + * Sent when a user logged in. + * \arg nick The nickname of the user that logged in. + */ + void loggedIn (const QString& nick); + + /** + * Sent when the server provides a userlist for a channel. + * \arg channel The channel that userlist applies to. + * \arg list The actual userlist. + */ + void userList (const QString& channel, const QStringList& list); +}; + +#endif // IRCCLIENTINTERFACE_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gui/src/irc/IRCCodes.h Sun Sep 25 21:13:59 2011 +0200 @@ -0,0 +1,223 @@ +/* OctaveGUI - A graphical user interface for Octave + * Copyright (C) 2011 Jacob Dawid + * jacob.dawid@googlemail.com + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + */ + +#ifndef IRCCODES_H +#define IRCCODES_H +#include <QString> + +namespace IRCCommand +{ + const QString Password = "PASS"; + const QString Nick = "NICK"; + const QString User = "USER"; + const QString Operation = "OPER"; + const QString Service = "SERVICE"; + const QString Quit = "QUIT"; + const QString ServerQuit = "SQUIT"; + + const QString Join = "JOIN"; + const QString Part = "PART"; + const QString Mode = "MODE"; + const QString Topic = "TOPIC"; + const QString Names = "NAMES"; + const QString List = "LIST"; + const QString Invite = "INVITE"; + const QString Kick = "KICK"; + + const QString PrivateMessage = "PRIVMSG"; + const QString Notice = "NOTICE"; + + const QString MessageOfTheDay = "MOTD"; + const QString ListUsers = "LUSERS"; + const QString Version = "VERSION"; + const QString Stats = "STATS"; + const QString Links = "LINKS"; + const QString Time = "TIME"; + const QString Command = "CONNECT"; + const QString Trace = "TRACE"; + const QString Admin = "ADMIN"; + const QString Info = "INFO"; + + const QString ServerList = "SERVLIST"; + const QString ServerQuery = "SQUERY"; + + const QString Who = "WHO"; + const QString WhoIs = "WHOIS"; + const QString WhoWas = "WHOWAS"; + + const QString Kill = "KILL"; + const QString Ping = "PING"; + const QString Pong = "PONG"; + const QString Error = "ERROR"; + + const QString Away = "AWAY"; + const QString Rehash = "REHASH"; + const QString Die = "DIE"; + const QString Restart = "RESTART"; + const QString Summon = "SUMMON"; + const QString Users = "USERS"; + const QString OperatorWall = "OPERWALL"; + const QString UserHost = "USERHOST"; + const QString IsOn = "ISON"; +}; + +namespace IRCReply +{ + const int Welcome = 1; + const int YourHost = 2; + const int Created = 3; + const int MyInfo = 4; + const int ReplyBounce = 5; + const int UserHost = 302; + const int IsOn = 303; + const int Away = 301; + const int UnAway = 305; + const int NoAway = 306; + const int WhoIsUser = 311; + const int WhoIsServer = 312; + const int WhoIsOperator = 313; + const int WhoIsIdle = 317; + const int EndOfWhoIs = 318; + const int WhoIsChannels = 319; + const int WhoWasUser = 314; + const int EndOfWhoWas = 369; + const int ListStart = 321; + const int List = 322; + const int ListEnd = 323; + const int UniqueOpIs = 325; + const int ChannelModeIs = 324; + const int NoTopic = 331; + const int Topic = 332; + const int Inviting = 341; + const int Summoning = 342; + const int InviteList = 346; + const int EndOfInviteList = 347; + const int ExceptList = 348; + const int EndOfExceptList = 349; + const int Version = 351; + const int WhoReply = 352; + const int EndOfWho = 315; + const int NameReply = 353; + const int EndOfNames = 366; + const int Links = 364; + const int EndOfLinks = 367; + const int BanList = 368; + const int Info = 371; + const int EndOfInfo = 374; + const int MessageOfTheDayStart = 375; + const int MessageOfTheDay = 372; + const int MessageOfTheDayEnd = 376; + const int YouAreOperator = 381; + const int Rehashing = 382; + const int YouAreService = 383; + const int Time = 391; + const int UserStart = 392; + const int Users = 393; + const int EndOfUsers = 394; + const int NoUsers = 395; + const int TraceLink = 200; + const int TraceConnecting = 201; + const int TraceHandshake = 202; + const int TraceUnknown = 203; + const int TraceOperator = 204; + const int TraceUser = 205; + const int TraceServer = 206; + const int TraceService = 207; + const int TraceNewType = 208; + const int TraceClass = 209; + const int TraceConnect = 210; + const int TraceLog = 261; + const int TraceEnd = 262; + const int StatsLinkInfo = 211; + const int StatsCommands = 212; + const int EndOfStats = 219; + const int StatsUptime = 242; + const int StatsOnline = 243; + const int UModeIs = 221; + const int ServerList = 234; + const int ServerListEnd = 235; + const int ListUserClient = 251; + const int ListUserOperator = 252; + const int ListUserUnknown = 253; + const int ListUserChannels = 254; + const int ListUserMe = 255; + const int AdminMe = 256; + const int AdminLoc1 = 257; + const int AdminLoc2 = 258; + const int AdminEmail = 259; + const int TryAgain = 263; +}; + +namespace IRCError +{ + const int NoSuchNick = 401; + const int NoSuchServer = 402; + const int NoSuchChannel = 403; + const int CannotSendToChannel = 404; + const int TooManyChannels = 405; + const int WasNoSuchNick = 406; + const int TooManyTargets = 407; + const int NoSuchService = 408; + const int NoOrigin = 409; + const int NoRecipient = 411; + const int NoTextToSend = 412; + const int NoTopLevel = 413; + const int WildTopLevel = 414; + const int BasMask = 415; + const int UnknownCommand = 421; + const int NoMessageOfTheDay = 422; + const int NoAdminInfo = 423; + const int FileError = 424; + const int NoNickNameGiven = 431; + const int ErroneusNick = 432; + const int NicknameInUse = 433; + const int NickCollision = 436; + const int UnavailResource = 437; + const int UserNotInChannel = 441; + const int NotOnChannel = 442; + const int UserOnChannel = 443; + const int NoLogin = 444; + const int SummonDisabled = 445; + const int UsersDisabled = 446; + const int NotRegistered = 451; + const int NeedMoreParams = 461; + const int AlreadyRegistered = 462; + const int NoPermissionForHost = 463; + const int PasswordMismatch = 464; + const int YouAreBannedCreep = 465; + const int YouWillBeBanned = 466; + const int KeySet = 467; + const int ChannelIsFull = 471; + const int UnknownMode = 472; + const int InviteOnlyChannel = 473; + const int BannedFromChannel = 474; + const int BadChannelKey = 475; + const int BadChannelMask = 476; + const int NoChannelModes = 477; + const int BanListFull = 478; + const int NoPrivileges = 481; + const int ChannelOperatorPrivilegesNeeded = 482; + const int CannotKillServer = 483; + const int Restricted = 484; + const int UniqueOperatorPrivilegesNeeded = 485; + const int NoOperatorHost = 491; + const int YourModeListUnknownFlag = 501; + const int UsersDontMatch = 502; +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gui/src/irc/IRCWidget.cpp Sun Sep 25 21:13:59 2011 +0200 @@ -0,0 +1,448 @@ +/* OctaveGUI - A graphical user interface for Octave + * Copyright (C) 2011 Jacob Dawid (jacob.dawid@googlemail.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "ResourceManager.h" +#include "IRCWidget.h" +#include <QMessageBox> +#include <QHBoxLayout> +#include <QVBoxLayout> +#include <QLabel> +#include <QSettings> +#include <QInputDialog> +#include <QKeyEvent> +#include <QScrollBar> +#include <QApplication> +#include "IRCClientImpl.h" + +ChatMessageTextEdit::ChatMessageTextEdit (QWidget *parent) + : QPlainTextEdit (parent), m_completer (0) +{ + setMaximumHeight (50); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); +} + +ChatMessageTextEdit::~ChatMessageTextEdit () +{ +} + +void +ChatMessageTextEdit::setCompleter (QCompleter *completer) +{ + if (m_completer) + QObject::disconnect (m_completer, 0, this, 0); + + m_completer = completer; + + if (!m_completer) + return; + + m_completer->setWidget (this); + m_completer->setCompletionMode (QCompleter::PopupCompletion); + m_completer->setCaseSensitivity (Qt::CaseInsensitive); + QObject::connect (m_completer, SIGNAL (activated (QString)), + this, SLOT (insertCompletion (QString))); +} + +QCompleter * +ChatMessageTextEdit::completer () const +{ + return m_completer; +} + +void +ChatMessageTextEdit::insertCompletion(const QString& completion) +{ + + if (m_completer->widget() != this) + return; + QTextCursor tc = textCursor(); + int extra = completion.length() - m_completer->completionPrefix().length(); + tc.movePosition(QTextCursor::Left); + tc.movePosition(QTextCursor::EndOfWord); + tc.insertText(completion.right(extra)); + setTextCursor(tc); +} + +QString +ChatMessageTextEdit::textUnderCursor () const +{ + QTextCursor tc = textCursor (); + tc.select (QTextCursor::WordUnderCursor); + return tc.selectedText (); +} + +void +ChatMessageTextEdit::focusInEvent (QFocusEvent *e) +{ + if (m_completer) + m_completer->setWidget (this); + QPlainTextEdit::focusInEvent (e); +} + +void +ChatMessageTextEdit::keyPressEvent (QKeyEvent *keyPressEvent) +{ + if (m_completer) { + switch (keyPressEvent->key ()) { + case Qt::Key_Enter: + case Qt::Key_Return: + if (! (keyPressEvent->modifiers () & Qt::ShiftModifier)) + { + emit sendMessage (document ()->toPlainText ()); + document ()->setPlainText (""); + } + else + { + QPlainTextEdit::keyPressEvent (keyPressEvent); + } + break; + case Qt::Key_Escape: + case Qt::Key_Tab: + case Qt::Key_Backtab: + keyPressEvent->ignore (); + return; + default: + QPlainTextEdit::keyPressEvent(keyPressEvent); + break; + } + + QString completionPrefix = textUnderCursor (); + if (completionPrefix != m_completer->completionPrefix ()) + { + m_completer->setCompletionPrefix(completionPrefix); + } + + if (completionPrefix.length() > 2) + { + m_completer->popup ()->setCurrentIndex (m_completer->completionModel ()->index (0, 0)); + m_completer->complete (); + } + else + { + m_completer->popup ()->hide (); + } + } +} + +IRCWidget::IRCWidget (QWidget * parent): +QWidget (parent) +{ + QSettings *settings = ResourceManager::instance ()->settings (); + bool connectOnStartup = settings->value ("connectOnStartup").toBool (); + m_autoIdentification = settings->value ("autoIdentification").toBool (); + m_nickServPassword = settings->value ("nickServPassword").toString (); + + m_initialNick = settings->value ("IRCNick").toString (); + + if (m_initialNick.isEmpty ()) + m_initialNick = "OctaveGUI-User"; + + QVBoxLayout *layout = new QVBoxLayout (); + + m_chatWindow = new QTextEdit (this); + m_chatWindow->setReadOnly (true); + m_chatWindow->setEnabled (false); + QWidget *bottomWidget = new QWidget (this); + + layout->addWidget (m_chatWindow); + layout->addWidget (bottomWidget); + layout->setMargin (0); + setLayout (layout); + + QHBoxLayout *bottomLayout = new QHBoxLayout (); + m_nickButton = new QPushButton (bottomWidget); + m_nickButton->setStatusTip (tr ((char *) "Click here to change your nick.")); + m_nickButton->setText (m_initialNick); + m_chatMessageTextEdit = new ChatMessageTextEdit (bottomWidget); + m_chatMessageTextEdit->setStatusTip (tr ((char *) "Enter your message here.")); + + bottomLayout->addWidget (m_nickButton); + bottomLayout->addWidget (new QLabel (":", this)); + bottomLayout->addWidget (m_chatMessageTextEdit); + bottomLayout->setMargin (0); + bottomWidget->setLayout (bottomLayout); + + m_nickButton->setEnabled (false); + m_chatMessageTextEdit->setEnabled (false); + + //setFocusProxy (m_chatMessageTextEdit); + m_nickButton->setFocusProxy (m_chatMessageTextEdit); + + QFont font; + font.setFamily ("Courier"); + font.setPointSize (11); + m_chatWindow->setFont (font); + m_ircClientInterface = new IRCClientImpl (this); + m_octaveChannel = m_ircClientInterface->ircChannelProxy ("#octave"); + + connect (m_ircClientInterface, SIGNAL (connected (QString)), + this, SLOT (handleConnected (QString))); + connect (m_ircClientInterface, SIGNAL(loggedIn(QString)), + this, SLOT (joinOctaveChannel (QString))); + connect (m_ircClientInterface, SIGNAL (error (QString)), + this, SLOT (showErrorMessage (QString))); + connect (m_ircClientInterface, SIGNAL (debugMessage (QString)), + this, SLOT (showStatusMessage (QString))); + connect (m_ircClientInterface, SIGNAL (message (QString, QString, QString)), + this, SLOT (showMessage (QString, QString, QString ))); + connect (m_ircClientInterface, SIGNAL (nicknameChanged (QString,QString)), + this, SLOT (handleNickChange (QString,QString))); + connect (m_ircClientInterface, SIGNAL (notification (QString,QString)), + this, SLOT (showNotification (QString,QString))); + connect (m_ircClientInterface, SIGNAL (loggedIn (QString)), + this, SLOT (handleLoggedIn(QString))); + connect (m_ircClientInterface, SIGNAL (userNicknameChanged (QString)), + this, SLOT (handleUserNicknameChanged (QString))); + + connect (m_nickButton, SIGNAL (clicked ()), this, SLOT (showChangeUserNickPopup ())); + connect (m_chatMessageTextEdit, SIGNAL (sendMessage (QString)), + this, SLOT (sendMessage (QString))); + + m_chatMessageTextEdit->setCompleter + (new QCompleter (m_ircClientInterface->ircChannelProxy ("#octave")->userListModel (), this)); + m_chatWindow->setDocument (m_octaveChannel->conversationModel ()); + + if (connectOnStartup) + connectToServer (); +} + +void +IRCWidget::connectToServer () +{ + showStatusMessage ("Looking up irc.freenode.net."); + QHostInfo hostInfo = QHostInfo::fromName ("irc.freenode.net"); + QList<QHostAddress> hostAddresses = hostInfo.addresses(); + if (hostAddresses.isEmpty ()) + { + showStatusMessage ("Failed to lookup irc.freenode.net."); + } + else + { + showStatusMessage (QString ("Attempting to connect to %1.") + .arg (hostAddresses.at (0).toString ())); + m_ircClientInterface->connectToHost(hostAddresses.at (0), 6667, m_initialNick); + } +} + +void +IRCWidget::showStatusMessage (const QString& message) +{ + m_chatWindow->append (QString ("<i>%1</i>").arg (message)); +} + +void +IRCWidget::showErrorMessage (const QString& message) +{ + m_chatWindow->append (QString ("<i>Error: %1</i>").arg (message)); +} + +void +IRCWidget::handleConnected (const QString &host) +{ + showStatusMessage (QString ("Connected to server %1.").arg (host)); +} + +void +IRCWidget::joinOctaveChannel (const QString& nick) +{ + Q_UNUSED (nick); + showStatusMessage (QString ("Joining channel #octave.")); + m_octaveChannel->sendJoinRequest (); +} + +void +IRCWidget::showMessage (const QString& channel, const QString& sender, const QString& message) +{ + Q_UNUSED (channel); + + // TODO: This doesn't work properly! + // Every message makes it emit unreadMessage (true), + // though it should inly be emitted when this window + // does not have focus, ie. is not the active window. + if (!(hasFocus() + || m_chatMessageTextEdit->hasFocus () + || m_nickButton->hasFocus () + || m_chatWindow->hasFocus () )) + { + emit unreadMessages (true); + } + + QString output; + QString htmlMessage = message; + htmlMessage.replace ("<", "<"); + htmlMessage.replace (">", ">"); + htmlMessage.replace ("\n", "<br>"); + if (message.contains (m_ircClientInterface->nickname ())) + { + output = + QString ("<font color=\"#990000\"><b>%1:</b> %2</font>").arg (sender). + arg (htmlMessage); + + QApplication::alert (this); + } + else + { + output = + QString ("<b>%1:</b> %2").arg (sender). + arg (htmlMessage); + } + m_chatWindow->append (output); + scrollToBottom (); +} + +void +IRCWidget::showNotification (const QString& sender, const QString& message) +{ + Q_UNUSED (sender); + m_chatWindow->append (QString ("<font color=\"#007700\">%1</font>").arg (message)); + scrollToBottom (); +} + +void +IRCWidget::showChangeUserNickPopup () +{ + bool ok; + QString newNick = + QInputDialog::getText (this, QString ("Nickname"), + QString ("Type in your nickname:"), + QLineEdit::Normal, m_ircClientInterface->nickname (), &ok); + if (ok) + { + m_ircClientInterface->sendNicknameChangeRequest (newNick); + } +} + +void +IRCWidget::sendMessage (QString message) +{ + // Do not send empty messages. + if (message.isEmpty ()) + return; + + // Remove trailing spaces. + while (message.at (0).isSpace ()) + message.remove (0, 1); + if (message.startsWith ("/")) + { + QStringList line = + message.split (QRegExp ("\\s+"), QString::SkipEmptyParts); + if (line.at (0) == "/join") + { + IRCChannelProxyInterface *ircChannel = m_ircClientInterface->ircChannelProxy (line.at (1)); + ircChannel->sendJoinRequest (); + } + else if (line.at (0) == "/nick") + { + m_ircClientInterface->sendNicknameChangeRequest (line.at (1)); + } + else if (line.at (0) == "/msg") + { + QString recipient = line.at (1); + // Since we splitted the message before, we have to glue it together again. + QString pmsg = ""; + for (int i = 2; i < line.length (); i++) + { + pmsg += line.at (i); + pmsg += " "; + } + m_ircClientInterface->sendPrivateMessage(recipient, pmsg); + } + } + else + { + m_octaveChannel->sendMessage (message); + message.replace ("<", "<"); + message.replace (">", ">"); + message.replace ("\n", "<br>"); + m_chatWindow->append (QString ("<b>%1:</b> %2"). + arg (m_ircClientInterface->nickname ()).arg (message)); + } + + scrollToBottom (); +} + +void +IRCWidget::maybeIdentifyOnNickServ () +{ + if (m_autoIdentification) + { + m_ircClientInterface->sendPrivateMessage("NickServ", QString ("identify %1"). + arg (m_nickServPassword)); + } +} + +void +IRCWidget::scrollToBottom () +{ + if (m_chatWindow->verticalScrollBar ()) + { + m_chatWindow->verticalScrollBar ()->setValue (m_chatWindow->verticalScrollBar ()->maximum ()); + } +} + +void +IRCWidget::focusInEvent (QFocusEvent *focusEvent) +{ + Q_UNUSED (focusEvent); + emit unreadMessages (false); + QWidget::focusInEvent (focusEvent); + + m_chatMessageTextEdit->setFocus (); +} + +void +IRCWidget::handleLoggedIn (const QString &nick) +{ + m_chatWindow-> + append (QString + ("<i><font color=\"#00AA00\"><b>Successfully logged in as %1.</b></font></i>"). + arg (nick)); + m_nickButton->setEnabled (true); + m_chatMessageTextEdit->setEnabled (true); + m_chatWindow->setEnabled (true); + m_chatMessageTextEdit->setFocus (); +} + +void +IRCWidget::handleNickChange (const QString &oldNick, const QString &newNick) +{ + m_chatWindow->append (QString ("%1 is now known as %2.").arg (oldNick).arg (newNick)); + scrollToBottom (); +} + +void +IRCWidget::handleUserJoined (const QString &nick, const QString &channel) +{ + m_chatWindow->append (QString ("<i>%1 has joined %2.</i>").arg (nick).arg (channel)); + scrollToBottom (); +} + +void +IRCWidget::handleUserQuit (const QString &nick, const QString &reason) +{ + m_chatWindow->append (QString ("<i>%1 has quit.(%2).</i>").arg (nick).arg (reason)); + scrollToBottom (); +} + +void +IRCWidget::handleUserNicknameChanged (const QString &nick) +{ + m_nickButton->setText (nick); + QSettings *settings = ResourceManager::instance ()->settings (); + settings->setValue ("IRCNick", nick); + maybeIdentifyOnNickServ (); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gui/src/irc/IRCWidget.h Sun Sep 25 21:13:59 2011 +0200 @@ -0,0 +1,101 @@ +/* OctaveGUI - A graphical user interface for Octave + * Copyright (C) 2011 Jacob Dawid (jacob.dawid@googlemail.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef IRCWIDGET_H +#define IRCWIDGET_H + +#include <QWidget> +#include <QPlainTextEdit> +#include <QPushButton> +#include <QLineEdit> +#include <QCompleter> +#include "IRCClientInterface.h" + +class ChatMessageTextEdit : public QPlainTextEdit +{ + Q_OBJECT +public: + explicit ChatMessageTextEdit(QWidget *parent = 0); + ~ChatMessageTextEdit(); + + void setCompleter(QCompleter *m_completer); + QCompleter *completer() const; + +signals: + void sendMessage (const QString& message); + +protected: + void keyPressEvent(QKeyEvent *e); + void focusInEvent(QFocusEvent *e); + +private slots: + void insertCompletion(const QString &completion); + +private: + QString textUnderCursor() const; + +private: + QCompleter *m_completer; +}; + +class IRCWidget : public QWidget +{ +Q_OBJECT public: + explicit IRCWidget (QWidget * parent); + void connectToServer (); + +public slots: + void showStatusMessage (const QString&); + void showErrorMessage (const QString&); + void showMessage (const QString& channel, const QString& sender, const QString& message); + void showNotification (const QString& sender, const QString& message); + + void handleConnected (const QString& host); + void joinOctaveChannel (const QString& nick); + + void handleLoggedIn (const QString& nick); + void handleNickChange (const QString& oldNick, const QString& newNick); + void handleUserJoined (const QString& nick, const QString& channel); + void handleUserQuit (const QString& nick, const QString& reason); + void handleUserNicknameChanged (const QString& nick); + + void showChangeUserNickPopup (); + void sendMessage (QString); + + void maybeIdentifyOnNickServ (); + void scrollToBottom (); + +signals: + void unreadMessages (bool yes); + +protected: + void focusInEvent (QFocusEvent *focusEvent); + +private: + IRCClientInterface *m_ircClientInterface; + IRCChannelProxyInterface *m_octaveChannel; + QTextEdit *m_chatWindow; + QPushButton *m_nickButton; + ChatMessageTextEdit *m_chatMessageTextEdit; + + QString m_initialNick; + bool m_autoIdentification; + QString m_nickServPassword; + QString m_settingsFile; +}; + +#endif // IRCWIDGET_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gui/src/irc/Makefile.am Sun Sep 25 21:13:59 2011 +0200 @@ -0,0 +1,34 @@ +####### kdevelop will overwrite this part!!! (begin)########## +bin_PROGRAMS = qirc + qirc_SOURCES = + programcommand.cpp newtab.cpp MainTab.cpp notifyshowcase.cpp channellist. + cpp dccget.cpp dccsend.cpp IServerSocket.cpp general.cpp listanicks. + cpp qirc.cpp ventanas.cpp inputBox.cpp cuadroListaNicks. + cpp cuadroConfiguracion.cpp cuadroConectarCon.cpp colamensajes. + cpp IRCClient.cpp IClientSocket.cpp Config.cpp ChatView.cpp main. + cpp qirc_LDADD = -lqt - lXext - lX11 $ (LIBSOCKET) SUBDIRS = + docs EXTRA_DIST = + main.cpp qirc.h ChatView.cpp ChatView.h Config.cpp Config.h IClientSocket. + cpp IClientSocket.h IRCClient.cpp IRCClient.h IRCCodes.h colamensajes. + cpp colamensajes.h cuadroConectarCon.cpp cuadroConectarCon. + h cuadroConfiguracion.cpp cuadroConfiguracion.h cuadroListaNicks. + cpp cuadroListaNicks.h inputBox.cpp inputBox.h ventanas.cpp ventanas.h qirc. + cpp resource.h qirc16x16.xpm qirc32x32.xpm qirc64x64.xpm listanicks. + cpp listanicks.h general.h general.cpp IServerSocket.cpp IServerSocket. + h dccsend.cpp dccsend.h dccget.cpp dccget.h connect.xpm dccsend.xpm help. + xpm connectto.xpm disconnect.xpm join.xpm part.xpm list.xpm channellist. + cpp channellist.h notifyshowcase.cpp notifyshowcase.h offline.xpm online. + xpm operator.xpm justconn.xpm MainTab.cpp MainTab.h newtab.cpp newtab. + h leftArrowDisabled.xpm leftArrowEnabled.xpm rightArrowDisabled. + xpm rightArrowEnabled.xpm tabLeft.xpm tabMiddle.xpm tabRight.xpm tabClose. + xpm programcommand.cpp programcommand.h +####### kdevelop will overwrite this part!!! (end)############ +#set the include path for X, qt and KDE + INCLUDES = $ (all_includes) +#claim, which subdirectories you want to install +#you can add here more. This one gets installed + bin_PROGRAMS = qirc qirc_METASOURCES = USE_AUTOMOC +#the library search path. + qirc_LDFLAGS = $ (all_libraries) +#them while "make clean", use CLEANFILES + DISTCLEANFILES = $ (qirc_METASOURCES)
--- a/gui/src/qirc/IRCClientImpl.cpp Sun Sep 25 21:12:47 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,511 +0,0 @@ -/* OctaveGUI - A graphical user interface for Octave - * Copyright (C) 2011 Jacob Dawid (jacob.dawid@googlemail.com) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "IRCClientImpl.h" - -IRCServerMessage::IRCServerMessage (const QString& serverMessage) -{ - if (serverMessage.isEmpty ()) - return; - - int position = 0; - QString buffer; - - m_nick = ""; - m_user = ""; - m_host = ""; - - // A server message starting with a prefix indicates - // a prefix. A prefix has the format: - // :nick!user@host - // followed by a space character. - if (serverMessage.startsWith (":")) - { - position++; - while ((position < serverMessage.size ()) - &&(serverMessage.at (position) != '!') - && !serverMessage.at (position).isSpace ()) - { - buffer.append (serverMessage.at (position)); - position++; - } - m_nick = buffer, buffer.clear (), position++; - - // If it belongs to the prefix, it must be concatenanted neatlessly without - // any spaces. - if (!serverMessage.at (position - 1).isSpace ()) - { - while ((position < serverMessage.size ()) - && serverMessage.at (position) != '@') - { - buffer.append (serverMessage.at (position)); - position++; - } - m_user = buffer, buffer.clear (), position++; - } - - // If it belongs to the prefix, it must be concatenanted neatlessly without - // any spaces. - if (!serverMessage.at (position - 1).isSpace ()) - { - while ((position < serverMessage.size ()) - && serverMessage.at (position) != ' ') - { - buffer.append (serverMessage.at (position)); - position++; - } - m_host = buffer, buffer.clear (), position++; - } - } - - // The next part is the command. The command can either be numeric - // or a written command. - while ((position < serverMessage.size ()) - && !serverMessage.at (position).isSpace ()) - { - buffer.append (serverMessage.at (position)); - position++; - } - m_command = buffer.toUpper (), buffer.clear (), position++; - m_codeNumber = m_command.toInt (&m_isNumeric); - - // Next: a list of parameters. If any of these parameters - // starts with a colon, we have to read everything that follows - // as a single parameter. - bool readUntilEnd = false; - while (position < serverMessage.size ()) - { - if (buffer.isEmpty () && !readUntilEnd && (serverMessage.at (position) == ':')) - { - readUntilEnd = true; - } - else - { - if (readUntilEnd) - { - buffer.append (serverMessage.at (position)); - } - else - { - if (serverMessage.at (position).isSpace ()) - { - if (!buffer.isEmpty ()) - { - m_parameters.append (buffer); - buffer.clear (); - } - } - else - { - buffer.append (serverMessage.at (position)); - } - } - } - position++; - } - - if (!buffer.isEmpty ()) - { - // We need to chop off \r\n here. - buffer.chop (2); - m_parameters.append (buffer); - } -} - -int -IRCServerMessage::numericValue () -{ - if (m_isNumeric) - return m_codeNumber; - return -1; -} - -QString -IRCServerMessage::parameter (int index) -{ - if (index >= 0 && index < m_parameters.size ()) - return m_parameters.at (index); - return ""; -} - - -IRCChannelProxyImpl::IRCChannelProxyImpl (IRCClientInterface *clientInterface, const QString& channelName, QObject *parent) - : IRCChannelProxyInterface (clientInterface, channelName, parent), - m_clientInterface (clientInterface) -{ - m_channelName = channelName; - connect (clientInterface, SIGNAL (nicknameChanged (QString,QString)), - this, SLOT (handleNickChange (QString,QString))); -} - -QTextDocument * -IRCChannelProxyImpl::conversationModel () -{ - return &m_conversationModel; -} - -QStringListModel * -IRCChannelProxyImpl::userListModel () -{ - return &m_userListModel; -} - -QString -IRCChannelProxyImpl::channelName () -{ - return m_channelName; -} - -void -IRCChannelProxyImpl::setNickList (const QStringList &nickList) -{ - m_userList = nickList; - m_userListModel.setStringList (nickList); -} - -void -IRCChannelProxyImpl::sendMessage (const QString& message) -{ - QStringList arguments; - arguments << m_channelName; - arguments << message; - m_clientInterface->sendIRCCommand (IRCCommand::PrivateMessage, arguments); -} - -void -IRCChannelProxyImpl::sendJoinRequest () -{ - m_clientInterface->sendIRCCommand (IRCCommand::Join, QStringList (m_channelName)); -} - - -void -IRCChannelProxyImpl::leave (const QString& reason) -{ - Q_UNUSED (reason); -} - -void -IRCChannelProxyImpl::handleNickChange (const QString &oldNick, const QString &newNick) -{ - m_userList = m_userListModel.stringList (); - m_userList.removeAll (oldNick); - m_userList.append (newNick); - m_userListModel.setStringList (m_userList); -} - -void -IRCChannelProxyImpl::handleJoin (const QString &nick) -{ - m_userList = m_userListModel.stringList (); - m_userList.append (nick); - m_userListModel.setStringList (m_userList); -} - -IRCClientImpl::IRCClientImpl (QObject *parent) - : IRCClientInterface (parent) -{ - m_loggedIn = false; - connect (&m_tcpSocket, SIGNAL (connected ()), this, SLOT (handleConnected ())); - connect (&m_tcpSocket, SIGNAL (disconnected ()), this, SLOT (handleDisconnected ())); - connect (&m_tcpSocket, SIGNAL (readyRead ()), this, SLOT (handleReadyRead ())); -} - -IRCClientImpl::~IRCClientImpl () -{ - foreach (IRCChannelProxyInterface *ircChannelProxy, m_channels) - { - delete ircChannelProxy; - } -} - -void -IRCClientImpl::connectToHost (const QHostAddress& host, int port, const QString& initialNick) -{ - m_host = host; - m_nickname = initialNick; - m_tcpSocket.connectToHost(host, port); -} - -void -IRCClientImpl::disconnect () -{ - m_tcpSocket.disconnect (); -} - -void -IRCClientImpl::reconnect () -{ - disconnect (); - connectToHost (m_host, m_port, m_nickname); -} - -bool -IRCClientImpl::isConnected () -{ - return m_connected; -} - -bool -IRCClientImpl::isLoggedIn () -{ - return m_loggedIn; -} - -const QHostAddress& -IRCClientImpl::host() -{ - return m_host; -} - -int -IRCClientImpl::port() -{ - return m_port; -} - -IRCChannelProxyInterface * -IRCClientImpl::ircChannelProxy (const QString &channel) -{ - if (!m_channels.contains (channel)) - m_channels[channel] = new IRCChannelProxyImpl(this, channel); - return m_channels[channel]; -} - -void -IRCClientImpl::sendNicknameChangeRequest (const QString &nickname) -{ - sendIRCCommand (IRCCommand::Nick, QStringList (nickname)); -} - -void -IRCClientImpl::sendPrivateMessage (const QString &recipient, const QString &message) -{ - QStringList arguments; - arguments << recipient; - arguments << message; - sendIRCCommand (IRCCommand::PrivateMessage, arguments); -} - -const QString& -IRCClientImpl::nickname () -{ - return m_nickname; -} - -void -IRCClientImpl::handleConnected () -{ - m_connected = true; - QStringList arguments; - arguments << "na" << "0" << "0" << "na"; - sendIRCCommand (IRCCommand::User, arguments); - sendNicknameChangeRequest (m_nickname); - emit connected (m_host.toString ()); -} - -void -IRCClientImpl::handleDisconnected () -{ - m_connected = false; - emit disconnected (); -} - -void -IRCClientImpl::handleReadyRead () -{ - QByteArray line; - do - { - line = m_tcpSocket.readLine(); - if (line.size ()) - handleIncomingLine(QString::fromUtf8(line.data ())); - else - break; - } - while (true); -} - -void -IRCClientImpl::handleNicknameChanged (const QString &oldNick, const QString &newNick) -{ - // Check if our nickname changed. - if (oldNick == m_nickname) - { - m_nickname = newNick; - emit userNicknameChanged (m_nickname); - } - emit nicknameChanged (oldNick, newNick); -} - -void -IRCClientImpl::handleUserJoined (const QString &nick, const QString &channel) -{ - ircChannelProxy (channel)->handleJoin (nick); - emit userJoined (nick, channel); -} - -void -IRCClientImpl::handleUserQuit (const QString &nick, const QString &reason) -{ - emit userQuit (nick, reason); -} - -void -IRCClientImpl::handleIncomingLine (const QString &line) -{ - if (m_connected && !line.isEmpty()) - { - IRCServerMessage ircServerMessage(line); - if (ircServerMessage.isNumeric () == true) - { - switch (ircServerMessage.numericValue ()) - { - case IRCReply::Welcome: - m_loggedIn = true; - emit userNicknameChanged (nickname ()); - emit loggedIn (nickname ()); - break; - case IRCError::NicknameInUse: - case IRCError::NickCollision: - // If we are already logged in, the user attempted to - // switch to a username that is already existing. - // In that case warn him. - if (isLoggedIn ()) - { - emit error ("The nickname is already in use."); - } - // Otherwise we are attempting to log in to the server. - // Change the nick so that we can at least log in. - else - { - m_nickname += "_"; - sendNicknameChangeRequest (m_nickname); - } - break; - case IRCError::PasswordMismatch: - emit error ("The password you provided is not correct."); - break; - case IRCReply::MessageOfTheDayStart: - case IRCReply::MessageOfTheDay: - case IRCReply::MessageOfTheDayEnd: - case IRCError::NoMessageOfTheDay: - break; - case IRCReply::NoTopic: - case IRCReply::Topic: - break; - case IRCReply::NameReply: - QString channel = ircServerMessage.parameter (2); - QString nickList = ircServerMessage.parameter (3); - emit debugMessage (nickList); - ircChannelProxy (channel)->setNickList (nickList.split (QRegExp ("\\s+"), QString::SkipEmptyParts)); - break; - } - } - else - { - QString command = ircServerMessage.command (); - if (command == IRCCommand::Nick) - { - handleNicknameChanged (ircServerMessage.nick(), ircServerMessage.parameter (0)); - } - else if (command == IRCCommand::Quit) - { - handleUserQuit (ircServerMessage.nick (), ircServerMessage.parameter (0)); - } - else if (command == IRCCommand::Join) - { - handleUserJoined(ircServerMessage.nick (), ircServerMessage.parameter (0)); - } - else if (command == IRCCommand::Part) - { - emit debugMessage ("WRITEME: Received part."); - //emit part (ircEvent.getNick ().toStdString ().c_str (), - // ircEvent.getParam (0).toStdString ().c_str (), - // ircEvent.getParam (1).toStdString ().c_str ()); - } - else if (command == IRCCommand::Mode) - { - emit debugMessage ("WRITEME: Received mode."); - //emit mode (&ircEvent); - } - else if (command == IRCCommand::Topic) - { - emit debugMessage - (QString("WRITEME: Received topic: %1") - .arg (ircServerMessage.parameter (0))); - } - else if (command == IRCCommand::Kick) - { - emit debugMessage ("WRITEME: Received kick command."); - } - else if (command == IRCCommand::Invite) - { - emit debugMessage ("WRITEME: Received invite command."); - - } - else if (command == IRCCommand::PrivateMessage) - { - emit message (ircServerMessage.parameter (0), ircServerMessage.nick (), ircServerMessage.parameter (1)); - } - else if (command == IRCCommand::Notice) - { - emit notification (ircServerMessage.nick ().toStdString ().c_str (), - ircServerMessage.parameter (1).toStdString ().c_str ()); - } - else if (command == IRCCommand::Ping) - { - sendIRCCommand (IRCCommand::Pong, QStringList (m_nickname)); - } - else if (command == IRCCommand::Error) - { - emit error (ircServerMessage.parameter (0)); - } - else - { - emit debugMessage (QString("FIXME: Received unknown reply: %1").arg(command)); - } - } - } -} - -void -IRCClientImpl::sendLine (const QString &line) -{ - if (m_connected) - m_tcpSocket.write ( (line + + "\r\n").toUtf8 ()); -} - -void -IRCClientImpl::sendIRCCommand (const QString &command, const QStringList &arguments) -{ - QString line = command; - for (int i = 0; i < arguments.size (); i++) - { - bool applyColon = false; - // Usually all parameters are separated by spaces. - // The last parameter of the message may contain spaces, it is usually used - // to transmit messages. In order to parse it correctly, if needs to be prefixed - // with a colon, so the server knows to ignore all forthcoming spaces and has to treat - // all remaining characters as a single parameter. If we detect any whitespace in the - // last argument, prefix it with a colon: - if ((i == arguments.size () - 1) && arguments.at (i).contains (QRegExp("\\s"))) - applyColon = true; - line += QString (" %1%2").arg (applyColon ? ":" : "").arg (arguments.at (i)); - } - sendLine (line); -}
--- a/gui/src/qirc/IRCClientImpl.h Sun Sep 25 21:12:47 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,355 +0,0 @@ -/* OctaveGUI - A graphical user interface for Octave - * Copyright (C) 2011 Jacob Dawid (jacob.dawid@googlemail.com) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef IRCCLIENTIMPL_H -#define IRCCLIENTIMPL_H - -#include <QTcpSocket> -#include <QHostInfo> -#include <QStringList> -#include <QTextDocument> -#include <QStringListModel> -#include "IRCClientInterface.h" - -/** - * \namespace IRCCommand - * This namespace includes all IRC commands. - */ -namespace IRCCommand -{ - const QString Password = "PASS"; - const QString Nick = "NICK"; - const QString User = "USER"; - const QString Operation = "OPER"; - const QString Service = "SERVICE"; - const QString Quit = "QUIT"; - const QString ServerQuit = "SQUIT"; - - const QString Join = "JOIN"; - const QString Part = "PART"; - const QString Mode = "MODE"; - const QString Topic = "TOPIC"; - const QString Names = "NAMES"; - const QString List = "LIST"; - const QString Invite = "INVITE"; - const QString Kick = "KICK"; - - const QString PrivateMessage = "PRIVMSG"; - const QString Notice = "NOTICE"; - - const QString MessageOfTheDay = "MOTD"; - const QString ListUsers = "LUSERS"; - const QString Version = "VERSION"; - const QString Stats = "STATS"; - const QString Links = "LINKS"; - const QString Time = "TIME"; - const QString Command = "CONNECT"; - const QString Trace = "TRACE"; - const QString Admin = "ADMIN"; - const QString Info = "INFO"; - - const QString ServerList = "SERVLIST"; - const QString ServerQuery = "SQUERY"; - - const QString Who = "WHO"; - const QString WhoIs = "WHOIS"; - const QString WhoWas = "WHOWAS"; - - const QString Kill = "KILL"; - const QString Ping = "PING"; - const QString Pong = "PONG"; - const QString Error = "ERROR"; - - const QString Away = "AWAY"; - const QString Rehash = "REHASH"; - const QString Die = "DIE"; - const QString Restart = "RESTART"; - const QString Summon = "SUMMON"; - const QString Users = "USERS"; - const QString OperatorWall = "OPERWALL"; - const QString UserHost = "USERHOST"; - const QString IsOn = "ISON"; -}; - -/** - * \namespace IRCReply - * This namespace includes all numeric IRC replies. - */ -namespace IRCReply -{ - const int Welcome = 1; - const int YourHost = 2; - const int Created = 3; - const int MyInfo = 4; - const int ReplyBounce = 5; - const int UserHost = 302; - const int IsOn = 303; - const int Away = 301; - const int UnAway = 305; - const int NoAway = 306; - const int WhoIsUser = 311; - const int WhoIsServer = 312; - const int WhoIsOperator = 313; - const int WhoIsIdle = 317; - const int EndOfWhoIs = 318; - const int WhoIsChannels = 319; - const int WhoWasUser = 314; - const int EndOfWhoWas = 369; - const int ListStart = 321; - const int List = 322; - const int ListEnd = 323; - const int UniqueOpIs = 325; - const int ChannelModeIs = 324; - const int NoTopic = 331; - const int Topic = 332; - const int Inviting = 341; - const int Summoning = 342; - const int InviteList = 346; - const int EndOfInviteList = 347; - const int ExceptList = 348; - const int EndOfExceptList = 349; - const int Version = 351; - const int WhoReply = 352; - const int EndOfWho = 315; - const int NameReply = 353; - const int EndOfNames = 366; - const int Links = 364; - const int EndOfLinks = 367; - const int BanList = 368; - const int Info = 371; - const int EndOfInfo = 374; - const int MessageOfTheDayStart = 375; - const int MessageOfTheDay = 372; - const int MessageOfTheDayEnd = 376; - const int YouAreOperator = 381; - const int Rehashing = 382; - const int YouAreService = 383; - const int Time = 391; - const int UserStart = 392; - const int Users = 393; - const int EndOfUsers = 394; - const int NoUsers = 395; - const int TraceLink = 200; - const int TraceConnecting = 201; - const int TraceHandshake = 202; - const int TraceUnknown = 203; - const int TraceOperator = 204; - const int TraceUser = 205; - const int TraceServer = 206; - const int TraceService = 207; - const int TraceNewType = 208; - const int TraceClass = 209; - const int TraceConnect = 210; - const int TraceLog = 261; - const int TraceEnd = 262; - const int StatsLinkInfo = 211; - const int StatsCommands = 212; - const int EndOfStats = 219; - const int StatsUptime = 242; - const int StatsOnline = 243; - const int UModeIs = 221; - const int ServerList = 234; - const int ServerListEnd = 235; - const int ListUserClient = 251; - const int ListUserOperator = 252; - const int ListUserUnknown = 253; - const int ListUserChannels = 254; - const int ListUserMe = 255; - const int AdminMe = 256; - const int AdminLoc1 = 257; - const int AdminLoc2 = 258; - const int AdminEmail = 259; - const int TryAgain = 263; -}; - -/** - * \namespace IRCError - * This namespace includes all numeric IRC errors. - */ -namespace IRCError -{ - const int NoSuchNick = 401; - const int NoSuchServer = 402; - const int NoSuchChannel = 403; - const int CannotSendToChannel = 404; - const int TooManyChannels = 405; - const int WasNoSuchNick = 406; - const int TooManyTargets = 407; - const int NoSuchService = 408; - const int NoOrigin = 409; - const int NoRecipient = 411; - const int NoTextToSend = 412; - const int NoTopLevel = 413; - const int WildTopLevel = 414; - const int BasMask = 415; - const int UnknownCommand = 421; - const int NoMessageOfTheDay = 422; - const int NoAdminInfo = 423; - const int FileError = 424; - const int NoNickNameGiven = 431; - const int ErroneusNick = 432; - const int NicknameInUse = 433; - const int NickCollision = 436; - const int UnavailResource = 437; - const int UserNotInChannel = 441; - const int NotOnChannel = 442; - const int UserOnChannel = 443; - const int NoLogin = 444; - const int SummonDisabled = 445; - const int UsersDisabled = 446; - const int NotRegistered = 451; - const int NeedMoreParams = 461; - const int AlreadyRegistered = 462; - const int NoPermissionForHost = 463; - const int PasswordMismatch = 464; - const int YouAreBannedCreep = 465; - const int YouWillBeBanned = 466; - const int KeySet = 467; - const int ChannelIsFull = 471; - const int UnknownMode = 472; - const int InviteOnlyChannel = 473; - const int BannedFromChannel = 474; - const int BadChannelKey = 475; - const int BadChannelMask = 476; - const int NoChannelModes = 477; - const int BanListFull = 478; - const int NoPrivileges = 481; - const int ChannelOperatorPrivilegesNeeded = 482; - const int CannotKillServer = 483; - const int Restricted = 484; - const int UniqueOperatorPrivilegesNeeded = 485; - const int NoOperatorHost = 491; - const int YourModeListUnknownFlag = 501; - const int UsersDontMatch = 502; -}; - -/** - * \class IRCServerMessage - * The IRCServerMessage class is a wrapper for server messages. - * It parses the server message into its single bits and makes these - * available through Getter-methods. - */ -class IRCServerMessage -{ -public: - IRCServerMessage (const QString& serverMessage); - - bool isNumeric () - { return m_isNumeric; } - - QString nick () - { return m_nick; } - - QString command () - { return m_command; } - - int numericValue (); - QString parameter (int index); - -private: - int m_codeNumber; - bool m_isNumeric; - QString m_nick; - QString m_user; - QString m_host; - QString m_command; - QStringList m_parameters; -}; - -/** - * \class IRCChannelProxyImpl - * Implements a handle to an IRC channel. This is usually provided by the - * the IRC client class. - */ -class IRCChannelProxyImpl : public IRCChannelProxyInterface -{ - Q_OBJECT -public: - IRCChannelProxyImpl (IRCClientInterface *clientInterface, const QString& channelName, QObject *parent = 0); - QTextDocument *conversationModel (); - QStringListModel *userListModel (); - QString channelName (); - - void setNickList (const QStringList &nickList); - void sendMessage (const QString& message); - void sendJoinRequest (); - void leave (const QString &reason); -public slots: - void handleNickChange (const QString& oldNick, const QString& newNick); - void handleJoin (const QString& nick); -private: - QString m_channelName; - QStringList m_userList; - QStringListModel m_userListModel; - QTextDocument m_conversationModel; - IRCClientInterface *m_clientInterface; -}; - -/** - * \class IRCClientImpl - * Implements an IRC client. This class can maintain a connection to one server. - * In order to interface an IRC channel, use the ircChannelProxy-method to retrieve - * a handle. - */ -class IRCClientImpl : public IRCClientInterface -{ - Q_OBJECT -public: - IRCClientImpl (QObject *parent = 0); - ~IRCClientImpl (); - - const QString& nickname (); - bool isConnected (); - bool isLoggedIn (); - const QHostAddress& host(); - int port(); - IRCChannelProxyInterface *ircChannelProxy(const QString& channel); - void sendIRCCommand (const QString& command, const QStringList& arguments); - -public slots: - void connectToHost (const QHostAddress& host, int port, const QString& initialNick); - void disconnect (); - void reconnect (); - - void sendNicknameChangeRequest (const QString &nickname); - void sendPrivateMessage (const QString &recipient, const QString &message); - -signals: - void debugMessage (const QString& message); - -private slots: - void handleConnected (); - void handleDisconnected (); - void handleReadyRead (); - -private: - void handleNicknameChanged (const QString& oldNick, const QString& newNick); - void handleUserJoined (const QString& nick, const QString& channel); - void handleUserQuit (const QString& nick, const QString& reason); - void handleIncomingLine (const QString& line); - void sendLine (const QString& line); - - QHostAddress m_host; - int m_port; - QString m_nickname; - bool m_connected; - bool m_loggedIn; - QTcpSocket m_tcpSocket; - QMap<QString, IRCChannelProxyInterface*> m_channels; -}; - -#endif // IRCCLIENTIMPL_H
--- a/gui/src/qirc/IRCClientInterface.h Sun Sep 25 21:12:47 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,221 +0,0 @@ -/* OctaveGUI - A graphical user interface for Octave - * Copyright (C) 2011 Jacob Dawid (jacob.dawid@googlemail.com) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef IRCCLIENTINTERFACE_H -#define IRCCLIENTINTERFACE_H - -#include <QString> -#include <QObject> -#include <QHostAddress> -#include <QTextDocument> -#include <QStringListModel> - -class IRCClientInterface; -/** - * \class IRCChannelProxyInterface - * Interface for a handle to an IRC channel. - */ -class IRCChannelProxyInterface : public QObject -{ - Q_OBJECT -public: - IRCChannelProxyInterface (IRCClientInterface *, const QString&, QObject *parent = 0) : QObject (parent) { } - virtual ~IRCChannelProxyInterface () { } - - /** Returns the conversation model part. */ - virtual QTextDocument *conversationModel () = 0; - - /** Returns a string list model for the user list. */ - virtual QStringListModel *userListModel () = 0; - - /** Returns the name of this channel. */ - virtual QString channelName () = 0; - - /** - * Overwrites the current nick list by settings a new nick list. - * \arg nickList The new nick list to set. - */ - virtual void setNickList (const QStringList& nickList) = 0; - - /** - * Sends a public message onto this channel. - * \arg message The message that should be sent. - */ - virtual void sendMessage (const QString& message) = 0; - - /** Requests to join this channel. */ - virtual void sendJoinRequest () = 0; - - /** - * Requests to leave this channel. - * \arg reason Reason for leaving the channel. - */ - virtual void leave (const QString& reason) = 0; - -public slots: - virtual void handleNickChange (const QString& oldNick, const QString& newNick) = 0; - virtual void handleJoin (const QString& nick) = 0; -}; - -/** - * \class IRCClientInterface - * IRC Clients need to implement this interface. - */ -class IRCClientInterface : public QObject -{ - Q_OBJECT -public: - IRCClientInterface (QObject *parent = 0) : QObject (parent) { } - virtual ~IRCClientInterface () { } - - /** Returns the current nickname of this client. */ - virtual const QString& nickname () = 0; - - /** Returns true if connected to the server. */ - virtual bool isConnected () = 0; - - /** - * Returns true if logged in to the server. - * Note: There is a small difference between isConnected and isLoggedIn. - * isConnected returns true if there is a physical connection to the server. - * isLoggedIn only returns true if the server has already accepted you - * and you are ready to log into channels. - */ - virtual bool isLoggedIn () = 0; - - /** Returns the current host address. */ - virtual const QHostAddress& host() = 0; - - /** Returns the current port. */ - virtual int port() = 0; - - /** - * Returns a handle to an IRC channel. - * Note: Retrieving a handle does not mean you have joined this channel. - * \arg channel The channel to retrieve a handle for. - */ - virtual IRCChannelProxyInterface *ircChannelProxy(const QString& channel) = 0; - - /** - * Send an IRC command to the server. - * \arg command Command to send. - * \arg arguments Arguments to send. - */ - virtual void sendIRCCommand (const QString& command, const QStringList& arguments) = 0; - -public slots: - /** - * Connects to a host. - * \arg host The host to connect tp. - * \arg port The port on which to connect to the host. - * \arg initialNick The initial nick to use when attempting to login. - */ - virtual void connectToHost (const QHostAddress& host, int port, const QString& initialNick) = 0; - - /** Disconnects from the host. */ - virtual void disconnect () = 0; - - /** Reconnects to the host. */ - virtual void reconnect () = 0; - - /** - * Sends a request to change the nickname. - * \arg nickname The new nickname to be requested. - */ - virtual void sendNicknameChangeRequest (const QString& nickname) = 0; - - /** - * Sends a private message. - * \arg recipient The nickname or channel that message should be sent to. - * \arg message The message that should be sent. - */ - virtual void sendPrivateMessage (const QString& recipient, const QString& message) = 0; - -signals: - /** - * Sent upon the arrival of a new message. - * \arg channel The channel this message was sent from. - * \arg sender The nickname of the sender. - * \arg message The message that has been sent. - */ - void newMessage (const QString& channel, const QString& sender, const QString& message); - void message (const QString& channel, const QString& sender, const QString& message); - - /** - * Sent when the connection to a server has been established. - * \arg server The name of the server that the connection has been established to. - */ - void connected (const QString& server); - - /** Sent when the connection to the server has been interrupted. */ - void disconnected (); - - /** - * Sent when an error occurs. - * \arg message A descriptive message of the error that occured. - */ - void error (const QString& message); - - /** - * Sent when a notification arrives. - * \arg sender The source of the notification. - * \arg message The notification. - */ - void notification (const QString& sender, const QString& message); - - /** - * Sent when a nickname changed. - * \arg oldNick The previous nickname. - * \arg newNick The new nickname. - */ - void nicknameChanged (const QString& oldNick, const QString& newNick); - - /** - * Sent when the nickname of this client changed. - * \arg nick The new nickname of this client. - */ - void userNicknameChanged (const QString& nick); - - /** - * Sent when a user has joined a channel. - * \arg nick Nickname of the user that joined the channel. - * \arg channel Channel that this user joined. - */ - void userJoined (const QString& nick, const QString& channel); - - /** - * Sent when a user quits. - * \arg nick Nickname of the user that quit. - * \arg reason Reason of the user to quit. - */ - void userQuit (const QString& nick, const QString& reason); - - /** - * Sent when a user logged in. - * \arg nick The nickname of the user that logged in. - */ - void loggedIn (const QString& nick); - - /** - * Sent when the server provides a userlist for a channel. - * \arg channel The channel that userlist applies to. - * \arg list The actual userlist. - */ - void userList (const QString& channel, const QStringList& list); -}; - -#endif // IRCCLIENTINTERFACE_H
--- a/gui/src/qirc/IRCCodes.h Sun Sep 25 21:12:47 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,223 +0,0 @@ -/* OctaveGUI - A graphical user interface for Octave - * Copyright (C) 2011 Jacob Dawid - * jacob.dawid@googlemail.com - * - * 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 3 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, see <http://www.gnu.org/licenses/>. - */ - -#ifndef IRCCODES_H -#define IRCCODES_H -#include <QString> - -namespace IRCCommand -{ - const QString Password = "PASS"; - const QString Nick = "NICK"; - const QString User = "USER"; - const QString Operation = "OPER"; - const QString Service = "SERVICE"; - const QString Quit = "QUIT"; - const QString ServerQuit = "SQUIT"; - - const QString Join = "JOIN"; - const QString Part = "PART"; - const QString Mode = "MODE"; - const QString Topic = "TOPIC"; - const QString Names = "NAMES"; - const QString List = "LIST"; - const QString Invite = "INVITE"; - const QString Kick = "KICK"; - - const QString PrivateMessage = "PRIVMSG"; - const QString Notice = "NOTICE"; - - const QString MessageOfTheDay = "MOTD"; - const QString ListUsers = "LUSERS"; - const QString Version = "VERSION"; - const QString Stats = "STATS"; - const QString Links = "LINKS"; - const QString Time = "TIME"; - const QString Command = "CONNECT"; - const QString Trace = "TRACE"; - const QString Admin = "ADMIN"; - const QString Info = "INFO"; - - const QString ServerList = "SERVLIST"; - const QString ServerQuery = "SQUERY"; - - const QString Who = "WHO"; - const QString WhoIs = "WHOIS"; - const QString WhoWas = "WHOWAS"; - - const QString Kill = "KILL"; - const QString Ping = "PING"; - const QString Pong = "PONG"; - const QString Error = "ERROR"; - - const QString Away = "AWAY"; - const QString Rehash = "REHASH"; - const QString Die = "DIE"; - const QString Restart = "RESTART"; - const QString Summon = "SUMMON"; - const QString Users = "USERS"; - const QString OperatorWall = "OPERWALL"; - const QString UserHost = "USERHOST"; - const QString IsOn = "ISON"; -}; - -namespace IRCReply -{ - const int Welcome = 1; - const int YourHost = 2; - const int Created = 3; - const int MyInfo = 4; - const int ReplyBounce = 5; - const int UserHost = 302; - const int IsOn = 303; - const int Away = 301; - const int UnAway = 305; - const int NoAway = 306; - const int WhoIsUser = 311; - const int WhoIsServer = 312; - const int WhoIsOperator = 313; - const int WhoIsIdle = 317; - const int EndOfWhoIs = 318; - const int WhoIsChannels = 319; - const int WhoWasUser = 314; - const int EndOfWhoWas = 369; - const int ListStart = 321; - const int List = 322; - const int ListEnd = 323; - const int UniqueOpIs = 325; - const int ChannelModeIs = 324; - const int NoTopic = 331; - const int Topic = 332; - const int Inviting = 341; - const int Summoning = 342; - const int InviteList = 346; - const int EndOfInviteList = 347; - const int ExceptList = 348; - const int EndOfExceptList = 349; - const int Version = 351; - const int WhoReply = 352; - const int EndOfWho = 315; - const int NameReply = 353; - const int EndOfNames = 366; - const int Links = 364; - const int EndOfLinks = 367; - const int BanList = 368; - const int Info = 371; - const int EndOfInfo = 374; - const int MessageOfTheDayStart = 375; - const int MessageOfTheDay = 372; - const int MessageOfTheDayEnd = 376; - const int YouAreOperator = 381; - const int Rehashing = 382; - const int YouAreService = 383; - const int Time = 391; - const int UserStart = 392; - const int Users = 393; - const int EndOfUsers = 394; - const int NoUsers = 395; - const int TraceLink = 200; - const int TraceConnecting = 201; - const int TraceHandshake = 202; - const int TraceUnknown = 203; - const int TraceOperator = 204; - const int TraceUser = 205; - const int TraceServer = 206; - const int TraceService = 207; - const int TraceNewType = 208; - const int TraceClass = 209; - const int TraceConnect = 210; - const int TraceLog = 261; - const int TraceEnd = 262; - const int StatsLinkInfo = 211; - const int StatsCommands = 212; - const int EndOfStats = 219; - const int StatsUptime = 242; - const int StatsOnline = 243; - const int UModeIs = 221; - const int ServerList = 234; - const int ServerListEnd = 235; - const int ListUserClient = 251; - const int ListUserOperator = 252; - const int ListUserUnknown = 253; - const int ListUserChannels = 254; - const int ListUserMe = 255; - const int AdminMe = 256; - const int AdminLoc1 = 257; - const int AdminLoc2 = 258; - const int AdminEmail = 259; - const int TryAgain = 263; -}; - -namespace IRCError -{ - const int NoSuchNick = 401; - const int NoSuchServer = 402; - const int NoSuchChannel = 403; - const int CannotSendToChannel = 404; - const int TooManyChannels = 405; - const int WasNoSuchNick = 406; - const int TooManyTargets = 407; - const int NoSuchService = 408; - const int NoOrigin = 409; - const int NoRecipient = 411; - const int NoTextToSend = 412; - const int NoTopLevel = 413; - const int WildTopLevel = 414; - const int BasMask = 415; - const int UnknownCommand = 421; - const int NoMessageOfTheDay = 422; - const int NoAdminInfo = 423; - const int FileError = 424; - const int NoNickNameGiven = 431; - const int ErroneusNick = 432; - const int NicknameInUse = 433; - const int NickCollision = 436; - const int UnavailResource = 437; - const int UserNotInChannel = 441; - const int NotOnChannel = 442; - const int UserOnChannel = 443; - const int NoLogin = 444; - const int SummonDisabled = 445; - const int UsersDisabled = 446; - const int NotRegistered = 451; - const int NeedMoreParams = 461; - const int AlreadyRegistered = 462; - const int NoPermissionForHost = 463; - const int PasswordMismatch = 464; - const int YouAreBannedCreep = 465; - const int YouWillBeBanned = 466; - const int KeySet = 467; - const int ChannelIsFull = 471; - const int UnknownMode = 472; - const int InviteOnlyChannel = 473; - const int BannedFromChannel = 474; - const int BadChannelKey = 475; - const int BadChannelMask = 476; - const int NoChannelModes = 477; - const int BanListFull = 478; - const int NoPrivileges = 481; - const int ChannelOperatorPrivilegesNeeded = 482; - const int CannotKillServer = 483; - const int Restricted = 484; - const int UniqueOperatorPrivilegesNeeded = 485; - const int NoOperatorHost = 491; - const int YourModeListUnknownFlag = 501; - const int UsersDontMatch = 502; -}; - -#endif
--- a/gui/src/qirc/IRCWidget.cpp Sun Sep 25 21:12:47 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,448 +0,0 @@ -/* OctaveGUI - A graphical user interface for Octave - * Copyright (C) 2011 Jacob Dawid (jacob.dawid@googlemail.com) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "ResourceManager.h" -#include "IRCWidget.h" -#include <QMessageBox> -#include <QHBoxLayout> -#include <QVBoxLayout> -#include <QLabel> -#include <QSettings> -#include <QInputDialog> -#include <QKeyEvent> -#include <QScrollBar> -#include <QApplication> -#include "IRCClientImpl.h" - -ChatMessageTextEdit::ChatMessageTextEdit (QWidget *parent) - : QPlainTextEdit (parent), m_completer (0) -{ - setMaximumHeight (50); - setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); -} - -ChatMessageTextEdit::~ChatMessageTextEdit () -{ -} - -void -ChatMessageTextEdit::setCompleter (QCompleter *completer) -{ - if (m_completer) - QObject::disconnect (m_completer, 0, this, 0); - - m_completer = completer; - - if (!m_completer) - return; - - m_completer->setWidget (this); - m_completer->setCompletionMode (QCompleter::PopupCompletion); - m_completer->setCaseSensitivity (Qt::CaseInsensitive); - QObject::connect (m_completer, SIGNAL (activated (QString)), - this, SLOT (insertCompletion (QString))); -} - -QCompleter * -ChatMessageTextEdit::completer () const -{ - return m_completer; -} - -void -ChatMessageTextEdit::insertCompletion(const QString& completion) -{ - - if (m_completer->widget() != this) - return; - QTextCursor tc = textCursor(); - int extra = completion.length() - m_completer->completionPrefix().length(); - tc.movePosition(QTextCursor::Left); - tc.movePosition(QTextCursor::EndOfWord); - tc.insertText(completion.right(extra)); - setTextCursor(tc); -} - -QString -ChatMessageTextEdit::textUnderCursor () const -{ - QTextCursor tc = textCursor (); - tc.select (QTextCursor::WordUnderCursor); - return tc.selectedText (); -} - -void -ChatMessageTextEdit::focusInEvent (QFocusEvent *e) -{ - if (m_completer) - m_completer->setWidget (this); - QPlainTextEdit::focusInEvent (e); -} - -void -ChatMessageTextEdit::keyPressEvent (QKeyEvent *keyPressEvent) -{ - if (m_completer) { - switch (keyPressEvent->key ()) { - case Qt::Key_Enter: - case Qt::Key_Return: - if (! (keyPressEvent->modifiers () & Qt::ShiftModifier)) - { - emit sendMessage (document ()->toPlainText ()); - document ()->setPlainText (""); - } - else - { - QPlainTextEdit::keyPressEvent (keyPressEvent); - } - break; - case Qt::Key_Escape: - case Qt::Key_Tab: - case Qt::Key_Backtab: - keyPressEvent->ignore (); - return; - default: - QPlainTextEdit::keyPressEvent(keyPressEvent); - break; - } - - QString completionPrefix = textUnderCursor (); - if (completionPrefix != m_completer->completionPrefix ()) - { - m_completer->setCompletionPrefix(completionPrefix); - } - - if (completionPrefix.length() > 2) - { - m_completer->popup ()->setCurrentIndex (m_completer->completionModel ()->index (0, 0)); - m_completer->complete (); - } - else - { - m_completer->popup ()->hide (); - } - } -} - -IRCWidget::IRCWidget (QWidget * parent): -QWidget (parent) -{ - QSettings *settings = ResourceManager::instance ()->settings (); - bool connectOnStartup = settings->value ("connectOnStartup").toBool (); - m_autoIdentification = settings->value ("autoIdentification").toBool (); - m_nickServPassword = settings->value ("nickServPassword").toString (); - - m_initialNick = settings->value ("IRCNick").toString (); - - if (m_initialNick.isEmpty ()) - m_initialNick = "OctaveGUI-User"; - - QVBoxLayout *layout = new QVBoxLayout (); - - m_chatWindow = new QTextEdit (this); - m_chatWindow->setReadOnly (true); - m_chatWindow->setEnabled (false); - QWidget *bottomWidget = new QWidget (this); - - layout->addWidget (m_chatWindow); - layout->addWidget (bottomWidget); - layout->setMargin (0); - setLayout (layout); - - QHBoxLayout *bottomLayout = new QHBoxLayout (); - m_nickButton = new QPushButton (bottomWidget); - m_nickButton->setStatusTip (tr ((char *) "Click here to change your nick.")); - m_nickButton->setText (m_initialNick); - m_chatMessageTextEdit = new ChatMessageTextEdit (bottomWidget); - m_chatMessageTextEdit->setStatusTip (tr ((char *) "Enter your message here.")); - - bottomLayout->addWidget (m_nickButton); - bottomLayout->addWidget (new QLabel (":", this)); - bottomLayout->addWidget (m_chatMessageTextEdit); - bottomLayout->setMargin (0); - bottomWidget->setLayout (bottomLayout); - - m_nickButton->setEnabled (false); - m_chatMessageTextEdit->setEnabled (false); - - //setFocusProxy (m_chatMessageTextEdit); - m_nickButton->setFocusProxy (m_chatMessageTextEdit); - - QFont font; - font.setFamily ("Courier"); - font.setPointSize (11); - m_chatWindow->setFont (font); - m_ircClientInterface = new IRCClientImpl (this); - m_octaveChannel = m_ircClientInterface->ircChannelProxy ("#octave"); - - connect (m_ircClientInterface, SIGNAL (connected (QString)), - this, SLOT (handleConnected (QString))); - connect (m_ircClientInterface, SIGNAL(loggedIn(QString)), - this, SLOT (joinOctaveChannel (QString))); - connect (m_ircClientInterface, SIGNAL (error (QString)), - this, SLOT (showErrorMessage (QString))); - connect (m_ircClientInterface, SIGNAL (debugMessage (QString)), - this, SLOT (showStatusMessage (QString))); - connect (m_ircClientInterface, SIGNAL (message (QString, QString, QString)), - this, SLOT (showMessage (QString, QString, QString ))); - connect (m_ircClientInterface, SIGNAL (nicknameChanged (QString,QString)), - this, SLOT (handleNickChange (QString,QString))); - connect (m_ircClientInterface, SIGNAL (notification (QString,QString)), - this, SLOT (showNotification (QString,QString))); - connect (m_ircClientInterface, SIGNAL (loggedIn (QString)), - this, SLOT (handleLoggedIn(QString))); - connect (m_ircClientInterface, SIGNAL (userNicknameChanged (QString)), - this, SLOT (handleUserNicknameChanged (QString))); - - connect (m_nickButton, SIGNAL (clicked ()), this, SLOT (showChangeUserNickPopup ())); - connect (m_chatMessageTextEdit, SIGNAL (sendMessage (QString)), - this, SLOT (sendMessage (QString))); - - m_chatMessageTextEdit->setCompleter - (new QCompleter (m_ircClientInterface->ircChannelProxy ("#octave")->userListModel (), this)); - m_chatWindow->setDocument (m_octaveChannel->conversationModel ()); - - if (connectOnStartup) - connectToServer (); -} - -void -IRCWidget::connectToServer () -{ - showStatusMessage ("Looking up irc.freenode.net."); - QHostInfo hostInfo = QHostInfo::fromName ("irc.freenode.net"); - QList<QHostAddress> hostAddresses = hostInfo.addresses(); - if (hostAddresses.isEmpty ()) - { - showStatusMessage ("Failed to lookup irc.freenode.net."); - } - else - { - showStatusMessage (QString ("Attempting to connect to %1.") - .arg (hostAddresses.at (0).toString ())); - m_ircClientInterface->connectToHost(hostAddresses.at (0), 6667, m_initialNick); - } -} - -void -IRCWidget::showStatusMessage (const QString& message) -{ - m_chatWindow->append (QString ("<i>%1</i>").arg (message)); -} - -void -IRCWidget::showErrorMessage (const QString& message) -{ - m_chatWindow->append (QString ("<i>Error: %1</i>").arg (message)); -} - -void -IRCWidget::handleConnected (const QString &host) -{ - showStatusMessage (QString ("Connected to server %1.").arg (host)); -} - -void -IRCWidget::joinOctaveChannel (const QString& nick) -{ - Q_UNUSED (nick); - showStatusMessage (QString ("Joining channel #octave.")); - m_octaveChannel->sendJoinRequest (); -} - -void -IRCWidget::showMessage (const QString& channel, const QString& sender, const QString& message) -{ - Q_UNUSED (channel); - - // TODO: This doesn't work properly! - // Every message makes it emit unreadMessage (true), - // though it should inly be emitted when this window - // does not have focus, ie. is not the active window. - if (!(hasFocus() - || m_chatMessageTextEdit->hasFocus () - || m_nickButton->hasFocus () - || m_chatWindow->hasFocus () )) - { - emit unreadMessages (true); - } - - QString output; - QString htmlMessage = message; - htmlMessage.replace ("<", "<"); - htmlMessage.replace (">", ">"); - htmlMessage.replace ("\n", "<br>"); - if (message.contains (m_ircClientInterface->nickname ())) - { - output = - QString ("<font color=\"#990000\"><b>%1:</b> %2</font>").arg (sender). - arg (htmlMessage); - - QApplication::alert (this); - } - else - { - output = - QString ("<b>%1:</b> %2").arg (sender). - arg (htmlMessage); - } - m_chatWindow->append (output); - scrollToBottom (); -} - -void -IRCWidget::showNotification (const QString& sender, const QString& message) -{ - Q_UNUSED (sender); - m_chatWindow->append (QString ("<font color=\"#007700\">%1</font>").arg (message)); - scrollToBottom (); -} - -void -IRCWidget::showChangeUserNickPopup () -{ - bool ok; - QString newNick = - QInputDialog::getText (this, QString ("Nickname"), - QString ("Type in your nickname:"), - QLineEdit::Normal, m_ircClientInterface->nickname (), &ok); - if (ok) - { - m_ircClientInterface->sendNicknameChangeRequest (newNick); - } -} - -void -IRCWidget::sendMessage (QString message) -{ - // Do not send empty messages. - if (message.isEmpty ()) - return; - - // Remove trailing spaces. - while (message.at (0).isSpace ()) - message.remove (0, 1); - if (message.startsWith ("/")) - { - QStringList line = - message.split (QRegExp ("\\s+"), QString::SkipEmptyParts); - if (line.at (0) == "/join") - { - IRCChannelProxyInterface *ircChannel = m_ircClientInterface->ircChannelProxy (line.at (1)); - ircChannel->sendJoinRequest (); - } - else if (line.at (0) == "/nick") - { - m_ircClientInterface->sendNicknameChangeRequest (line.at (1)); - } - else if (line.at (0) == "/msg") - { - QString recipient = line.at (1); - // Since we splitted the message before, we have to glue it together again. - QString pmsg = ""; - for (int i = 2; i < line.length (); i++) - { - pmsg += line.at (i); - pmsg += " "; - } - m_ircClientInterface->sendPrivateMessage(recipient, pmsg); - } - } - else - { - m_octaveChannel->sendMessage (message); - message.replace ("<", "<"); - message.replace (">", ">"); - message.replace ("\n", "<br>"); - m_chatWindow->append (QString ("<b>%1:</b> %2"). - arg (m_ircClientInterface->nickname ()).arg (message)); - } - - scrollToBottom (); -} - -void -IRCWidget::maybeIdentifyOnNickServ () -{ - if (m_autoIdentification) - { - m_ircClientInterface->sendPrivateMessage("NickServ", QString ("identify %1"). - arg (m_nickServPassword)); - } -} - -void -IRCWidget::scrollToBottom () -{ - if (m_chatWindow->verticalScrollBar ()) - { - m_chatWindow->verticalScrollBar ()->setValue (m_chatWindow->verticalScrollBar ()->maximum ()); - } -} - -void -IRCWidget::focusInEvent (QFocusEvent *focusEvent) -{ - Q_UNUSED (focusEvent); - emit unreadMessages (false); - QWidget::focusInEvent (focusEvent); - - m_chatMessageTextEdit->setFocus (); -} - -void -IRCWidget::handleLoggedIn (const QString &nick) -{ - m_chatWindow-> - append (QString - ("<i><font color=\"#00AA00\"><b>Successfully logged in as %1.</b></font></i>"). - arg (nick)); - m_nickButton->setEnabled (true); - m_chatMessageTextEdit->setEnabled (true); - m_chatWindow->setEnabled (true); - m_chatMessageTextEdit->setFocus (); -} - -void -IRCWidget::handleNickChange (const QString &oldNick, const QString &newNick) -{ - m_chatWindow->append (QString ("%1 is now known as %2.").arg (oldNick).arg (newNick)); - scrollToBottom (); -} - -void -IRCWidget::handleUserJoined (const QString &nick, const QString &channel) -{ - m_chatWindow->append (QString ("<i>%1 has joined %2.</i>").arg (nick).arg (channel)); - scrollToBottom (); -} - -void -IRCWidget::handleUserQuit (const QString &nick, const QString &reason) -{ - m_chatWindow->append (QString ("<i>%1 has quit.(%2).</i>").arg (nick).arg (reason)); - scrollToBottom (); -} - -void -IRCWidget::handleUserNicknameChanged (const QString &nick) -{ - m_nickButton->setText (nick); - QSettings *settings = ResourceManager::instance ()->settings (); - settings->setValue ("IRCNick", nick); - maybeIdentifyOnNickServ (); -}
--- a/gui/src/qirc/IRCWidget.h Sun Sep 25 21:12:47 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -/* OctaveGUI - A graphical user interface for Octave - * Copyright (C) 2011 Jacob Dawid (jacob.dawid@googlemail.com) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef IRCWIDGET_H -#define IRCWIDGET_H - -#include <QWidget> -#include <QPlainTextEdit> -#include <QPushButton> -#include <QLineEdit> -#include <QCompleter> -#include "IRCClientInterface.h" - -class ChatMessageTextEdit : public QPlainTextEdit -{ - Q_OBJECT -public: - explicit ChatMessageTextEdit(QWidget *parent = 0); - ~ChatMessageTextEdit(); - - void setCompleter(QCompleter *m_completer); - QCompleter *completer() const; - -signals: - void sendMessage (const QString& message); - -protected: - void keyPressEvent(QKeyEvent *e); - void focusInEvent(QFocusEvent *e); - -private slots: - void insertCompletion(const QString &completion); - -private: - QString textUnderCursor() const; - -private: - QCompleter *m_completer; -}; - -class IRCWidget : public QWidget -{ -Q_OBJECT public: - explicit IRCWidget (QWidget * parent); - void connectToServer (); - -public slots: - void showStatusMessage (const QString&); - void showErrorMessage (const QString&); - void showMessage (const QString& channel, const QString& sender, const QString& message); - void showNotification (const QString& sender, const QString& message); - - void handleConnected (const QString& host); - void joinOctaveChannel (const QString& nick); - - void handleLoggedIn (const QString& nick); - void handleNickChange (const QString& oldNick, const QString& newNick); - void handleUserJoined (const QString& nick, const QString& channel); - void handleUserQuit (const QString& nick, const QString& reason); - void handleUserNicknameChanged (const QString& nick); - - void showChangeUserNickPopup (); - void sendMessage (QString); - - void maybeIdentifyOnNickServ (); - void scrollToBottom (); - -signals: - void unreadMessages (bool yes); - -protected: - void focusInEvent (QFocusEvent *focusEvent); - -private: - IRCClientInterface *m_ircClientInterface; - IRCChannelProxyInterface *m_octaveChannel; - QTextEdit *m_chatWindow; - QPushButton *m_nickButton; - ChatMessageTextEdit *m_chatMessageTextEdit; - - QString m_initialNick; - bool m_autoIdentification; - QString m_nickServPassword; - QString m_settingsFile; -}; - -#endif // IRCWIDGET_H
--- a/gui/src/qirc/Makefile.am Sun Sep 25 21:12:47 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -####### kdevelop will overwrite this part!!! (begin)########## -bin_PROGRAMS = qirc - qirc_SOURCES = - programcommand.cpp newtab.cpp MainTab.cpp notifyshowcase.cpp channellist. - cpp dccget.cpp dccsend.cpp IServerSocket.cpp general.cpp listanicks. - cpp qirc.cpp ventanas.cpp inputBox.cpp cuadroListaNicks. - cpp cuadroConfiguracion.cpp cuadroConectarCon.cpp colamensajes. - cpp IRCClient.cpp IClientSocket.cpp Config.cpp ChatView.cpp main. - cpp qirc_LDADD = -lqt - lXext - lX11 $ (LIBSOCKET) SUBDIRS = - docs EXTRA_DIST = - main.cpp qirc.h ChatView.cpp ChatView.h Config.cpp Config.h IClientSocket. - cpp IClientSocket.h IRCClient.cpp IRCClient.h IRCCodes.h colamensajes. - cpp colamensajes.h cuadroConectarCon.cpp cuadroConectarCon. - h cuadroConfiguracion.cpp cuadroConfiguracion.h cuadroListaNicks. - cpp cuadroListaNicks.h inputBox.cpp inputBox.h ventanas.cpp ventanas.h qirc. - cpp resource.h qirc16x16.xpm qirc32x32.xpm qirc64x64.xpm listanicks. - cpp listanicks.h general.h general.cpp IServerSocket.cpp IServerSocket. - h dccsend.cpp dccsend.h dccget.cpp dccget.h connect.xpm dccsend.xpm help. - xpm connectto.xpm disconnect.xpm join.xpm part.xpm list.xpm channellist. - cpp channellist.h notifyshowcase.cpp notifyshowcase.h offline.xpm online. - xpm operator.xpm justconn.xpm MainTab.cpp MainTab.h newtab.cpp newtab. - h leftArrowDisabled.xpm leftArrowEnabled.xpm rightArrowDisabled. - xpm rightArrowEnabled.xpm tabLeft.xpm tabMiddle.xpm tabRight.xpm tabClose. - xpm programcommand.cpp programcommand.h -####### kdevelop will overwrite this part!!! (end)############ -#set the include path for X, qt and KDE - INCLUDES = $ (all_includes) -#claim, which subdirectories you want to install -#you can add here more. This one gets installed - bin_PROGRAMS = qirc qirc_METASOURCES = USE_AUTOMOC -#the library search path. - qirc_LDFLAGS = $ (all_libraries) -#them while "make clean", use CLEANFILES - DISTCLEANFILES = $ (qirc_METASOURCES)