diff options
Diffstat (limited to 'libcommuni/src/model/ircbuffer.cpp')
| -rw-r--r-- | libcommuni/src/model/ircbuffer.cpp | 593 |
1 files changed, 593 insertions, 0 deletions
diff --git a/libcommuni/src/model/ircbuffer.cpp b/libcommuni/src/model/ircbuffer.cpp new file mode 100644 index 0000000..e7aa6b9 --- /dev/null +++ b/libcommuni/src/model/ircbuffer.cpp @@ -0,0 +1,593 @@ +/* + Copyright (C) 2008-2014 The Communi Project + + You may use this file under the terms of BSD license as follows: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "ircbuffer.h" +#include "ircbuffer_p.h" +#include "ircbuffermodel.h" +#include "ircbuffermodel_p.h" +#include "ircconnection.h" +#include "ircchannel.h" + +IRC_BEGIN_NAMESPACE + +/*! + \file ircbuffer.h + \brief \#include <IrcBuffer> + */ + +/*! + \class IrcBuffer ircbuffer.h <IrcBuffer> + \ingroup models + \brief Keeps track of buffer status. + + \sa IrcBufferModel +*/ + +/*! + \fn void IrcBuffer::messageReceived(IrcMessage* message) + + This signal is emitted when a buffer specific message is received. + + The message may one of the following types: + - IrcMessage::Join + - IrcMessage::Kick + - IrcMessage::Mode + - IrcMessage::Names + - IrcMessage::Nick + - IrcMessage::Notice + - IrcMessage::Numeric + - IrcMessage::Part + - IrcMessage::Private + - IrcMessage::Quit + - IrcMessage::Topic + + \sa IrcConnection::messageReceived(), IrcBufferModel::messageIgnored() + */ + +#ifndef IRC_DOXYGEN +IrcBufferPrivate::IrcBufferPrivate() + : q_ptr(0), model(0), persistent(false), sticky(false) +{ + qRegisterMetaType<IrcBuffer*>(); + qRegisterMetaType<QList<IrcBuffer*> >(); +} + +IrcBufferPrivate::~IrcBufferPrivate() +{ +} + +void IrcBufferPrivate::init(const QString& title, IrcBufferModel* m) +{ + name = title; + setModel(m); +} + +void IrcBufferPrivate::connected() +{ + Q_Q(IrcBuffer); + emit q->activeChanged(q->isActive()); +} + +void IrcBufferPrivate::disconnected() +{ + Q_Q(IrcBuffer); + emit q->activeChanged(q->isActive()); +} + +void IrcBufferPrivate::setName(const QString& value) +{ + Q_Q(IrcBuffer); + if (name != value) { + const QString oldTitle = q->title(); + name = value; + emit q->nameChanged(name); + emit q->titleChanged(q->title()); + if (model) + IrcBufferModelPrivate::get(model)->renameBuffer(oldTitle, q->title()); + } +} + +void IrcBufferPrivate::setPrefix(const QString& value) +{ + Q_Q(IrcBuffer); + if (prefix != value) { + const QString oldTitle = q->title(); + prefix = value; + emit q->prefixChanged(prefix); + emit q->titleChanged(q->title()); + if (model) + IrcBufferModelPrivate::get(model)->renameBuffer(oldTitle, q->title()); + } +} + +void IrcBufferPrivate::setModel(IrcBufferModel* value) +{ + model = value; +} + +bool IrcBufferPrivate::processMessage(IrcMessage* message) +{ + Q_Q(IrcBuffer); + bool processed = false; + switch (message->type()) { + case IrcMessage::Join: + processed = processJoinMessage(static_cast<IrcJoinMessage*>(message)); + break; + case IrcMessage::Kick: + processed = processKickMessage(static_cast<IrcKickMessage*>(message)); + break; + case IrcMessage::Mode: + processed = processModeMessage(static_cast<IrcModeMessage*>(message)); + break; + case IrcMessage::Names: + processed = processNamesMessage(static_cast<IrcNamesMessage*>(message)); + break; + case IrcMessage::Nick: + processed = processNickMessage(static_cast<IrcNickMessage*>(message)); + break; + case IrcMessage::Notice: + processed = processNoticeMessage(static_cast<IrcNoticeMessage*>(message)); + break; + case IrcMessage::Numeric: + processed = processNumericMessage(static_cast<IrcNumericMessage*>(message)); + break; + case IrcMessage::Part: + processed = processPartMessage(static_cast<IrcPartMessage*>(message)); + break; + case IrcMessage::Private: + processed = processPrivateMessage(static_cast<IrcPrivateMessage*>(message)); + break; + case IrcMessage::Quit: + processed = processQuitMessage(static_cast<IrcQuitMessage*>(message)); + break; + case IrcMessage::Topic: + processed = processTopicMessage(static_cast<IrcTopicMessage*>(message)); + break; + case IrcMessage::WhoReply: + processed = processWhoReplyMessage(static_cast<IrcWhoReplyMessage*>(message)); + break; + default: + break; + } + if (processed) + emit q->messageReceived(message); + return processed; +} + +bool IrcBufferPrivate::processJoinMessage(IrcJoinMessage* message) +{ + Q_UNUSED(message); + return false; +} + +bool IrcBufferPrivate::processKickMessage(IrcKickMessage* message) +{ + Q_UNUSED(message); + return false; +} + +bool IrcBufferPrivate::processModeMessage(IrcModeMessage* message) +{ + Q_UNUSED(message); + return false; +} + +bool IrcBufferPrivate::processNamesMessage(IrcNamesMessage* message) +{ + Q_UNUSED(message); + return false; +} + +bool IrcBufferPrivate::processNickMessage(IrcNickMessage* message) +{ + if (!(message->flags() & IrcMessage::Playback) && !message->nick().compare(name, Qt::CaseInsensitive)) { + setName(message->newNick()); + return true; + } + return !message->newNick().compare(name, Qt::CaseInsensitive); +} + +bool IrcBufferPrivate::processNoticeMessage(IrcNoticeMessage* message) +{ + Q_UNUSED(message); + return true; +} + +bool IrcBufferPrivate::processNumericMessage(IrcNumericMessage* message) +{ + Q_UNUSED(message); + return true; +} + +bool IrcBufferPrivate::processPartMessage(IrcPartMessage* message) +{ + Q_UNUSED(message); + return false; +} + +bool IrcBufferPrivate::processPrivateMessage(IrcPrivateMessage* message) +{ + Q_UNUSED(message); + return true; +} + +bool IrcBufferPrivate::processQuitMessage(IrcQuitMessage* message) +{ + return !message->nick().compare(name, Qt::CaseInsensitive); +} + +bool IrcBufferPrivate::processTopicMessage(IrcTopicMessage* message) +{ + Q_UNUSED(message); + return false; +} + +bool IrcBufferPrivate::processWhoReplyMessage(IrcWhoReplyMessage *message) +{ + Q_UNUSED(message); + return true; +} +#endif // IRC_DOXYGEN + +/*! + Constructs a new buffer object with \a parent. + */ +IrcBuffer::IrcBuffer(QObject* parent) + : QObject(parent), d_ptr(new IrcBufferPrivate) +{ + Q_D(IrcBuffer); + d->q_ptr = this; +} + +/*! + \internal + */ +IrcBuffer::IrcBuffer(IrcBufferPrivate& dd, QObject* parent) + : QObject(parent), d_ptr(&dd) +{ + Q_D(IrcBuffer); + d->q_ptr = this; +} + +/*! + Destructs the buffer object. + */ +IrcBuffer::~IrcBuffer() +{ + emit destroyed(this); +} + +/*! + This property holds the whole buffer title. + + The title consists of \ref prefix and \ref name. + + \par Access function: + \li QString <b>title</b>() const + + \par Notifier signal: + \li void <b>titleChanged</b>(const QString& title) + */ +QString IrcBuffer::title() const +{ + Q_D(const IrcBuffer); + return d->prefix + d->name; +} + +/*! + This property holds the name part of the buffer \ref title. + + \par Access functions: + \li QString <b>name</b>() const + \li void <b>setName</b>(const QString& name) [slot] + + \par Notifier signal: + \li void <b>nameChanged</b>(const QString& name) + */ +QString IrcBuffer::name() const +{ + Q_D(const IrcBuffer); + return d->name; +} + +void IrcBuffer::setName(const QString& name) +{ + Q_D(IrcBuffer); + d->setName(name); +} + +/*! + This property holds the prefix part of the buffer \ref title. + + \par Access functions: + \li QString <b>prefix</b>() const + \li void <b>setPrefix</b>(const QString& prefix) [slot] + + \par Notifier signal: + \li void <b>prefixChanged</b>(const QString& prefix) + */ +QString IrcBuffer::prefix() const +{ + Q_D(const IrcBuffer); + return d->prefix; +} + +void IrcBuffer::setPrefix(const QString& prefix) +{ + Q_D(IrcBuffer); + return d->setPrefix(prefix); +} + +/*! + \property bool IrcBuffer::channel + This property holds whether the buffer is a channel. + + \par Access function: + \li bool <b>isChannel</b>() const + + \sa toChannel() + */ +bool IrcBuffer::isChannel() const +{ + return qobject_cast<const IrcChannel*>(this); +} + +/*! + Returns the buffer cast to a IrcChannel, + if the class is actually a channel, \c 0 otherwise. + + \sa \ref channel "isChannel()" +*/ +IrcChannel* IrcBuffer::toChannel() +{ + return qobject_cast<IrcChannel*>(this); +} + +/*! + This property holds the connection of the buffer. + + \par Access function: + \li \ref IrcConnection* <b>connection</b>() const + */ +IrcConnection* IrcBuffer::connection() const +{ + Q_D(const IrcBuffer); + return d->model ? d->model->connection() : 0; +} + +/*! + This property holds the network of the buffer. + + \par Access function: + \li \ref IrcNetwork* <b>network</b>() const + */ +IrcNetwork* IrcBuffer::network() const +{ + Q_D(const IrcBuffer); + return d->model ? d->model->network() : 0; +} + +/*! + This property holds the model of the buffer. + + \par Access function: + \li \ref IrcBufferModel* <b>model</b>() const + */ +IrcBufferModel* IrcBuffer::model() const +{ + Q_D(const IrcBuffer); + return d->model; +} + +/*! + \property bool IrcBuffer::active + This property holds whether the buffer is active. + + A buffer is considered active when a %connection is established. Furthermore, + channel buffers are only considered active when the user is on the channel. + + \par Access function: + \li bool <b>isActive</b>() const + + \par Notifier signal: + \li void <b>activeChanged</b>(bool active) + + \sa IrcConnection::connected + */ +bool IrcBuffer::isActive() const +{ + if (IrcConnection* c = connection()) + return c->isConnected(); + return false; +} + +/*! + \property bool IrcBuffer::sticky + This property holds whether the buffer is sticky. + + A sticky buffer stays in the beginning (Qt::AscendingOrder) or + end (Qt::DescendingOrder) of the list of buffers in IrcBufferModel. + + The default value is \c false. + + \par Access functions: + \li bool <b>isSticky</b>() const + \li void <b>setSticky</b>(bool sticky) + + \par Notifier signal: + \li void <b>stickyChanged</b>(bool sticky) + */ + +bool IrcBuffer::isSticky() const +{ + Q_D(const IrcBuffer); + return d->sticky; +} + +void IrcBuffer::setSticky(bool sticky) +{ + Q_D(IrcBuffer); + if (d->sticky != sticky) { + d->sticky = sticky; + emit stickyChanged(sticky); + } +} + +/*! + \property bool IrcBuffer::persistent + This property holds whether the buffer is persistent. + + The default value is \c false. + + A persistent buffer does not get removed and destructed + when calling IrcBufferModel::clear(), or when when leaving + the corresponding channel. In order to remove a persistent + buffer, either explicitly call IrcBufferModel::remove() or + delete the buffer. + + \par Access functions: + \li bool <b>isPersistent</b>() const + \li void <b>setPersistent</b>(bool persistent) + + \par Notifier signal: + \li void <b>persistentChanged</b>(bool persistent) + */ + +bool IrcBuffer::isPersistent() const +{ + Q_D(const IrcBuffer); + return d->persistent; +} + +void IrcBuffer::setPersistent(bool persistent) +{ + Q_D(IrcBuffer); + if (d->persistent != persistent) { + d->persistent = persistent; + emit persistentChanged(persistent); + } +} + +/*! + \since 3.1 + + This property holds arbitrary user data. + + \par Access functions: + \li QVariantMap <b>userData</b>() const + \li void <b>setUserData</b>(const QVariantMap& data) + + \par Notifier signal: + \li void <b>userDataChanged</b>(const QVariantMap& data) + */ +QVariantMap IrcBuffer::userData() const +{ + Q_D(const IrcBuffer); + return d->userData; +} + +void IrcBuffer::setUserData(const QVariantMap& data) +{ + Q_D(IrcBuffer); + if (d->userData != data) { + d->userData = data; + emit userDataChanged(data); + } +} + +/*! + Sends a \a command to the server. + + This method is provided for convenience. It is equal to: + \code + IrcConnection* connection = buffer->connection(); + connection->sendCommand(command); + \endcode + + \sa IrcConnection::sendCommand() + */ +bool IrcBuffer::sendCommand(IrcCommand* command) +{ + if (IrcConnection* c = connection()) + return c->sendCommand(command); + return false; +} + +/*! + Emits messageReceived() with \a message. + + IrcBufferModel handles only buffer specific messages and delivers them + to the appropriate IrcBuffer instances. When applications decide to handle + IrcBuffer::messageReceived(), IrcBufferModel::messageIgnored() makes it + easy to implement handling for the rest, non-buffer specific messages. + This method can be used to forward such ignored messages to the desired + buffers (for instance the one that is currently active in the GUI). + */ +void IrcBuffer::receiveMessage(IrcMessage* message) +{ + if (message) + emit messageReceived(message); +} + +/*! + \since 3.1 + + Closes the buffer with an optional \a reason. + + The default implementation removes the buffer from its \ref model. + Furthermore, IrcChannel parts the channel with \a reason and custom + IrcBuffer subclasses might do some additional tasks. + + \sa IrcChannel::close() + */ +void IrcBuffer::close(const QString& reason) +{ + Q_UNUSED(reason); + Q_D(const IrcBuffer); + if (d->model) + d->model->remove(this); +} + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug debug, const IrcBuffer* buffer) +{ + if (!buffer) + return debug << "IrcBuffer(0x0) "; + debug.nospace() << buffer->metaObject()->className() << '(' << (void*) buffer; + if (!buffer->objectName().isEmpty()) + debug.nospace() << ", name=" << qPrintable(buffer->objectName()); + if (!buffer->title().isEmpty()) + debug.nospace() << ", title=" << qPrintable(buffer->title()); + debug.nospace() << ')'; + return debug.space(); +} +#endif // QT_NO_DEBUG_STREAM + +#include "moc_ircbuffer.cpp" + +IRC_END_NAMESPACE |
