This repository has been archived on 2025-12-24. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
yachat/src/psievent.cpp

1515 lines
28 KiB
C++
Raw Normal View History

2025-12-25 01:37:49 +05:00
/*
* psievent.h - events
* Copyright (C) 2001, 2002 Justin Karneges
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "psievent.h"
#include <qdom.h>
#include <QTextStream>
#include <QList>
#include <QCoreApplication>
#include "psicon.h"
#include "psiaccount.h"
#include "xmpp_xmlcommon.h"
#include "dummystream.h"
#include "filetransfer.h"
#include "applicationinfo.h"
#include "psicontactlist.h"
#include "atomicxmlfile.h"
#include "globaleventqueue.h"
#ifdef YAPSI
#include "yacommon.h"
#include "psioptions.h"
#endif
using namespace XMPP;
using namespace XMLHelper;
//----------------------------------------------------------------------------
// PsiEvent
//----------------------------------------------------------------------------
PsiEvent::PsiEvent(PsiAccount *acc)
{
v_originLocal = false;
v_late = false;
v_account = acc;
#ifdef YAPSI_ACTIVEX_SERVER
v_shownInOnline = false;
#endif
#ifdef YAPSI
v_id = -1;
#endif
}
PsiEvent::PsiEvent(const PsiEvent &from)
: QObject()
{
v_originLocal = from.v_originLocal;
v_late = from.v_late;
v_ts = from.v_ts;
v_jid = from.v_jid;
v_account = from.v_account;
#ifdef YAPSI_ACTIVEX_SERVER
v_shownInOnline = from.v_shownInOnline;
#endif
#ifdef YAPSI
v_id = from.v_id;
#endif
}
PsiEvent::~PsiEvent()
{
}
XMPP::Jid PsiEvent::jid() const
{
return v_jid;
}
void PsiEvent::setJid(const XMPP::Jid &j)
{
v_jid = j;
}
PsiAccount *PsiEvent::account() const
{
return v_account;
}
void PsiEvent::setAccount(PsiAccount* account)
{
v_account = account;
}
bool PsiEvent::originLocal() const
{
return v_originLocal;
}
bool PsiEvent::late() const
{
return v_late;
}
QDateTime PsiEvent::timeStamp() const
{
return v_ts;
}
void PsiEvent::setOriginLocal(bool b)
{
v_originLocal = b;
}
void PsiEvent::setLate(bool b)
{
v_late = b;
}
void PsiEvent::setTimeStamp(const QDateTime &t)
{
v_ts = t;
}
bool PsiEvent::saveable() const
{
return true;
}
QDomElement PsiEvent::toXml(QDomDocument *doc) const
{
QDomElement e = doc->createElement("event");
e.setAttribute("type", className());
#ifdef YAPSI_ACTIVEX_SERVER
e.setAttribute("shownInOnline", v_shownInOnline ? "true" : "false");
#endif
#ifdef YAPSI
e.setAttribute("id", QString::number(v_id));
#endif
e.appendChild( textTag(*doc, "originLocal", v_originLocal) );
e.appendChild( textTag(*doc, "late", v_late) );
e.appendChild( textTag(*doc, "ts", v_ts.toString( Qt::ISODate )) );
if ( !v_jid.full().isEmpty() )
e.appendChild( textTag(*doc, "jid", v_jid.full()) );
if ( v_account )
e.appendChild( textTag(*doc, "account", v_account->name()) );
return e;
}
bool PsiEvent::fromXml(PsiCon *psi, PsiAccount *account, const QDomElement *e)
{
if ( e->tagName() != "event" )
return false;
if ( e->attribute("type") != className() )
return false;
#ifdef YAPSI_ACTIVEX_SERVER
v_shownInOnline = e->attribute("shownInOnline") == "true";
#endif
#ifdef YAPSI
v_id = e->attribute("id").toInt();
#endif
readBoolEntry(*e, "originLocal", &v_originLocal);
readBoolEntry(*e, "late", &v_late);
v_ts = QDateTime::fromString(subTagText(*e, "ts"), Qt::ISODate);
v_jid = Jid( subTagText(*e, "jid") );
if ( account ) {
v_account = account;
}
else if ( hasSubTag(*e, "account") ) {
QString accName = subTagText(*e, "account");
foreach(PsiAccount* account, psi->contactList()->accounts()) {
if ( account->name() == accName ) {
v_account = account;
break;
}
}
}
return true;
}
int PsiEvent::priority() const
{
return Options::EventPriorityDontCare;
}
QString PsiEvent::description() const
{
return QString();
}
PsiEvent *PsiEvent::copy() const
{
return 0;
}
#ifdef YAPSI_ACTIVEX_SERVER
bool PsiEvent::shownInOnline() const
{
return v_shownInOnline;
}
void PsiEvent::setShownInOnline(bool shownInOnline)
{
v_shownInOnline = shownInOnline;
}
#endif
#ifdef YAPSI
int PsiEvent::id() const
{
return v_id;
}
void PsiEvent::setId(int id)
{
v_id = id;
}
#endif
//----------------------------------------------------------------------------
// MessageEvent
//----------------------------------------------------------------------------
MessageEvent::MessageEvent(PsiAccount *acc)
: PsiEvent(acc)
{
v_sentToChatWindow = false;
#ifdef YAPSI
multiContactCount_ = 1;
#endif
}
MessageEvent::MessageEvent(const XMPP::Message &m, PsiAccount *acc)
: PsiEvent(acc)
{
v_sentToChatWindow = false;
setMessage(m);
#ifdef YAPSI
multiContactCount_ = 1;
#endif
}
MessageEvent::MessageEvent(const MessageEvent &from)
: PsiEvent(from), v_m(from.v_m), v_sentToChatWindow(from.v_sentToChatWindow)
{
#ifdef YAPSI
multiContactCount_ = 1;
#endif
}
MessageEvent::~MessageEvent()
{
}
int MessageEvent::type() const
{
return Message;
}
Jid MessageEvent::from() const
{
return v_m.from();
}
void MessageEvent::setFrom(const Jid &j)
{
v_m.setFrom(j);
}
const QString& MessageEvent::nick() const
{
return v_m.nick();
}
void MessageEvent::setNick(const QString &nick)
{
v_m.setNick(nick);
}
bool MessageEvent::sentToChatWindow() const
{
return v_sentToChatWindow;
}
const XMPP::Message & MessageEvent::message() const
{
return v_m;
}
void MessageEvent::setSentToChatWindow(bool b)
{
v_sentToChatWindow = b;
}
void MessageEvent::setMessage(const XMPP::Message &m)
{
v_m = m;
setTimeStamp ( v_m.timeStamp() );
setLate ( v_m.spooled() );
}
QDomElement MessageEvent::toXml(QDomDocument *doc) const
{
QDomElement e = PsiEvent::toXml(doc);
DummyStream stream;
Stanza s = v_m.toStanza(&stream);
e.appendChild( s.element() );
return e;
}
bool MessageEvent::fromXml(PsiCon *psi, PsiAccount *account, const QDomElement *e)
{
if ( !PsiEvent::fromXml(psi, account, e) )
return false;
bool found = false;
QDomElement msg = findSubTag(*e, "message", &found);
if ( found ) {
DummyStream stream;
Stanza s = stream.createStanza(addCorrectNS(msg));
v_m.fromStanza(s, 0); // FIXME: fix tzoffset?
// if message was not spooled, it will be initialized with the
// current datetime. we want to reset it back to the original
// receive time
if (!v_m.timeStamp().secsTo(QDateTime::currentDateTime()))
v_m.setTimeStamp(timeStamp());
return true;
}
return false;
}
int MessageEvent::priority() const
{
if ( v_m.type() == "headline" )
return option.eventPriorityHeadline;
else if ( v_m.type() == "chat" )
return option.eventPriorityChat;
return option.eventPriorityMessage;
}
#ifdef YAPSI
void MessageEvent::setMultiContactCount(int count)
{
multiContactCount_ = count;
}
int MessageEvent::multiContactCount() const
{
return multiContactCount_;
}
#endif
bool MessageEvent::isForcedDescription() const
{
return !forcedDescription_.isEmpty();
}
void MessageEvent::setForcedDescription(const QString& description)
{
forcedDescription_ = description;
}
QString MessageEvent::description() const
{
if (!forcedDescription_.isEmpty())
return forcedDescription_;
QStringList result;
if (!v_m.subject().isEmpty())
result << v_m.subject();
if (!v_m.body().isEmpty())
result << v_m.body();
foreach(Url url, v_m.urlList()) {
QString text = url.url();
if (!url.desc().isEmpty())
text += QString("(%1)").arg(url.desc());
result << text;
}
return result.join("\n");
}
PsiEvent *MessageEvent::copy() const
{
return new MessageEvent( *this );
}
//----------------------------------------------------------------------------
// AuthEvent
//----------------------------------------------------------------------------
AuthEvent::AuthEvent(const Jid &j, const QString &authType, PsiAccount *acc)
: PsiEvent(acc)
{
v_from = j;
v_at = authType;
}
AuthEvent::AuthEvent(const AuthEvent &from)
: PsiEvent(from), v_from(from.v_from), v_at(from.v_at)
{
}
AuthEvent::~AuthEvent()
{
}
int AuthEvent::type() const
{
return Auth;
}
Jid AuthEvent::from() const
{
return v_from;
}
void AuthEvent::setFrom(const Jid &j)
{
v_from = j;
}
const QString& AuthEvent::nick() const
{
return v_nick;
}
void AuthEvent::setNick(const QString &nick)
{
v_nick = nick;
}
QString AuthEvent::authType() const
{
return v_at;
}
bool AuthEvent::saveable() const
{
return false;
}
QDomElement AuthEvent::toXml(QDomDocument *doc) const
{
QDomElement e = PsiEvent::toXml(doc);
e.appendChild( textTag(*doc, "from", v_from.full()) );
e.appendChild( textTag(*doc, "authType", v_at) );
e.appendChild( textTag(*doc, "nick", v_nick) );
return e;
}
bool AuthEvent::fromXml(PsiCon *psi, PsiAccount *account, const QDomElement *e)
{
if ( !PsiEvent::fromXml(psi, account, e) )
return false;
v_from = Jid( subTagText(*e, "from") );
v_at = subTagText(*e, "authType");
v_nick = subTagText(*e, "nick");
return true;
}
int AuthEvent::priority() const
{
return option.eventPriorityAuth;
}
QString AuthEvent::description() const
{
QString jid = from().bare();
#ifdef YAPSI
if (account()) {
jid = Ya::humanReadableJid(account()->psi(), jid);
}
#endif
QString result;
if (authType() == "subscribe")
result = tr("%1 wants to subscribe to your presence.").arg(jid);
else if (authType() == "subscribed")
result = tr("%1 authorized you to view his status.").arg(jid);
else if (authType() == "unsubscribed" || authType() == "unsubscribe")
result = tr("%1 removed your authorization to view his status!").arg(jid);
else
Q_ASSERT(false);
return result;
}
PsiEvent *AuthEvent::copy() const
{
return new AuthEvent( *this );
}
#ifdef YAPSI
//----------------------------------------------------------------------------
// MoodEvent
//----------------------------------------------------------------------------
MoodEvent::MoodEvent(const XMPP::Jid& j, const QString& mood, PsiAccount* acc)
: PsiEvent(acc)
, v_mood(mood)
{
setTimeStamp(QDateTime::currentDateTime());
setJid(j);
}
MoodEvent::MoodEvent(const MoodEvent& from)
: PsiEvent(from)
, v_mood(from.v_mood)
{
}
MoodEvent::~MoodEvent()
{
}
int MoodEvent::type() const
{
return Mood;
}
XMPP::Jid MoodEvent::from() const
{
return jid();
}
void MoodEvent::setFrom(const XMPP::Jid &j)
{
setJid(j);
}
const QString& MoodEvent::mood() const
{
return v_mood;
}
void MoodEvent::setMood(const QString& mood)
{
v_mood = mood;
}
bool MoodEvent::saveable() const
{
return false;
}
QDomElement MoodEvent::toXml(QDomDocument* doc) const
{
QDomElement e = PsiEvent::toXml(doc);
e.appendChild(textTag(*doc, "mood", v_mood));
return e;
}
bool MoodEvent::fromXml(PsiCon* psi, PsiAccount* account, const QDomElement* e)
{
if (!PsiEvent::fromXml(psi, account, e))
return false;
v_mood = subTagText(*e, "mood");
return true;
}
int MoodEvent::priority() const
{
return 0;
}
QString MoodEvent::description() const
{
return tr("%1 changed mood to: %2").arg(from().bare()).arg(mood());
}
PsiEvent *MoodEvent::copy() const
{
return new MoodEvent(*this);
}
//----------------------------------------------------------------------------
// GroupchatInviteEvent
//----------------------------------------------------------------------------
GroupchatInviteEvent::GroupchatInviteEvent(const XMPP::Jid& j, const XMPP::Jid& groupchat, const QString& reason, const QString& password, PsiAccount* acc)
: PsiEvent(acc)
, v_password(password)
, v_groupchat(groupchat)
, v_reason(reason)
{
setTimeStamp(QDateTime::currentDateTime());
setJid(j);
}
GroupchatInviteEvent::GroupchatInviteEvent(const GroupchatInviteEvent& from)
: PsiEvent(from)
{
}
GroupchatInviteEvent::~GroupchatInviteEvent()
{
}
int GroupchatInviteEvent::type() const
{
return GroupchatInvite;
}
XMPP::Jid GroupchatInviteEvent::from() const
{
return jid();
}
void GroupchatInviteEvent::setFrom(const XMPP::Jid &j)
{
setJid(j);
}
XMPP::Jid GroupchatInviteEvent::groupchat() const
{
return v_groupchat;
}
void GroupchatInviteEvent::setGroupchat(const XMPP::Jid &j)
{
v_groupchat = j;
}
const QString& GroupchatInviteEvent::reason() const
{
return v_reason;
}
void GroupchatInviteEvent::setReason(const QString& r)
{
v_reason = r;
}
const QString& GroupchatInviteEvent::password() const
{
return v_password;
}
void GroupchatInviteEvent::setPassword(const QString& password)
{
v_password = password;
}
QDomElement GroupchatInviteEvent::toXml(QDomDocument* doc) const
{
QDomElement e = PsiEvent::toXml(doc);
e.appendChild(textTag(*doc, "password", v_password));
e.appendChild(textTag(*doc, "groupchat", v_groupchat.full()));
e.appendChild(textTag(*doc, "reason", v_reason));
return e;
}
bool GroupchatInviteEvent::fromXml(PsiCon* psi, PsiAccount* account, const QDomElement* e)
{
if (!PsiEvent::fromXml(psi, account, e))
return false;
v_password = subTagText(*e, "password");
v_groupchat = Jid(subTagText(*e, "groupchat"));
v_reason = subTagText(*e, "reason");
return true;
}
int GroupchatInviteEvent::priority() const
{
return 0;
}
QString GroupchatInviteEvent::description() const
{
return tr("%1 invited you to %2")
.arg(from().bare())
.arg(groupchat().bare());
}
PsiEvent *GroupchatInviteEvent::copy() const
{
return new GroupchatInviteEvent(*this);
}
//----------------------------------------------------------------------------
// GroupchatAlertEvent
//----------------------------------------------------------------------------
GroupchatAlertEvent::GroupchatAlertEvent(const XMPP::Jid& j, const QString& message, PsiAccount* acc)
: PsiEvent(acc)
, v_message(message)
{
setTimeStamp(QDateTime::currentDateTime());
XMPP::Jid jid(j);
setJid(jid);
}
GroupchatAlertEvent::GroupchatAlertEvent(const GroupchatAlertEvent& from)
: PsiEvent(from)
{
}
GroupchatAlertEvent::~GroupchatAlertEvent()
{
}
int GroupchatAlertEvent::type() const
{
return GroupchatAlert;
}
XMPP::Jid GroupchatAlertEvent::from() const
{
return jid();
}
void GroupchatAlertEvent::setFrom(const XMPP::Jid &j)
{
setJid(j);
}
const QString& GroupchatAlertEvent::message() const
{
return v_message;
}
void GroupchatAlertEvent::setMessage(const QString& message)
{
v_message = message;
}
QDomElement GroupchatAlertEvent::toXml(QDomDocument* doc) const
{
QDomElement e = PsiEvent::toXml(doc);
e.appendChild(textTag(*doc, "message", v_message));
return e;
}
bool GroupchatAlertEvent::fromXml(PsiCon* psi, PsiAccount* account, const QDomElement* e)
{
if (!PsiEvent::fromXml(psi, account, e))
return false;
v_message = subTagText(*e, "message");
return true;
}
int GroupchatAlertEvent::priority() const
{
return 0;
}
QString GroupchatAlertEvent::description() const
{
return tr("%1 (%2): %3")
.arg(from().resource())
.arg(from().bare())
.arg(v_message);
}
PsiEvent *GroupchatAlertEvent::copy() const
{
return new GroupchatAlertEvent(*this);
}
#endif
//----------------------------------------------------------------------------
// FileEvent
//----------------------------------------------------------------------------
FileEvent::FileEvent(const Jid &j, FileTransfer *_ft, PsiAccount *acc)
:PsiEvent(acc)
{
v_from = j;
ft = _ft;
}
FileEvent::~FileEvent()
{
delete ft;
}
FileEvent::FileEvent(const FileEvent &from)
: PsiEvent(from.account())
{
v_from = from.v_from;
ft = from.ft->copy();
}
int FileEvent::priority() const
{
return option.eventPriorityFile;
}
Jid FileEvent::from() const
{
return v_from;
}
void FileEvent::setFrom(const Jid &j)
{
v_from = j;
}
FileTransfer *FileEvent::takeFileTransfer()
{
FileTransfer *_ft = ft;
ft = 0;
return _ft;
}
QString FileEvent::description() const
{
return tr("This user wants to send you a file.");
}
PsiEvent *FileEvent::copy() const
{
return new FileEvent( *this );
}
//----------------------------------------------------------------------------
// HttpAuthEvent
//----------------------------------------------------------------------------
HttpAuthEvent::HttpAuthEvent(const PsiHttpAuthRequest &req, PsiAccount *acc)
:MessageEvent(acc), v_req(req)
{
const XMPP::Stanza &s = req.stanza();
XMPP::Message m;
if ( s.kind() == XMPP::Stanza::Message ) {
m.fromStanza(s, acc->client()->timeZoneOffset());
}
else {
m.setFrom(s.from());
m.setTimeStamp(QDateTime::currentDateTime());
m.setHttpAuthRequest(HttpAuthRequest(s.element().elementsByTagNameNS("http://jabber.org/protocol/http-auth", "confirm").item(0).toElement()));
}
setMessage(m);
}
HttpAuthEvent::~HttpAuthEvent()
{
}
QString HttpAuthEvent::description() const
{
return tr("HTTP Authentication Request");
}
//----------------------------------------------------------------------------
// RosterExchangeEvent
//----------------------------------------------------------------------------
RosterExchangeEvent::RosterExchangeEvent(const Jid &j, const RosterExchangeItems& i, const QString& text, PsiAccount *acc)
:PsiEvent(acc)
{
v_from = j;
v_items = i;
v_text = text;
}
int RosterExchangeEvent::priority() const
{
return option.eventPriorityRosterExchange;
}
Jid RosterExchangeEvent::from() const
{
return v_from;
}
void RosterExchangeEvent::setFrom(const Jid &j)
{
v_from = j;
}
const RosterExchangeItems& RosterExchangeEvent::rosterExchangeItems() const
{
return v_items;
}
void RosterExchangeEvent::setRosterExchangeItems(const RosterExchangeItems& i)
{
v_items = i;
}
const QString& RosterExchangeEvent::text() const
{
return v_text;
}
void RosterExchangeEvent::setText(const QString& text)
{
v_text = text;
}
QString RosterExchangeEvent::description() const
{
return tr("This user wants to modify your roster.");
}
//----------------------------------------------------------------------------
// Status
//----------------------------------------------------------------------------
/*StatusEvent::StatusEvent(const Jid &j, const XMPP::Status& s, PsiAccount *acc)
:PsiEvent(acc)
{
v_from = j;
v_status = s;
}
int StatusEvent::priority() const
{
return option.eventPriorityChat;
}
Jid StatusEvent::from() const
{
return v_from;
}
void StatusEvent::setFrom(const Jid &j)
{
v_from = j;
}
const XMPP::Status& StatusEvent::status() const
{
return v_status;
}
void StatusEvent::setStatus(const XMPP::Status& s)
{
v_status = s;
}*/
//----------------------------------------------------------------------------
// EventIdGenerator
//----------------------------------------------------------------------------
class EventIdGenerator : public QObject
{
Q_OBJECT
public:
static EventIdGenerator* instance();
int getId();
private:
static EventIdGenerator* instance_;
int id_;
EventIdGenerator();
};
EventIdGenerator* EventIdGenerator::instance_ = 0;
EventIdGenerator* EventIdGenerator::instance()
{
if (!instance_) {
instance_ = new EventIdGenerator();
}
return instance_;
}
static const QString idGeneratorOptionPath = "options.ya.last-event-id";
EventIdGenerator::EventIdGenerator()
: QObject(QCoreApplication::instance())
{
#ifdef YAPSI
id_ = PsiOptions::instance()->getOption(idGeneratorOptionPath).toInt();
#else
id_ = 0;
#endif
}
int EventIdGenerator::getId()
{
int result = id_;
#ifdef YAPSI
// TODO: upgrade to uint64
while(GlobalEventQueue::instance()->ids().contains(result)) {
qWarning("Generated id already in GlobalEventQueue: %d", result);
++result;
}
id_ = result + 1;
PsiOptions::instance()->setOption(idGeneratorOptionPath, id_);
#else
++id_;
#endif
if (id_ > 0x7FFFFFFF) {
id_ = 0;
}
Q_ASSERT(id_ >= 0);
Q_ASSERT(result >= 0);
return result;
}
//----------------------------------------------------------------------------
// EventItem
//----------------------------------------------------------------------------
EventItem::EventItem(PsiEvent *_e)
{
e = _e;
#ifdef YAPSI
if (e->id() >= 0) {
v_id = e->id();
}
else {
Q_ASSERT(e->account());
v_id = EventIdGenerator::instance()->getId();
e->setId(v_id);
}
#else
Q_ASSERT(e->account());
v_id = EventIdGenerator::instance()->getId();
#endif
}
EventItem::EventItem(const EventItem &from)
{
e = from.e->copy();
v_id = from.v_id;
}
EventItem::~EventItem()
{
}
int EventItem::id() const
{
return v_id;
}
PsiEvent* EventItem::event() const
{
return e;
}
//----------------------------------------------------------------------------
// EventQueue
//----------------------------------------------------------------------------
EventQueue::EventQueue(PsiAccount *account)
: psi_(0)
, account_(0)
, enabled_(false)
{
account_ = account;
psi_ = account_->psi();
}
EventQueue::~EventQueue()
{
setEnabled(false);
}
bool EventQueue::enabled() const
{
return enabled_;
}
void EventQueue::setEnabled(bool enabled)
{
if (enabled_ != enabled) {
enabled_ = enabled;
foreach(EventItem* i, list_) {
if (enabled)
GlobalEventQueue::instance()->enqueue(i);
else
GlobalEventQueue::instance()->dequeue(i);
}
}
}
#if 0
EventQueue &EventQueue::operator= (const EventQueue &from)
{
while(!list_.isEmpty())
delete list_.takeFirst();
psi_ = from.psi_;
account_ = from.account_;
foreach(EventItem *i, from.list_) {
PsiEvent *e = i->event();
enqueue( e->copy() );
}
return *this;
}
#endif
int EventQueue::nextId() const
{
if (list_.isEmpty())
return -1;
EventItem *i = list_.first();
if(!i)
return -1;
return i->id();
}
int EventQueue::count() const
{
return list_.count();
}
int EventQueue::count(const Jid &j, bool compareRes) const
{
int total = 0;
foreach(EventItem *i, list_) {
Jid j2(i->event()->jid());
if(j.compare(j2, compareRes))
++total;
}
return total;
}
void EventQueue::enqueue(PsiEvent *e)
{
EventItem *i = new EventItem(e);
if (enabled_) {
GlobalEventQueue::instance()->enqueue(i);
}
int prior = e->priority();
bool found = false;
// skip all with higher or equal priority
foreach(EventItem *ei, list_) {
if (ei && ei->event()->priority() < prior ) {
list_.insert(list_.find(ei), i);
found = true;
break;
}
}
// everything else
if ( !found )
list_.append(i);
emit queueChanged();
}
void EventQueue::dequeue(PsiEvent *e)
{
if ( !e )
return;
foreach(EventItem *i, list_) {
if ( e == i->event() ) {
if (enabled_) {
GlobalEventQueue::instance()->dequeue(i);
}
list_.remove(i);
emit queueChanged();
delete i;
return;
}
}
}
PsiEvent *EventQueue::dequeue(const Jid &j, bool compareRes)
{
foreach(EventItem *i, list_) {
PsiEvent *e = i->event();
Jid j2(e->jid());
if(j.compare(j2, compareRes)) {
if (enabled_) {
GlobalEventQueue::instance()->dequeue(i);
}
list_.remove(i);
emit queueChanged();
delete i;
return e;
}
}
return 0;
}
PsiEvent *EventQueue::peek(const Jid &j, bool compareRes) const
{
foreach(EventItem *i, list_) {
PsiEvent *e = i->event();
Jid j2(e->jid());
if(j.compare(j2, compareRes)) {
return e;
}
}
return 0;
}
PsiEvent *EventQueue::dequeueNext()
{
if (list_.isEmpty())
return 0;
EventItem *i = list_.first();
if(!i)
return 0;
PsiEvent *e = i->event();
if (enabled_) {
GlobalEventQueue::instance()->dequeue(i);
}
list_.remove(i);
emit queueChanged();
delete i;
return e;
}
PsiEvent *EventQueue::peekNext() const
{
if (list_.isEmpty())
return 0;
EventItem *i = list_.first();
if(!i)
return 0;
return i->event();
}
PsiEvent *EventQueue::peekFirstChat(const Jid &j, bool compareRes) const
{
foreach(EventItem *i, list_) {
PsiEvent *e = i->event();
if(e->type() == PsiEvent::Message) {
MessageEvent *me = (MessageEvent *)e;
if(j.compare(me->from(), compareRes) && me->message().type() == "chat")
return e;
}
}
return 0;
}
bool EventQueue::hasChats(const Jid &j, bool compareRes) const
{
return (peekFirstChat(j, compareRes) ? true: false);
}
// this function extracts all chats from the queue, and returns a list of queue positions
void EventQueue::extractChats(QList<PsiEvent*> *el, const Jid &j, bool compareRes, bool removeEvents)
{
bool changed = false;
for(QList<EventItem*>::Iterator it = list_.begin(); it != list_.end();) {
PsiEvent *e = (*it)->event();
bool extract = false;
if(e->type() == PsiEvent::Message) {
MessageEvent *me = (MessageEvent *)e;
if(j.compare(me->from(), compareRes) && me->message().type() == "chat") { // FIXME: refactor-refactor-refactor
extract = true;
}
}
#ifdef YAPSI
else if (e->type() == PsiEvent::Mood) {
MoodEvent* moodEvent = static_cast<MoodEvent*>(e);
if(j.compare(moodEvent->from(), false)) {
extract = true;
}
}
#endif
if (extract) {
el->append(e);
}
if (extract && removeEvents) {
EventItem* ei = *it;
if (enabled_) {
GlobalEventQueue::instance()->dequeue(ei);
}
it = list_.erase(it);
delete ei;
changed = true;
continue;
}
++it;
}
if ( changed )
emit queueChanged();
}
// this function extracts all messages from the queue, and returns a list of them
void EventQueue::extractMessages(QList<PsiEvent*> *el)
{
bool changed = false;
for(QList<EventItem*>::Iterator it = list_.begin(); it != list_.end();) {
PsiEvent *e = (*it)->event();
if(e->type() == PsiEvent::Message) {
el->append(e);
EventItem* ei = *it;
if (enabled_) {
GlobalEventQueue::instance()->dequeue(ei);
}
it = list_.erase(it);
delete ei;
changed = true;
continue;
}
++it;
}
if ( changed )
emit queueChanged();
}
void EventQueue::printContent() const
{
foreach(EventItem *i, list_) {
PsiEvent *e = i->event();
printf(" %d: (%d) from=[%s] jid=[%s]\n", i->id(), e->type(), qPrintable(e->from().full()), qPrintable(e->jid().full()));
}
}
void EventQueue::clear()
{
while(!list_.isEmpty())
delete list_.takeFirst();
emit queueChanged();
}
// this function removes all events associated with the input jid
void EventQueue::clear(const Jid &j, bool compareRes)
{
bool changed = false;
for(QList<EventItem*>::Iterator it = list_.begin(); it != list_.end();) {
PsiEvent *e = (*it)->event();
Jid j2(e->jid());
if(j.compare(j2, compareRes)) {
EventItem* ei = *it;
if (enabled_) {
GlobalEventQueue::instance()->dequeue(ei);
}
it = list_.erase(it);
delete ei;
changed = true;
}
else
++it;
}
if ( changed )
emit queueChanged();
}
QDomElement EventQueue::toXml(QDomDocument *doc) const
{
QDomElement e = doc->createElement("eventQueue");
e.setAttribute("version", "1.0");
e.appendChild(textTag(doc, "progver", ApplicationInfo::version()));
foreach(EventItem *i, list_) {
if (!i->event()->saveable())
continue;
QDomElement event = i->event()->toXml(doc);
e.appendChild( event );
}
return e;
}
bool EventQueue::fromXml(const QDomElement *q)
{
if ( !q )
return false;
if ( q->tagName() != "eventQueue" )
return false;
if ( q->attribute("version") != "1.0" )
return false;
QString progver = subTagText(*q, "progver");
for(QDomNode n = q->firstChild(); !n.isNull(); n = n.nextSibling()) {
QDomElement e = n.toElement();
if( e.isNull() )
continue;
if ( e.tagName() != "event" )
continue;
PsiEvent *event = 0;
QString eventType = e.attribute("type");
if ( eventType == "MessageEvent" ) {
event = new MessageEvent(0);
if ( !event->fromXml(psi_, account_, &e) ) {
delete event;
event = 0;
}
}
else if ( eventType == "AuthEvent" ) {
event = new AuthEvent("", "", 0);
if ( !event->fromXml(psi_, account_, &e) ) {
delete event;
event = 0;
}
}
#ifdef YAPSI
else if ( eventType == "MoodEvent" ) {
event = new MoodEvent("", "", 0);
if ( !event->fromXml(psi_, account_, &e) ) {
delete event;
event = 0;
}
}
else if ( eventType == "GroupchatInviteEvent" ) {
event = new GroupchatInviteEvent("", "", "", "", 0);
if ( !event->fromXml(psi_, account_, &e) ) {
delete event;
event = 0;
}
}
else if ( eventType == "GroupchatAlertEvent" ) {
event = new GroupchatAlertEvent("", "", 0);
if ( !event->fromXml(psi_, account_, &e) ) {
delete event;
event = 0;
}
}
#endif
if (event && !event->saveable()) {
delete event;
event = 0;
}
if ( event ) {
emit eventFromXml( event );
}
}
return true;
}
QList<EventQueue::PsiEventId> EventQueue::eventsFor(const XMPP::Jid& jid, bool compareRes)
{
QList<PsiEventId> result;
foreach(EventItem* i, list_) {
if (i->event()->from().compare(jid, compareRes))
result << QPair<int, PsiEvent*>(i->id(), i->event());
}
return result;
}
bool EventQueue::toFile(const QString &fname)
{
QDomDocument doc;
QDomElement element = toXml(&doc);
doc.appendChild(element);
AtomicXmlFile f(fname);
return f.saveDocument(doc);
}
bool EventQueue::fromFile(const QString &fname)
{
AtomicXmlFile f(fname);
QDomDocument doc;
if (!f.loadDocument(&doc))
return false;
QDomElement base = doc.documentElement();
return fromXml(&base);
}
#include "psievent.moc"