/* * userlist.cpp - high-level roster * 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"userlist.h" #include"im.h" #include"openpgp.h" #include"common.h" #include"contactview.h" #include"avatars.h" using namespace XMPP; static QString dot_truncate(const QString &in, int clip) { if((int)in.length() <= clip) return in; QString s = in; s.truncate(clip); s += "..."; return s; } //---------------------------------------------------------------------------- // UserResource //---------------------------------------------------------------------------- UserResource::UserResource() :Resource() { } UserResource::UserResource(const Resource &r) { setResource(r); } UserResource::~UserResource() { } void UserResource::setResource(const Resource &r) { setName(r.name()); setStatus(r.status()); } const QString & UserResource::versionString() const { return v_ver; } const QString & UserResource::clientName() const { return v_clientName; } const QString & UserResource::clientVersion() const { return v_clientVersion; } const QString & UserResource::clientOS() const { return v_clientOS; } void UserResource::setClient(const QString &name, const QString& version, const QString& os) { v_clientName = name; v_clientVersion = version; v_clientOS = os; v_ver = v_clientName + " " + v_clientVersion; if ( !v_clientOS.isEmpty() ) v_ver += " / " + v_clientOS; } const QString & UserResource::publicKeyID() const { return v_keyID; } int UserResource::pgpVerifyStatus() const { return v_pgpVerifyStatus; } QDateTime UserResource::sigTimestamp() const { return sigts; } void UserResource::setPublicKeyID(const QString &s) { v_keyID = s; } void UserResource::setPGPVerifyStatus(int x) { v_pgpVerifyStatus = x; } void UserResource::setSigTimestamp(const QDateTime &ts) { sigts = ts; } bool operator<(const UserResource &r1, const UserResource &r2) { return r1.priority() > r2.priority(); } bool operator<=(const UserResource &r1, const UserResource &r2) { return r1.priority() >= r2.priority(); } bool operator==(const UserResource &r1, const UserResource &r2) { return r1.priority() == r2.priority(); } bool operator>(const UserResource &r1, const UserResource &r2) { return r1.priority() < r2.priority(); } bool operator>=(const UserResource &r1, const UserResource &r2) { return r1.priority() <= r2.priority(); } //---------------------------------------------------------------------------- // UserResourceList //---------------------------------------------------------------------------- UserResourceList::UserResourceList() :QValueList() { } UserResourceList::~UserResourceList() { } UserResourceList::Iterator UserResourceList::find(const QString & _find) { for(UserResourceList::Iterator it = begin(); it != end(); ++it) { if((*it).name() == _find) return it; } return end(); } UserResourceList::Iterator UserResourceList::priority() { UserResourceList::Iterator highest = end(); for(UserResourceList::Iterator it = begin(); it != end(); ++it) { if(highest == end() || (*it).priority() > (*highest).priority()) highest = it; } return highest; } UserResourceList::ConstIterator UserResourceList::find(const QString & _find) const { for(UserResourceList::ConstIterator it = begin(); it != end(); ++it) { if((*it).name() == _find) return it; } return end(); } UserResourceList::ConstIterator UserResourceList::priority() const { UserResourceList::ConstIterator highest = end(); for(UserResourceList::ConstIterator it = begin(); it != end(); ++it) { if(highest == end() || (*it).priority() > (*highest).priority()) highest = it; } return highest; } void UserResourceList::sort() { qHeapSort(*this); } //---------------------------------------------------------------------------- // UserListItem //---------------------------------------------------------------------------- UserListItem::UserListItem(bool self) { v_inList = false; v_self = self; v_private = false; lastmsgtype = -1; v_avatarFactory = 0; } UserListItem::~UserListItem() { } bool UserListItem::inList() const { return v_inList; } void UserListItem::setJid(const Jid &j) { LiveRosterItem::setJid(j); int n = jid().full().find('@'); if(n == -1) v_isTransport = true; else v_isTransport = false; } bool UserListItem::isTransport() const { return v_isTransport; } bool UserListItem::isAvailable() const { return !v_url.isEmpty(); } bool UserListItem::isHidden() const { return groups().contains(ContactView::tr("Hidden")); } bool UserListItem::isAway() const { int status; if(!isAvailable()) status = STATUS_OFFLINE; else status = makeSTATUS((*userResourceList().priority()).status()); if(status == STATUS_AWAY || status == STATUS_XA || status == STATUS_DND) return true; else return false; } QDateTime UserListItem::lastAvailable() const { return v_t; } int UserListItem::lastMessageType() const { return lastmsgtype; } void UserListItem::setLastMessageType(const int mtype) { // printf("setting message type to %i\n", mtype); lastmsgtype = mtype; } const QString & UserListItem::presenceError() const { return v_perr; } bool UserListItem::isSelf() const { return v_self; } void UserListItem::setInList(bool b) { v_inList = b; } void UserListItem::setLastAvailable(const QDateTime &t) { v_t = t; } void UserListItem::setPresenceError(const QString &e) { v_perr = e; } UserResourceList & UserListItem::userResourceList() { return v_url; } UserResourceList::Iterator UserListItem::priority() { return v_url.priority(); } const UserResourceList & UserListItem::userResourceList() const { return v_url; } UserResourceList::ConstIterator UserListItem::priority() const { return v_url.priority(); } QString UserListItem::makeTip(bool trim, bool doLinkify) const { return "" + makeBareTip(trim,doLinkify) + ""; } QString UserListItem::makeBareTip(bool trim, bool doLinkify) const { QString str; #ifdef AVATARS str += ""; if (option.avatarsEnabled) { QString client; QString res; if (!userResourceList().isEmpty()) { client = (*userResourceList().priority()).clientName(); res = (*userResourceList().priority()).name(); } if (avatarFactory()) { QPixmap p = avatarFactory()->getAvatar(jid().withResource(res),client); if (!p.isNull()) { str += ""; } } } str += ""; str += "
"; QMimeSourceFactory::defaultFactory()->setPixmap("avatar.png",p); str += ""; str += ""; #endif QString nick = jidnick(jid().full(), name()); str += QString("%1").arg(expandEntities(nick)); if(jid().full() != nick) str += QString("
[%1]").arg(expandEntities(jid().full())); // subscription if(!v_self) str += QString("
") + QObject::tr("Subscription") + ": " + subscription().toString() + ""; if(!v_keyID.isEmpty()) str += QString("
") + QObject::tr("OpenPGP") + ": " + v_keyID.right(8) + ""; // resources if(!userResourceList().isEmpty()) { UserResourceList srl = userResourceList(); srl.sort(); for(UserResourceList::ConstIterator rit = srl.begin(); rit != srl.end(); ++rit) { const UserResource &r = *rit; QString name; if(!r.name().isEmpty()) name = r.name(); else name = QObject::tr("[blank]"); int status = makeSTATUS(r.status()); QString istr = "status/offline"; if(status == STATUS_ONLINE) istr = "status/online"; else if(status == STATUS_AWAY) istr = "status/away"; else if(status == STATUS_XA) istr = "status/xa"; else if(status == STATUS_DND) istr = "status/dnd"; else if(status == STATUS_CHAT) istr = "status/chat"; else if(status == STATUS_INVISIBLE) istr = "status/invisible"; //this shouldn't happen QString imgTag = "icon name"; // or 'img src' if appropriate QMimeSourceFactory is installed. but mblsha noticed that QMimeSourceFactory unloads sometimes QString secstr; if(isSecure(r.name())) secstr += QString(" <%1=\"psi/cryptoYes\">").arg(imgTag); str += QString("
") + QString("<%1=\"%1\"> ").arg(imgTag).arg(istr) + QString("%1 ").arg(expandEntities(name)) + QString("(%1)").arg(r.priority()) + secstr + ""; if(!r.publicKeyID().isEmpty()) { int v = r.pgpVerifyStatus(); if(v == OpenPGP::VerifyGood || v == OpenPGP::VerifyNoKey || v == OpenPGP::VerifyBad) { if(v == OpenPGP::VerifyGood) { QString d = r.sigTimestamp().toString(Qt::TextDate); str += QString("
") + QObject::tr("Signed") + " @ " + "" + d + ""; } else if(v == OpenPGP::VerifyNoKey) { QString d = r.sigTimestamp().toString(Qt::TextDate); str += QString("
") + QObject::tr("Signed") + " @ " + d; } else if(v == OpenPGP::VerifyBad) { str += QString("
") + "" + QObject::tr("Bad signature") + ""; } if(v_keyID != r.publicKeyID()) str += QString(" [%1]").arg(r.publicKeyID().right(8)); str += ""; } } // last status if(r.status().timeStamp().isValid()) { QString d = r.status().timeStamp().toString(Qt::TextDate); str += QString("
") + QObject::tr("Last Status") + " @ " + d + ""; } // gabber music if(!r.status().songTitle().isEmpty()) { QString s = r.status().songTitle(); if(trim) s = dot_truncate(s, 80); s = expandEntities(s); str += QString("
") + QObject::tr("Listening to") + QString(": %1").arg(s) + ""; } // client if(!r.versionString().isEmpty()) { QString ver = r.versionString(); if(trim) ver = dot_truncate(ver, 80); ver = expandEntities(ver); str += QString("
") + QObject::tr("Using") + QString(": %1").arg(ver) + ""; } // status message QString s = r.status().status(); if(!s.isEmpty()) { QString head = QObject::tr("Status Message"); if(trim) s = plain2rich(clipStatus(s, 200, 12)); else s = plain2rich(s); if ( doLinkify ) s = linkify(s); if( option.useEmoticons && !doLinkify ) s = emoticonify(s); str += QString("
%1
%2").arg(head).arg(s); } } } else { // last available if(!lastAvailable().isNull()) { QString d = lastAvailable().toString(Qt::TextDate); str += QString("
") + QObject::tr("Last Available") + " @ " + d + ""; } // presence error if(!v_perr.isEmpty()) { str += QString("
") + QObject::tr("Presence Error") + QString(": %1").arg(expandEntities(v_perr)) + ""; } // status message QString s = lastUnavailableStatus().status(); if(!s.isEmpty()) { QString head = QObject::tr("Last Status Message"); if(trim) s = plain2rich(clipStatus(s, 200, 12)); else { s = plain2rich(clipStatus(s, 200, 12)); if ( doLinkify ) s = linkify(s); } str += QString("
%1
%2").arg(head).arg(s); } } #ifdef AVATARS str += "
"; #endif return str; } QString UserListItem::makeDesc() const { return makeTip(false); } bool UserListItem::isPrivate() const { return v_private; } void UserListItem::setPrivate(bool b) { v_private = b; } bool UserListItem::isSecure(const QString &rname) const { for(QStringList::ConstIterator it = secList.begin(); it != secList.end(); ++it) { if(*it == rname) return true; } return false; } void UserListItem::setSecure(const QString &rname, bool b) { for(QStringList::Iterator it = secList.begin(); it != secList.end(); ++it) { if(*it == rname) { if(!b) secList.remove(it); return; } } if(b) secList.append(rname); } const QString & UserListItem::publicKeyID() const { return v_keyID; } void UserListItem::setPublicKeyID(const QString &k) { v_keyID = k; } AvatarFactory* UserListItem::avatarFactory() const { return v_avatarFactory; } void UserListItem::setAvatarFactory(AvatarFactory* av) { v_avatarFactory = av; } //---------------------------------------------------------------------------- // UserList //---------------------------------------------------------------------------- UserList::UserList() { } UserList::~UserList() { } UserListItem *UserList::find(const XMPP::Jid &j) { UserListIt it(*this); for(UserListItem *i; (i = it.current()); ++it) { if(i->jid().compare(j)) return i; } return 0; }