1
/****************************************************************************
2
** jabcon.cpp - core control class for Psi
3
** Copyright (C) 2001, 2002 Justin Karneges
5
** This program is free software; you can redistribute it and/or
6
** modify it under the terms of the GNU General Public License
7
** as published by the Free Software Foundation; either version 2
8
** of the License, or (at your option) any later version.
10
** This program is distributed in the hope that it will be useful,
11
** but WITHOUT ANY WARRANTY; without even the implied warranty of
12
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
** GNU General Public License for more details.
15
** You should have received a copy of the GNU General Public License
16
** along with this program; if not, write to the Free Software
17
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,USA.
19
****************************************************************************/
21
#include<qapplication.h>
24
#include<qstylesheet.h>
27
#include<qmessagebox.h>
31
#include<qdesktopwidget.h>
37
#include"historydlg.h"
39
#include"optionsdlg.h"
40
#include"servicesdlg.h"
44
#include"offermaindlg.h"
49
jabcon::jabcon(QObject *par)
52
pdb(DEBUG_JABCON, QString("%1 v%2\n By Justin Karneges\n infiniti@affinix.com\n\n").arg(PROG_NAME).arg(PROG_VERSION));
54
lastStatusString = "";
59
pro.fromFile(pathToProfileConfig(activeProfile));
61
// if no accounts, add a blank account
62
if(pro.acc.isEmpty()) {
63
pro.acc.append(UserAccount());
66
// set the "global" profile data
68
lastStatusString = pro.lastStatusString;
69
useSound = pro.useSound;
71
// set the preferences
77
// first thing, try to load the iconset
78
if(!loadPsiIconSet(option.iconset)) {
79
option.iconset = "stellar";
80
if(!loadPsiIconSet(option.iconset)) {
81
QMessageBox::critical(0, tr("Error"), tr("Unable to load iconset! Please make sure Psi is properly installed."));
86
// create a new session
87
s = new JabSession(&jsm);
89
debug_jabber = s->serv();
91
// setup the main window
92
mainwin = new MainWin(option.alwaysOnTop, 0, "psimain");
93
mainwin->userlist = &s->userlist;
94
mainwin->setUseDock(option.useDock);
96
// if the coordinates are out of the desktop bounds, reset to the top left
97
QRect r = QApplication::desktop()->screenGeometry();
98
if(mwgeom.x() >= r.right() || mwgeom.y() >= r.bottom()) {
99
mwgeom.setX(r.left() + 32);
100
mwgeom.setY(r.top() + 32);
102
mainwin->move(mwgeom.x(), mwgeom.y());
103
mainwin->resize(mwgeom.width(), mwgeom.height());
105
cvp = mainwin->cvlist->createProfile("justin@orbit.tenpura.org", "Orbit", TRUE);
107
mainwin->setUsingSSL(FALSE);
109
fileserv = new FileServer;
110
//fileserv->setServer("127.0.0.1", 12346);
111
//FileServerItem *i = fileserv->addFile("/opt/kde", "", "");
113
// printf("offering: [%s]\n", i->url.latin1());
117
connect(&jsm, SIGNAL(accountSettingsChanged()), SLOT(slotApplyAccounts()));
118
connect(&jsm, SIGNAL(jab_connected(JabSession *)), SLOT(jab_connected(JabSession *)));
119
connect(&jsm, SIGNAL(jab_disconnected(JabSession *)), SLOT(jab_disconnected(JabSession *)));
120
connect(&jsm, SIGNAL(jab_statusUpdate(JabSession *, JabUpdate *)), SLOT(jab_statusUpdate(JabSession *, JabUpdate *)) );
121
connect(&jsm, SIGNAL(jab_error(JabSession *, JabError *)), SLOT(jab_error(JabSession *, JabError *)) );
122
connect(&jsm, SIGNAL(jab_messageReceived(JabSession *, const JabMessage &)), SLOT(jab_messageReceived(JabSession *, const JabMessage &)) );
123
connect(&jsm, SIGNAL(jab_resourceAvailable(JabSession *, const Jid &, const JabResource &)), SLOT(jab_resourceAvailable(JabSession *, const Jid &, const JabResource &)));
124
connect(&jsm, SIGNAL(jab_resourceUnavailable(JabSession *, const Jid &)), SLOT(jab_resourceUnavailable(JabSession *, const Jid &)));
125
connect(&jsm, SIGNAL(jab_contactChanged(JabSession *, JabRosterEntry *)), SLOT(jab_contactChanged(JabSession *, JabRosterEntry *)) );
126
connect(&jsm, SIGNAL(jab_contactNew(JabSession *, JabRosterEntry *)), SLOT(jab_contactNew(JabSession *, JabRosterEntry *)) );
127
connect(&jsm, SIGNAL(jab_contactRemove(JabSession *, JabRosterEntry *)), SLOT(jab_contactRemove(JabSession *, JabRosterEntry *)) );
128
connect(&jsm, SIGNAL(jab_authRequest(JabSession *, const Jid &)), SLOT(jab_authRequest(JabSession *, const Jid &)) );
129
connect(&jsm, SIGNAL(jab_authGrant(JabSession *, const Jid &)), SLOT(jab_authGrant(JabSession *, const Jid &)) );
130
connect(&jsm, SIGNAL(jab_authRemove(JabSession *, const Jid &)), SLOT(jab_authRemove(JabSession *, const Jid &)) );
133
/*connect(serv, SIGNAL(connected()), SLOT(servConnected()));
134
connect(serv, SIGNAL(disconnected()), SLOT(servDisconnected()));
135
connect(serv, SIGNAL(statusUpdate(JabUpdate *)), SLOT(statusUpdate(JabUpdate *)) );
136
connect(serv, SIGNAL(error(JabError *)), SLOT(servError(JabError *)) );
137
connect(serv, SIGNAL(messageReceived(const JabMessage &)), SLOT(messageReceived(const JabMessage &)) );
139
connect(serv, SIGNAL(resourceAvailable(const Jid &, const JabResource &)), SLOT(resourceAvailable(const Jid &, const JabResource &)));
140
connect(serv, SIGNAL(resourceUnavailable(const Jid &)), SLOT(resourceUnavailable(const Jid &)));
142
connect(serv, SIGNAL(contactChanged(JabRosterEntry *)), SLOT(contactChanged(JabRosterEntry *)) );
143
connect(serv, SIGNAL(contactNew(JabRosterEntry *)), SLOT(contactNew(JabRosterEntry *)) );
144
connect(serv, SIGNAL(contactRemove(JabRosterEntry *)), SLOT(contactRemove(JabRosterEntry *)) );
146
connect(serv, SIGNAL(authRequest(const Jid &)), SLOT(authRequest(const Jid &)) );
147
connect(serv, SIGNAL(authGrant(const Jid &)), SLOT(authGrant(const Jid &)) );
148
connect(serv, SIGNAL(authRemove(const Jid &)), SLOT(authRemove(const Jid &)) );*/
151
connect(this, SIGNAL(emitOptionsUpdate()), mainwin->cvlist, SLOT(optionsUpdate()) );
152
connect(this, SIGNAL(emitLocalUpdate(const JabRosterEntry &)), cvp, SLOT(localUpdate(const JabRosterEntry &)));
153
connect(cvp, SIGNAL(actionDefault(ContactViewItem *)),SLOT(actionDefault(ContactViewItem *)) );
154
connect(cvp, SIGNAL(actionRecvEvent(ContactViewItem *)),SLOT(actionRecvEvent(ContactViewItem *)) );
155
connect(cvp, SIGNAL(actionSendMessage(ContactViewItem *)),SLOT(actionSendMessage(ContactViewItem *)) );
156
connect(cvp, SIGNAL(actionSendMessage(const QStringList &)),SLOT(actionSendMessage(const QStringList &)) );
157
connect(cvp, SIGNAL(actionSendUrl(const QString &)),SLOT(actionSendUrl(const QString &)) );
158
connect(cvp, SIGNAL(actionAuthorize(ContactViewItem *)),SLOT(actionAuthorize(ContactViewItem *)) );
159
connect(cvp, SIGNAL(actionAdd(ContactViewItem *)),SLOT(actionAdd(ContactViewItem *)) );
160
connect(cvp, SIGNAL(actionRemove(const QString &)),SLOT(actionRemove(const QString &)) );
161
connect(cvp, SIGNAL(actionRename(ContactViewItem *, const QString &)),SLOT(actionRename(ContactViewItem *, const QString &)) );
162
connect(cvp, SIGNAL(actionGroupChange(const QString &, const QString &)),SLOT(actionGroupChange(const QString &, const QString &)) );
163
connect(cvp, SIGNAL(actionGroupRename(const QString &, const QString &)),SLOT(actionGroupRename(const QString &, const QString &)) );
164
connect(cvp, SIGNAL(actionHistory(const QString &)),SLOT(actionHistory(const QString &)) );
165
connect(cvp, SIGNAL(actionStatusShow(const QString &)),SLOT(actionStatusShow(const QString &)) );
166
connect(cvp, SIGNAL(actionOpenChat(const QString &)), SLOT(actionOpenChat(const QString &)) );
167
connect(cvp, SIGNAL(actionAgentSetStatus(const QString &, int)), SLOT(agentSetStatus(const QString &, int)));
168
connect(cvp, SIGNAL(actionInfo(const QString &)), SLOT(actionInfo(const QString &)));
169
connect(cvp, SIGNAL(actionOfferFile(const QString &)), SLOT(actionOfferFile(const QString &)));
170
connect(mainwin, SIGNAL(doOptions()), SLOT(doOptions()) );
171
connect(mainwin, SIGNAL(doManageServices()), SLOT(doManageServices()) );
172
connect(mainwin, SIGNAL(doManageAccounts()), SLOT(doManageAccounts()) );
173
connect(mainwin, SIGNAL(doFileSharing()), SLOT(doFileSharing()) );
174
connect(mainwin, SIGNAL(accountInfo()), SLOT(openAccountInfo()) );
175
connect(mainwin, SIGNAL(blankMessage()), SLOT(composeBlankMessage()) );
176
connect(mainwin, SIGNAL(statusChanged(int)),SLOT(statusMenuChanged(int)) );
177
connect(mainwin, SIGNAL(closeProgram()), SLOT(closeProgram()));
178
connect(mainwin, SIGNAL(changeProfile()), SLOT(changeProfile()));
179
connect(mainwin, SIGNAL(addUser()), SLOT(askAddUser()));
180
connect(mainwin, SIGNAL(recvNextEvent()), SLOT(recvNextEvent()));
181
connect(this, SIGNAL(emitLocalUpdate(const JabRosterEntry &)), mainwin, SLOT(localUpdate(const JabRosterEntry &)));
182
connect(this, SIGNAL(emitOptionsUpdate()), mainwin, SLOT(optionsUpdate()) );
184
s->setContactProfile(cvp);
185
s->setAccount(pro.acc.first());
187
mainwin->cvlist->setShowOffline(s->acc()->tog_offline);
188
mainwin->cvlist->setShowAway(s->acc()->tog_away);
189
mainwin->cvlist->setShowAgents(s->acc()->tog_agents);
193
JabUpdate ju = s->serv()->getJU();
194
jab_statusUpdate(s, &ju);
196
emitLocalUpdate(*s->serv()->userEntry());
199
connect(&idle, SIGNAL(secondsIdle(int)), s, SLOT(secondsIdle(int)));
202
if(s->acc()->host.isEmpty()) {
206
if(s->acc()->opt_auto)
207
statusMenuChanged(STATUS_ONLINE);
215
// serv not created yet? don't bother destructing
221
//isDisconnecting = TRUE;
223
s->acc()->roster = *s->serv()->getCurrentRoster();
224
s->acc()->olr_string = s->serv()->getOLR();
226
mwgeom.setX(mainwin->x());
227
mwgeom.setY(mainwin->y());
228
mwgeom.setWidth(mainwin->width());
229
mwgeom.setHeight(mainwin->height());
230
s->acc()->tog_offline = mainwin->cvlist->isShowOffline();
231
s->acc()->tog_away = mainwin->cvlist->isShowAway();
232
s->acc()->tog_agents = mainwin->cvlist->isShowAgents();
236
// delete all toplevel windows except log window (and QDesktopWidget..)
237
QWidgetList *list = QApplication::topLevelWidgets();
238
QWidgetListIt it(*list);
239
for(QWidget *w; (w = it.current()); ++it) {
240
if(w->isA("LogWindow") && (LogWindow *)w == debug_window)
242
if(w->isA("QDesktopWidget") || w->isA("QWidget"))
250
pro.lastStatusString = lastStatusString;
251
pro.useSound = useSound;
253
pro.acc.first() = *s->acc();
256
pro.toFile(pathToProfileConfig(activeProfile));
266
void jabcon::jab_connected(JabSession *)
268
mainwin->setUsingSSL(s->serv()->isSSLEnabled());
271
void jabcon::jab_disconnected(JabSession *)
275
void jabcon::jab_statusUpdate(JabSession *, JabUpdate *x)
277
// make a status string
279
if(x->queuePending > 0)
280
str.append(QString("[%1] - ").arg(x->queuePending));
283
// show status in the gui
284
mainwin->setInfo(str);
286
pdb(DEBUG_JABCON, QString("[jabcon: status update: %1]\n").arg(str));
289
void jabcon::jab_error(JabSession *, JabError *err)
291
if(err->type == JABERR_CONNECT) {
292
QMessageBox::critical(0, CAP(tr("Error")), QString(tr("There was an error communicating with the Jabber server.\nReason: %1")).arg(err->msg));
295
else if(err->type == JABERR_AUTH) {
296
QMessageBox::critical(0, CAP(tr("Error")), QString(tr("Authorization failed.\nReason: %1")).arg(err->msg));
299
else if(err->type == JABERR_CREATE) {
300
QMessageBox::critical(0, CAP(tr("Error")), QString(tr("Failed to create the new account.\nThe server gave this reason: \"%1\"")).arg(err->msg));
303
else if(err->type == JABERR_DISCONNECT) {
304
QMessageBox::critical(0, CAP(tr("Error")), tr("You have been disconnected from the Jabber server."));
307
QMessageBox::critical(0, CAP(tr("Error")), QString(tr("An unknown error occurred.\nType: %1\nReason: %2")).arg(err->type).arg(err->msg));
311
void jabcon::jab_messageReceived(JabSession *, const JabMessage &_msg)
314
if(_msg.type == JABMESSAGE_HEADLINE && option.ignoreHeadline)
318
msg.from = _msg.from.full();
319
if(_msg.type == JABMESSAGE_CHAT)
320
msg.type = MESSAGE_CHAT;
321
else if(_msg.type == JABMESSAGE_ERROR)
322
msg.type = MESSAGE_ERROR;
323
else if(_msg.type == JABMESSAGE_HEADLINE)
324
msg.type = MESSAGE_HEADLINE;
326
msg.type = MESSAGE_NORM;
327
msg.text = _msg.body;
328
msg.subject = _msg.subject;
330
msg.url_desc = _msg.url_desc;
331
msg.timeStamp = _msg.timeStamp;
332
msg.late = _msg.late;
333
msg.originLocal = FALSE;
335
pdb(DEBUG_JABCON, QString("[jabcon: message received from %1]\n").arg(msg.from));
338
if(option.incomingAs == 1)
339
msg.type = MESSAGE_NORM;
340
else if(option.incomingAs == 2)
341
msg.type = MESSAGE_CHAT;
343
if(msg.type == MESSAGE_CHAT) {
344
ChatDlg *c = ChatDlg::find(msg.from);
345
if(c && !c->isHidden()) {
346
c->incomingMessage(msg);
347
doOnEvent(option.onevent[eChat2]);
349
// since it never goes into the queue in this case, we need to log here
350
if(s->acc()->opt_log)
357
if(msg.type == MESSAGE_ERROR) {
358
msg.text = QString(tr("<big>[Error Message]</big><br>%1").arg(plain2rich(msg.text)));
364
void jabcon::jab_resourceAvailable(JabSession *s, const Jid &j, const JabResource &r)
366
QString dstr = QString("[jabcon: resource available: jid=[%1], name=[%2], status=[%3] ]\n").arg(j.full()).arg(r.name).arg(status2txt(r.status));
367
pdb(DEBUG_JABCON, dstr);
369
JabRosterEntry *me = s->serv()->userEntry();
370
if(jidcmp(me->jid, j.s())) {
371
int oldStatus = s->localStatus;
373
s->localStatus = me->local()->status;
374
s->localStatusString = me->local()->statusString;
376
pdb(DEBUG_JABCON, QString("presence: [%1] total=%2\n").arg(status2txt(s->localStatus)).arg(me->res.count()));
378
mainwin->decorateButton(s->localStatus);
379
emitLocalUpdate(*me);
381
// coming from offline to online
382
if(oldStatus == STATUS_OFFLINE && s->localStatus != STATUS_OFFLINE) {
384
QMessageBox::information(0, CAP(tr("Success")), tr("New account was created and logged in successfully. Enjoy."));
387
// allow the new user to set account info
391
QTimer::singleShot(15000, this, SLOT(enableOnEventOnline()));
393
JT_VCard *j = new JT_VCard(s->serv()->ioUser());
394
connect(j, SIGNAL(finished(JabTask *)), SLOT(slotCheckVCard(JabTask *)));
395
j->get(s->acc()->jid());
400
UserListItem *item = s->userlist.findAnyByJid(j.s());
404
// if the contact was offline before this, then do things
405
bool doThings = FALSE;
406
if(item->state == STATUS_OFFLINE && s->onEventOnlineOk)
409
//item->state = r.status;
410
//item->statusString = r.statusString;
412
// add/update resource
413
JabResource *r2 = item->res.find(r.name);
415
r2 = new JabResource(r);
416
item->res.append(r2);
422
// contact view should reflect the priority status
423
item->state = item->res.priority()->status;
424
item->statusString = item->res.priority()->statusString;
427
cvp->updateEntry(*item);
428
//mainwin->cvlist->updateEntry(item->jid, jidnick(item->jid, item->nick), item->group, item->sub, item->state, item->statusString, item->inList, item->isTransport, item->res);
431
doOnEvent(option.onevent[eOnline]);
433
if(option.rosterAnim)
434
cvp->animateNick(item->jid);
442
void jabcon::jab_resourceUnavailable(JabSession *s, const Jid &j)
444
QString dstr = QString("[jabcon: resource unavailable: jid=[%1], name=[%2] ]\n").arg(j.s()).arg(j.resource());
445
pdb(DEBUG_JABCON, dstr);
447
JabRosterEntry *me = s->serv()->userEntry();
448
if(jidcmp(me->jid, j.s())) {
449
// only go offline if the local resource goes offline
451
s->localStatus = STATUS_OFFLINE;
452
s->localStatusString = "";
454
pdb(DEBUG_JABCON, QString("presence: [%1] total=%2\n").arg(status2txt(s->localStatus)).arg(me->res.count()));
456
mainwin->setUsingSSL(FALSE);
458
mainwin->decorateButton(s->localStatus);
459
emitLocalUpdate(*me);
461
// restore original account and delete contacts if guestMode
463
pdb(DEBUG_JABCON, "Return from GUESTMODE\n");
472
emitLocalUpdate(*me);
475
JabRosterEntry *entry = s->serv()->findByJid(j.s());
478
UserListItem *item = s->userlist.findAnyByJid(j.s());
482
// if the contact was not offline before this, then sound
483
if(item->state != STATUS_OFFLINE && !s->isDisconnecting)
484
doOnEvent(option.onevent[eOffline]);
486
// still available? use next highest resource
487
if(entry->isAvailable()) {
488
JabResource *r = entry->res.priority();
489
item->state = r->status;
490
item->statusString = r->statusString;
494
item->state = STATUS_OFFLINE;
495
item->statusString = entry->unavailableStatusString;
499
JabResource *r = item->res.find(j.resource());
504
cvp->updateEntry(*item);
505
//mainwin->cvlist->updateEntry(item->jid, jidnick(item->jid, item->nick), item->group, item->sub, item->state, item->statusString, item->inList, item->isTransport, item->res);
512
void jabcon::jab_contactChanged(JabSession *, JabRosterEntry *entry)
514
QString dstr = QString("[jabcon: roster changed: %1]\n").arg(entry->jid);
515
pdb(DEBUG_JABCON, dstr);
517
// this should never fail...
518
UserListItem *item = s->userlist.findAnyByJid(cleanJid(entry->jid));
522
// copy into userlist
523
item->nick = entry->nick;
524
if(entry->groups.isEmpty())
527
item->group = entry->groups[0];
528
item->sub = entry->sub;
530
QString nick = item->nick.isEmpty() ? item->jid: item->nick;
533
cvp->updateEntry(*item);
534
//mainwin->cvlist->updateEntry(item->jid, nick, item->group, item->sub, item->state, item->statusString, item->inList, item->isTransport, item->res);
540
void jabcon::jab_contactNew(JabSession *, JabRosterEntry *entry)
542
// we probably already have the entry in our list somewhere,
543
// because of the authorization transaction
544
UserListItem *item = s->userlist.findAnyByJid(cleanJid(entry->jid));
548
cvp->updateEntry(*item);
549
//mainwin->cvlist->updateEntry(item->jid, jidnick(item->jid, item->nick), item->group, item->sub, item->state, item->statusString, item->inList, item->isTransport, item->res);
552
// add to the userlist
553
UserListItem *item = new UserListItem;
554
item->jid = cleanJid(entry->jid);
555
item->nick = entry->nick;
556
if(entry->groups.isEmpty())
559
item->group = entry->groups[0];
560
item->sub = entry->sub;
562
item->state = STATUS_OFFLINE;
563
item->isTransport = jidIsAgent(item->jid);
565
// a new entry that is "push"? [pushinfo]
568
if(readUserInfo(entry->jid, &info) && !info.field[vNickname].isEmpty()) {
569
item->nick = info.field[vNickname];
572
if(localStatus != STATUS_OFFLINE)
573
serv->getVCard(item->jid);
577
s->userlist.add(item);
579
// add to the contact gui
580
cvp->updateEntry(*item);
581
//mainwin->cvlist->updateEntry(item->jid, jidnick(item->jid, item->nick), item->group, item->sub, item->state, item->statusString, item->inList, item->isTransport, item->res);
583
// search for unread messages and queue them
587
pdb(DEBUG_JABCON, QString("[jabcon: %1 has been added to the internal contact list]\n").arg(entry->jid));
590
void jabcon::jab_contactRemove(JabSession *, JabRosterEntry *entry)
592
UserListItem *item = s->userlist.findAnyByJid(cleanJid(entry->jid));
596
// remove all events from the queue (and tell mainwin)
597
events.removeAll(item->jid);
599
int next_amount = events.QPtrList<EventItem>::count();
601
next_type = events.peekNext()->msg.type;
602
mainwin->updateReadNext(next_type, next_amount);
604
// remove from the contact gui
605
cvp->removeEntry(item->jid);
607
// remove from the userlist
608
s->userlist.remove(item->jid);
610
pdb(DEBUG_JABCON, QString("[jabcon: %1 has been removed from the internal contact list]\n").arg(entry->jid));
613
void jabcon::jab_authRequest(JabSession *, const Jid &from)
615
QString body(tr("<big>[System Message]</big><br>This user wants to subscribe to your presence. Click the button labelled \"Add/Auth\" to authorize the subscription. This will also add the person to your contact list if it is not already there."));
618
tmp.from = from.full();
619
tmp.type = MESSAGE_AUTHREQ;
621
tmp.timeStamp = QDateTime::currentDateTime();
623
tmp.originLocal = FALSE;
626
pdb(DEBUG_JABCON, QString("[jabcon: %1 wants to add you to their list]\n").arg(from.full()));
629
void jabcon::jab_authGrant(JabSession *, const Jid &from)
631
QString body(tr("<big>[System Message]</big><br>You are now authorized."));
634
tmp.from = from.full();
635
tmp.type = MESSAGE_SYS;
637
tmp.timeStamp = QDateTime::currentDateTime();
639
tmp.originLocal = FALSE;
642
pdb(DEBUG_JABCON, QString("[jabcon: %1 has authorized you]\n").arg(from.full()));
645
void jabcon::jab_authRemove(JabSession *, const Jid &from)
647
// only send a sysmessage if it's done by the other person
648
// (because we get this signal when we remove contacts too. I think...)
649
if(s->userlist.findAnyByJid(from.s())) {
650
QString body(tr("<big>[System Message]</big><br>Your authorization has been removed!"));
653
tmp.from = from.full();
654
tmp.type = MESSAGE_SYS;
656
tmp.timeStamp = QDateTime::currentDateTime();
658
tmp.originLocal = FALSE;
662
pdb(DEBUG_JABCON, QString("[jabcon: %1 has removed you from their contact list]\n").arg(from.full()));
667
/*void jabcon::servConnected()
669
mainwin->setUsingSSL(serv->isSSLEnabled());
672
void jabcon::servDisconnected()
674
isDisconnecting = TRUE;
677
void jabcon::statusUpdate(JabUpdate *x)
679
// make a status string
681
if(x->queuePending > 0)
682
str.append(QString("[%1] - ").arg(x->queuePending));
685
// show status in the gui
686
mainwin->setInfo(str);
688
pdb(DEBUG_JABCON, QString("[jabcon: status update: %1]\n").arg(str));
692
void jabcon::insertMessage(const Message &msg, bool doLog)
695
if(msg.type == MESSAGE_CHAT) {
696
// any pending chats from this person?
698
UserListItem *i = s->userlist.findAnyByJid(msg.from);
700
found = events.hasChats(i->jid);
702
doOnEvent(option.onevent[found ? eChat2: eChat1]);
704
else if(msg.type == MESSAGE_NORM)
705
doOnEvent(option.onevent[eMessage]);
706
else if(msg.type == MESSAGE_HEADLINE)
707
doOnEvent(option.onevent[eMessage]);
709
doOnEvent(option.onevent[eSystem]);
714
if(s->acc()->opt_log)
719
cvp->showAlert(cleanJid(msg.from), msg.type);
721
// update mainwin status
722
mainwin->updateReadNext(events.peekNext()->msg.type, events.QPtrList<EventItem>::count());
725
EventDlg *e = EventDlg::find(msg.from);
727
UserListItem *item = s->userlist.findAnyByJid(msg.from);
728
e->updateReadNext(events.peek(item->jid)->msg.type, events.count(item->jid));
731
if((msg.type != MESSAGE_CHAT && option.popupMsgs) ||
732
(msg.type == MESSAGE_CHAT && option.popupChats)) {
733
UserListItem *i = s->userlist.findAnyByJid(msg.from);
740
// win_raiseNoFocus(mainwin);
742
mainwin->showNormal();
748
void jabcon::actionDefault(ContactViewItem *item)
750
UserListItem *i = s->userlist.findAnyByJid(item->jid());
755
QString dstr; dstr.sprintf("[jabcon: default action: %s]\n", i->jid.latin1());
756
pdb(DEBUG_JABCON, dstr);
760
// pending messages from this person?
761
if(events.count(i->jid) > 0) {
765
if(option.defaultAction == 0)
766
composeMessage(i, FALSE);
772
void jabcon::actionSendMessage(ContactViewItem *item)
774
UserListItem *i = s->userlist.findAnyByJid(item->jid());
777
composeMessage(i, FALSE);
780
void jabcon::actionSendMessage(const QStringList &list)
782
EventDlg *c = new EventDlg(list, s->localStatus);
783
connect(c, SIGNAL(aSend(const Message &)), SLOT(sendMessage(const Message &)));
784
connect(c, SIGNAL(aOpenURL(const QString &)), SLOT(actionOpenURL(const QString &)));
785
connect(this, SIGNAL(emitLocalUpdate(const JabRosterEntry &)), c, SLOT(localUpdate(const JabRosterEntry &)));
786
connect(this, SIGNAL(emitOptionsUpdate()), c, SLOT(optionsUpdate()));
791
void jabcon::actionSendUrl(const QString &jid)
793
UserListItem *i = s->userlist.findAnyByJid(jid);
796
composeMessage(i, TRUE);
799
void jabcon::actionRecvEvent(ContactViewItem *item)
801
UserListItem *i = s->userlist.findAnyByJid(item->jid());
805
if(events.count(i->jid) > 0)
809
void jabcon::actionRemove(const QString &jid)
811
UserListItem *i = s->userlist.findAnyByJid(jid);
818
void jabcon::actionRename(ContactViewItem *item, const QString &newname)
820
UserListItem *i = s->userlist.findAnyByJid(item->jid());
825
userRename(i, newname);
828
void jabcon::actionGroupChange(const QString &jid, const QString &groupname)
830
UserListItem *i = s->userlist.findAnyByJid(jid);
838
userGroupChange(i, groupname);
841
void jabcon::actionGroupRename(const QString &oldname, const QString &groupname)
843
// change all users in this group to use the new name
844
UserListItem *i = s->userlist.start(USERLIST_CONTACTS);
845
for(; i ; i = s->userlist.next()) {
846
if(oldname == i->group)
847
userGroupChange(i, groupname);
852
void jabcon::actionHistory(const QString &jid)
854
UserListItem *i = s->userlist.findAnyByJid(jid);
858
// search for an already opened historydlg
859
HistoryDlg *hist = HistoryDlg::find(i->jid);
865
hist = new HistoryDlg(i, 0, "HistoryDlg");
866
connect(hist, SIGNAL(openMessage(const Message &)), SLOT(actionHistoryBox(const Message &)));
872
void jabcon::actionHistoryBox(const Message &msg)
878
// create the messagebox
879
EventDlg *e = new EventDlg(&tmp, s->localStatus, FALSE, FALSE);
880
connect(e, SIGNAL(aReply(const QString &)), SLOT(composeMessage(const QString &)));
881
connect(e, SIGNAL(aReadNext(const QString &)), SLOT(processReadNext(const QString &)));
882
connect(e, SIGNAL(aAuth(const QString &)), SLOT(userAddAuth(const QString &)));
883
connect(e, SIGNAL(aInfo(const QString &)), SLOT(actionInfo(const QString &)));
884
connect(e, SIGNAL(aHistory(const QString &)), SLOT(actionHistory(const QString &)));
885
connect(e, SIGNAL(aOpenURL(const QString &)), SLOT(actionOpenURL(const QString &)));
886
connect(this, SIGNAL(emitContact(UserListItem *)), e, SLOT(updateContact(UserListItem *)));
887
connect(this, SIGNAL(emitLocalUpdate(const JabRosterEntry &)), e, SLOT(localUpdate(const JabRosterEntry &)));
888
connect(this, SIGNAL(emitOptionsUpdate()), e, SLOT(optionsUpdate()));
891
//processReadNext(item);
897
void jabcon::actionStatusShow(const QString &jid)
899
UserListItem *i = s->userlist.findAnyByJid(jid);
903
StatusShowDlg *w = new StatusShowDlg(i);
907
void jabcon::actionAuthorize(ContactViewItem *item)
909
userAuthorize(item->jid());
912
void jabcon::actionAdd(ContactViewItem *item)
914
userAdd(item->jid());
917
void jabcon::actionOpenChat(const QString &jid)
919
UserListItem *item = s->userlist.findAnyByJid(jid);
926
void jabcon::actionInfo(const QString &jid)
928
InfoDlg *w = InfoDlg::find(jid);
933
Info *p = InfoBank::get(jid);
938
w = new InfoDlg(INFODLG_CONTACT, jid, tmp, s->localStatus, 0);
939
connect(w, SIGNAL(signalGetVCard(const QString &, QString *)), SLOT(slotGetVCard(const QString &, QString *)));
940
connect(w, SIGNAL(signalCancelTransaction(const QString &)), SLOT(slotCancelTransaction(const QString &)));
941
connect(this, SIGNAL(emitLocalUpdate(const JabRosterEntry &)), w, SLOT(localUpdate(const JabRosterEntry &)));
944
// automatically retrieve info if it doesn't exist
951
ChatDlg *jabcon::ensureChatDlg(const QString &jid)
953
UserListItem *item = s->userlist.findAnyByJid(jid);
957
ChatDlg *c = ChatDlg::find(jid);
959
// create the chatbox
960
c = new ChatDlg(item, s->acc()->user, s->localStatus);
961
connect(c, SIGNAL(aSend(const Message &)), SLOT(sendMessage(const Message &)));
962
connect(c, SIGNAL(aInfo(const QString &)), SLOT(actionInfo(const QString &)));
963
connect(c, SIGNAL(aHistory(const QString &)), SLOT(actionHistory(const QString &)));
964
connect(c, SIGNAL(aOpenURL(const QString &)), SLOT(actionOpenURL(const QString &)));
965
connect(this, SIGNAL(emitContact(UserListItem *)), c, SLOT(updateContact(UserListItem *)));
966
connect(this, SIGNAL(emitLocalUpdate(const JabRosterEntry &)), c, SLOT(localUpdate(const JabRosterEntry &)));
967
connect(this, SIGNAL(emitOptionsUpdate()), c, SLOT(optionsUpdate()));
973
void jabcon::openChat(UserListItem *item)
975
ChatDlg *c = ensureChatDlg(item->jid);
977
return; // not quite sure how this would happen
987
void jabcon::readMessage(UserListItem *item)
989
Message *m = &events.peek(item->jid)->msg;
990
if(m->type == MESSAGE_CHAT) {
994
// search for an already opened messagebox
995
EventDlg *e = EventDlg::find(item->jid);
1001
// create the messagebox
1002
e = new EventDlg(item, s->localStatus, TRUE, FALSE);
1003
connect(e, SIGNAL(aReply(const QString &)), SLOT(composeMessage(const QString &)));
1004
connect(e, SIGNAL(aReadNext(const QString &)), SLOT(processReadNext(const QString &)));
1005
connect(e, SIGNAL(aAuth(const QString &)), SLOT(userAddAuth(const QString &)));
1006
connect(e, SIGNAL(aInfo(const QString &)), SLOT(actionInfo(const QString &)));
1007
connect(e, SIGNAL(aHistory(const QString &)), SLOT(actionHistory(const QString &)));
1008
connect(e, SIGNAL(aOpenURL(const QString &)), SLOT(actionOpenURL(const QString &)));
1010
connect(this, SIGNAL(emitContact(UserListItem *)), e, SLOT(updateContact(UserListItem *)));
1011
connect(this, SIGNAL(emitLocalUpdate(const JabRosterEntry &)), e, SLOT(localUpdate(const JabRosterEntry &)));
1012
connect(this, SIGNAL(emitOptionsUpdate()), e, SLOT(optionsUpdate()));
1015
processReadNext(item);
1023
void jabcon::composeMessage(const QString &jid)
1025
UserListItem *i = s->userlist.findAnyByJid(jid);
1029
actionSendMessage(tmp);
1032
composeMessage(i, FALSE);
1035
void jabcon::composeMessage(UserListItem *item, bool urlMode)
1037
EventDlg *c = new EventDlg(item, s->localStatus, FALSE, TRUE, urlMode);
1038
connect(c, SIGNAL(aSend(const Message &)), SLOT(sendMessage(const Message &)));
1039
connect(c, SIGNAL(aInfo(const QString &)), SLOT(actionInfo(const QString &)));
1040
connect(c, SIGNAL(aHistory(const QString &)), SLOT(actionHistory(const QString &)));
1041
connect(c, SIGNAL(aOpenURL(const QString &)), SLOT(actionOpenURL(const QString &)));
1042
connect(this, SIGNAL(emitContact(UserListItem *)), c, SLOT(updateContact(UserListItem *)));
1043
connect(this, SIGNAL(emitLocalUpdate(const JabRosterEntry &)), c, SLOT(localUpdate(const JabRosterEntry &)));
1044
connect(this, SIGNAL(emitOptionsUpdate()), c, SLOT(optionsUpdate()));
1049
void jabcon::composeBlankMessage()
1053
EventDlg *c = new EventDlg(to, s->localStatus);
1054
connect(c, SIGNAL(aSend(const Message &)), SLOT(sendMessage(const Message &)));
1055
connect(c, SIGNAL(aOpenURL(const QString &)), SLOT(actionOpenURL(const QString &)));
1056
connect(this, SIGNAL(emitLocalUpdate(const JabRosterEntry &)), c, SLOT(localUpdate(const JabRosterEntry &)));
1057
connect(this, SIGNAL(emitOptionsUpdate()), c, SLOT(optionsUpdate()));
1062
void jabcon::sendMessage(const Message &msg)
1066
if(msg.type == MESSAGE_CHAT)
1067
tmp.type = JABMESSAGE_CHAT;
1069
tmp.type = JABMESSAGE_NORM;
1070
tmp.body = msg.text;
1071
tmp.subject = msg.subject;
1073
tmp.url_desc = msg.url_desc;
1075
s->serv()->sendMessage(tmp);
1077
QString dstr; dstr.sprintf("jabcon: message sent to %s.\n", msg.to.latin1());
1078
pdb(DEBUG_JABCON, dstr);
1080
if(s->acc()->opt_log) {
1081
MessageHistory log(msg.to, HISTORY_WRITE);
1082
log.writeEntry(msg);
1085
doOnEvent(option.onevent[eSend]);
1087
// auto close an open messagebox (if non-chat)
1088
if(msg.type != MESSAGE_CHAT) {
1089
EventDlg *e = EventDlg::find(msg.to);
1091
e->closeAfterReply();
1096
void jabcon::processReadNext(const QString &jid)
1098
UserListItem *i = s->userlist.findAnyByJid(jid);
1104
void jabcon::processReadNext(UserListItem *item)
1106
EventDlg *e = EventDlg::find(item->jid);
1108
// this should NEVER happen
1112
// look at the message
1113
Message *m = &events.peek(item->jid)->msg;
1115
// if it's a chat message, just open the chat window. there is no need to do
1116
// further processing. the chat window will remove it from the queue, de-alert
1117
// the cvlist, etc etc.
1118
if(m->type == MESSAGE_CHAT) {
1123
// remove from queue
1124
EventItem *ei = events.dequeue(item->jid);
1125
//flagAsRead(ei->msg);
1128
// update the eventdlg
1129
e->updateEvent(ei->msg);
1132
// update eventdlg's read-next
1134
if(events.count(item->jid) > 0)
1135
nexttype = events.peek(item->jid)->msg.type;
1136
e->updateReadNext(nexttype, events.count(item->jid));
1138
// clear the cvlist alert
1139
cvp->clearAlert(item->jid);
1143
int next_amount = events.QPtrList<EventItem>::count();
1145
next_type = events.peekNext()->msg.type;
1146
mainwin->updateReadNext(next_type, next_amount);
1149
void jabcon::processChats(const QString &jid)
1151
UserListItem *i = s->userlist.findAnyByJid(jid);
1157
void jabcon::processChats(UserListItem *item)
1159
ChatDlg *c = ChatDlg::find(item->jid);
1161
// this should NEVER happen
1164
pdb(DEBUG_JABCON, "jabcon: processChats: processing chats.\n");
1166
// extract the chats and position list
1167
QPtrList<Message> chatList;
1168
QValueList<int> pos;
1169
events.extractChats(item->jid, &chatList, &pos);
1171
// dump the chats into the chat window, and remove the related cvlist alerts
1172
chatList.setAutoDelete(TRUE);
1173
QValueList<int>::Iterator it = pos.begin();
1175
for(Message *m = chatList.last(); m;) {
1176
// process the message
1178
c->incomingMessage(*m);
1183
// deleting an item at the end means we need to move up to the new "last"
1184
m = chatList.last();
1187
int x = (*it) - modifier;
1188
//printf("deleting entry %d (pos=%d,mod=%d)\n", x, (*it), modifier);
1189
cvp->clearAlert(item->jid, x);
1194
// if there is an associated eventdlg, make sure that gets updated also
1195
EventDlg *e = EventDlg::find(item->jid);
1198
if(events.count(item->jid) > 0)
1199
nexttype = events.peek(item->jid)->msg.type;
1201
e->updateReadNext(nexttype, events.count(item->jid));
1206
int next_amount = events.QPtrList<EventItem>::count();
1208
next_type = events.peekNext()->msg.type;
1209
mainwin->updateReadNext(next_type, next_amount);
1212
void jabcon::userRemove(UserListItem *i)
1217
s->serv()->unsubscribe(i->jid);
1220
void jabcon::userRename(UserListItem *i, const QString &newname)
1222
if(i->nick == newname)
1225
// setting to jidname? remove nick
1226
if(newname == i->jid)
1236
s->serv()->setRoster(i->jid, i->nick, i->group);
1239
void jabcon::userGroupChange(UserListItem *i, const QString &groupname)
1241
i->group = groupname;
1243
s->serv()->setRoster(i->jid, i->nick, i->group);
1247
/****************************************************************************
1249
****************************************************************************/
1250
void jabcon::userAdd(const QString &jid)
1252
// the contact should be in the local list someplace
1253
UserListItem *i = s->userlist.findAnyByJid(jid);
1257
// put the user in our contact list (don't do this if it's already there)
1258
if(!s->serv()->findByJid(i->jid))
1259
s->serv()->setRoster(i->jid, i->nick, i->group);
1261
// request subscription
1262
s->serv()->subscribe(i->jid);
1265
void jabcon::userAuthorize(const QString &jid)
1267
s->serv()->subscribed(jid);
1270
void jabcon::userAddAuth(const QString &jid)
1272
// the contact should be in the local list someplace
1273
UserListItem *i = s->userlist.findAnyByJid(jid);
1277
// authorize using authoritative jid (argument) instead of local jid (userlist)
1280
// only add if it's _not_ a transport.
1281
// this is a workaround for the AIM transport, which has status change
1282
// problems if fully subscribed.
1289
void jabcon::actionAdd(const QString &jid, const QString &nick, const QString &group)
1291
s->serv()->subscribe(jid);
1293
// skip setting the roster if it's already in the server contact list
1294
if(s->serv()->findByJid(jid))
1297
s->serv()->setRoster(jid, nick, group);
1300
void jabcon::agentSetStatus(const QString &jid, int status)
1302
UserListItem *i = s->userlist.findServiceByJid(jid);
1306
s->serv()->agentSetStatus(jid, status);
1309
void jabcon::agentRemove(const QString &jid)
1311
UserListItem *i = s->userlist.findServiceByJid(jid);
1315
s->serv()->unsubscribe(i->jid);
1316
//userRemove(i); // FIXME: i say this whole jabcon class needs help
1320
void jabcon::queueMessage(const Message &msg)
1322
UserListItem *item = s->userlist.findAnyByJid(msg.from);
1324
// if not in list, add a temporary entry
1326
// add to the userlist
1327
item = new UserListItem;
1328
item->jid = cleanJid(msg.from);
1332
item->state = STATUS_OFFLINE;
1333
item->statusString = "";
1334
item->inList = FALSE;
1335
item->isTransport = jidIsAgent(item->jid);
1337
// treat it like a push [pushinfo]
1339
if(readUserInfo(item->jid, &info) && !info.field[vNickname].isEmpty())
1340
item->nick = info.field[vNickname];
1342
if(localStatus != STATUS_OFFLINE)
1343
serv->getVCard(item->jid);
1346
s->userlist.add(item);
1349
// make sure the contact is displayed
1350
QString nick = item->nick.isEmpty() ? item->jid: item->nick;
1351
cvp->updateEntry(*item);
1352
//mainwin->cvlist->updateEntry(item->jid, nick, item->group, item->sub, item->state, item->statusString, item->inList, item->isTransport, item->res);
1354
EventItem *ei = new EventItem;
1355
ei->jid = item->jid;
1359
QString dstr; dstr.sprintf("jabcon: queuing a message from %s.\n", msg.from.latin1());
1360
pdb(DEBUG_JABCON, dstr);
1363
void jabcon::logMessage(const Message &msg)
1366
MessageHistory log(m.from, HISTORY_WRITE);
1368
// use a short message for AUTHREQ. FIXME: this is not a good way to do it
1369
if(msg.type == MESSAGE_AUTHREQ)
1370
m.text = QString(tr("<big>[System Message]</big><br>This user wants to subscribe to your presence."));
1375
void jabcon::queueUnread(UserListItem *item)
1377
MessageHistory log(item->jid, HISTORY_FLAG);
1379
bool inZone = FALSE;
1381
// collect unread received messages into a QPtrList, save in reverse order
1382
QPtrList<Message> unreadList;
1383
unreadList.setAutoDelete(TRUE);
1385
msg = log.readEntry();
1390
// skip sent messages
1391
if(msg->originLocal) {
1402
unreadList.insert(0, msg);
1407
if(unreadList.isEmpty())
1410
// now put them in the queue. don't log history
1411
QPtrListIterator<Message> it(unreadList);
1412
for(; (msg = it.current()); ++it)
1413
insertMessage(*msg, FALSE);
1418
void jabcon::flagAsRead(const Message &msg)
1420
// messages must be read in sequence, so this message must be earliest.
1421
// scan backwards until we find the last unread message.
1423
MessageHistory log(msg.from, HISTORY_FLAG);
1425
bool inZone = FALSE;
1429
//printf("reading entry\n");
1430
m = log.readCurrent();
1434
//printf("read entry\n");
1437
// skip sent messages
1438
if(m->originLocal) {
1440
//printf("local message\n");
1448
//printf("read message\n");
1453
//printf("unread message, going forward\n");
1458
//printf("num = %d\n", num);
1464
// go back one message
1465
//printf("stepping back\n");
1467
log.setFlagsCurrent("**-*");
1470
// mainwin triggers this when the user alters the status button
1471
void jabcon::statusMenuChanged(int x)
1473
// setting to some type of online status
1474
if(x != STATUS_OFFLINE) {
1479
if(x == STATUS_ONLINE && !option.askOnline) {
1484
if(lastStatusString.isEmpty())
1485
info.str = tr("I am away from my computer. Please leave a message.");
1487
info.str = lastStatusString; // default to old away message
1489
if(StatusSetDlg::getStatus(&info)) {
1491
lastStatusString = info.str;
1498
// setting to offline
1501
mainwin->setUsingSSL(FALSE);
1505
/*void jabcon::conn()
1507
if(!s->serv()->isActive()) {
1508
s->isDisconnecting = FALSE;
1509
s->onEventOnlineOk = FALSE;
1511
s->serv()->setHost(s->acc()->host, s->acc()->port);
1512
s->serv()->setAccount(s->acc()->user, s->acc()->pass, s->acc()->resource);
1513
s->serv()->login(loginAs.type, loginAs.str, s->acc()->priority);
1518
/*void jabcon::askLogin()
1520
pdb(DEBUG_JABCON, "askLogin\n");
1522
if(serv->isActive()) {
1523
QMessageBox::information(0, CAP(tr("Error")), tr("Please disconnect before changing the account."));
1527
// cancel any pending connection
1528
isDisconnecting = TRUE;
1534
info.user = acc.user;
1535
info.pass = acc.pass;
1536
info.host = acc.host;
1537
info.port = acc.port;
1538
info.resource = acc.resource;
1539
info.priority = acc.priority;
1540
info.savepw = opt_pass;
1541
info.autologin = opt_auto;
1542
info.use_ssl = opt_ssl;
1545
LoginDlg *login = new LoginDlg(&info, serv->isSSLSupported());
1546
int n = login->exec();
1549
if(info.user != acc.user) {
1550
// nuke the offline contact list (this will clear cvlist thru signal-chain)
1553
// there might be some "not in list" contacts left, so this gets them too
1557
opt_pass = info.savepw;
1558
opt_auto = info.autologin;
1559
opt_ssl = info.use_ssl;
1560
guestMode = info.guest;
1562
serv->setSSLEnabled(opt_ssl);
1567
pdb(DEBUG_JABCON, "Using GUESTMODE\n");
1571
acc.user = info.user;
1572
acc.pass = info.pass;
1573
acc.host = info.host;
1574
acc.port = info.port;
1575
acc.resource = info.resource;
1576
acc.priority = info.priority;
1580
statusMenuChanged(STATUS_ONLINE);
1590
void jabcon::delayedAskLogin()
1592
QTimer *t = new QTimer(this);
1593
connect(t, SIGNAL(timeout()), SLOT(askLogin()));
1598
void jabcon::askAddUser()
1600
if(s->localStatus == STATUS_OFFLINE) {
1601
QMessageBox::information(0, CAP(tr("Error")), tr("You must be connected to the server in order to do this."));
1605
AddUserDlg *w = AddUserDlg::find();
1611
// build groups list
1613
for(item = s->userlist.start(USERLIST_CONTACTS); item; item = s->userlist.next()) {
1614
if(item->group.isEmpty())
1617
// weed out duplicates
1618
if(qstringlistmatch(groups, item->group) == -1)
1619
groups.append(item->group);
1622
// build services list
1623
QStringList services, names;
1624
for(item = s->userlist.start(USERLIST_SERVICES); item; item = s->userlist.next()) {
1625
services += item->jid;
1626
if(item->nick.isEmpty())
1627
names += QString(item->jid);
1629
names += QString("%1 (%2)").arg(item->nick).arg(item->jid);
1632
AddUserDlg *w = new AddUserDlg(services, names, groups, s->localStatus);
1633
connect(w, SIGNAL(signalGetGateway(const QString &, QString *)), SLOT(slotGetIQGateway(const QString &, QString *)));
1634
connect(w, SIGNAL(signalSetGateway(const QString &, const QString &, QString *)), SLOT(slotSetIQGateway(const QString &, const QString &, QString *)));
1635
connect(w, SIGNAL(signalCancelTransaction(const QString &)), SLOT(slotCancelTransaction(const QString &)));
1636
connect(w, SIGNAL(add(const AddUserDlg::Info &)), SLOT(slotAddUser(const AddUserDlg::Info &)));
1637
connect(this, SIGNAL(emitLocalUpdate(const JabRosterEntry &)), w, SLOT(localUpdate(const JabRosterEntry &)));
1642
void jabcon::slotAddUser(const AddUserDlg::Info &info)
1644
actionAdd(info.jid, info.nick, info.group);
1647
/*void jabcon::servError(JabError *err)
1649
if(err->type == JABERR_CONNECT) {
1650
QMessageBox::critical(0, CAP(tr("Error")), QString(tr("There was an error communicating with the Jabber server.\nReason: %1")).arg(err->msg));
1651
//delayedAskLogin();
1653
else if(err->type == JABERR_AUTH) {
1654
QMessageBox::critical(0, CAP(tr("Error")), QString(tr("Authorization failed.\nReason: %1")).arg(err->msg));
1655
//delayedAskLogin();
1657
else if(err->type == JABERR_CREATE) {
1658
QMessageBox::critical(0, CAP(tr("Error")), QString(tr("Failed to create the new account.\nThe server gave this reason: \"%1\"")).arg(err->msg));
1659
//delayedAskLogin();
1661
else if(err->type == JABERR_DISCONNECT) {
1662
QMessageBox::critical(0, CAP(tr("Error")), tr("You have been disconnected from the Jabber server."));
1665
QMessageBox::critical(0, CAP(tr("Error")), QString(tr("An unknown error occurred.\nType: %1\nReason: %2")).arg(err->type).arg(err->msg));
1670
void jabcon::closeProgram()
1678
void jabcon::changeProfile()
1680
if(s->serv()->isActive()) {
1681
QMessageBox::information(0, CAP(tr("Error")), tr("Please disconnect before changing the profile."));
1688
void jabcon::doOptions()
1690
OptionsDlg *w = OptionsDlg::find();
1694
w = new OptionsDlg(option);
1695
connect(w, SIGNAL(applyOptions(const Options &)), SLOT(slotApplyOptions(const Options &)));
1700
void jabcon::slotApplyOptions(const Options &opt)
1702
QString oldiconset = option.iconset;
1706
if(option.iconset != oldiconset) {
1708
if(!loadPsiIconSet(option.iconset)) {
1709
QMessageBox::critical(0, tr("Error"), QString(tr("Unable to load the \"%1\" iconset.")).arg(option.iconset));
1710
option.iconset = oldiconset;
1711
loadPsiIconSet(option.iconset);
1715
mainwin->setAlwaysOnTop(option.alwaysOnTop);
1716
mainwin->setUseDock(option.useDock);
1718
emitOptionsUpdate();
1720
// save just the options
1722
pro.toFile(pathToProfileConfig(activeProfile));
1724
//QSettings settings;
1725
//settings.insertSearchPath(QSettings::Windows, "/Affinix");
1726
//settings.insertSearchPath(QSettings::Unix, g.pathHome);
1727
//configSaveOptions(settings);
1730
void jabcon::slotApplyAccounts()
1732
pro.acc.first() = *s->acc();
1733
pro.toFile(pathToProfileConfig(activeProfile));
1736
void jabcon::doManageServices()
1738
ServicesDlg *w = ServicesDlg::find();
1742
w = new ServicesDlg(s->localStatus, 0);
1743
connect(this, SIGNAL(emitLocalUpdate(const JabRosterEntry &)), w, SLOT(localUpdate(const JabRosterEntry &)));
1744
connect(w, SIGNAL(signalRefresh(QString *)), SLOT(slotGetServices(QString *)));
1745
connect(w, SIGNAL(signalSearch(const QString &, QString *)), SLOT(slotGetSearchForm(const QString &, QString *)));
1746
connect(w, SIGNAL(signalGetRegForm(const QString &, QString *)), SLOT(slotGetRegForm(const QString &, QString *)));
1747
connect(w, SIGNAL(signalCancelTransaction(const QString &)), SLOT(slotCancelTransaction(const QString &)));
1754
void jabcon::doManageAccounts()
1759
void jabcon::doFileSharing()
1761
OfferMainDlg *w = OfferMainDlg::find();
1765
w = new OfferMainDlg(0);
1766
connect(this, SIGNAL(emitNewOffer(FileServerItem *)), w, SLOT(slotNewOffer(FileServerItem *)));
1769
QPtrList<FileServerItem> list = fileserv->items();
1770
QPtrListIterator<FileServerItem> it(list);
1771
for(FileServerItem *fi; (fi = it.current()); ++it)
1778
#include<qfiledialog.h>
1779
void jabcon::actionOfferFile(const QString &jid)
1781
QString fname = QFileDialog::getOpenFileName(QDir::homeDirPath(), "(*.*)", 0, "", "Choose a file to offer");
1782
if(!fname.isEmpty())
1783
offerFile(fname, "A cool video", jid);
1786
void jabcon::actionOpenURL(const QString &jid)
1791
void jabcon::offerFile(const QString &fname, const QString &desc, const QString &jid)
1793
FileServerItem *i = fileserv->addFile(fname, desc, jid);
1795
printf("%s\n", QString("Offering: [%1]").arg(i->url).latin1());
1800
void jabcon::openAccountInfo()
1802
InfoDlg *w = InfoDlg::find(s->acc()->jid());
1806
/*Info *p = InfoBank::get(jid);
1812
w = new InfoDlg(INFODLG_USER, s->acc()->jid(), tmp, s->localStatus);
1813
connect(w, SIGNAL(signalGetVCard(const QString &, QString *)), SLOT(slotGetVCard(const QString &, QString *)));
1814
connect(w, SIGNAL(signalSetVCard(const VCard &, QString *)), SLOT(slotSetVCard(const VCard &, QString *)));
1815
connect(w, SIGNAL(signalCancelTransaction(const QString &)), SLOT(slotCancelTransaction(const QString &)));
1816
connect(this, SIGNAL(emitLocalUpdate(const JabRosterEntry &)), w, SLOT(localUpdate(const JabRosterEntry &)));
1823
void jabcon::slotGetServices(QString *id)
1825
JT_GetServices *j = new JT_GetServices(s->serv()->ioUser(), "");
1826
connect(j, SIGNAL(finished(JabTask *)), SLOT(slotJTDone(JabTask *)));
1831
void jabcon::slotJTDone(JabTask *t)
1833
//printf("slotJTDone\n");
1834
if(t->isA("JT_GetServices")) {
1835
JT_GetServices *j = (JT_GetServices *)t;
1837
slotGetServicesResponse(&j->services);
1840
ServicesDlg *w = ServicesDlg::find();
1845
else if(t->isA("JT_VCard")) {
1846
JT_VCard *j = (JT_VCard *)t;
1847
QString jid = j->jid;
1850
slotGetVCardResponse(jid, &j->vcard);
1853
slotGetVCardResponse(jid, 0);
1857
slotSetVCardResponse(j->success());
1860
else if(t->isA("JT_RegForm")) {
1861
JT_RegForm *j = (JT_RegForm *)t;
1864
slotGetRegFormResponse(j->form);
1867
ServicesDlg *w = ServicesDlg::find();
1873
slotPutRegFormResponse(j->jid, j->success(), j->errorString());
1876
else if(t->isA("JT_Search")) {
1877
JT_Search *j = (JT_Search *)t;
1880
slotGetSearchFormResponse(j->jid, &j->form);
1882
slotGetSearchFormResponse(j->jid, 0);
1886
slotPutSearchFormResponse(j->jid, &j->roster);
1888
slotPutSearchFormResponse(j->jid, 0);
1891
else if(t->isA("JT_Gateway")) {
1892
JT_Gateway *j = (JT_Gateway *)t;
1893
AddUserDlg *w = AddUserDlg::find();
1896
w->slotGetGatewayResponse(j->id(), j->success(), j->desc);
1898
w->slotSetGatewayResponse(j->id(), j->success(), j->prompt);
1905
void jabcon::slotGetServicesResponse(JabRoster *services)
1907
ServicesDlg *w = ServicesDlg::find();
1909
w->loadSuccess(services);
1912
void jabcon::slotGetRegForm(const QString &service, QString *id)
1914
// do we already have this open?
1915
RegistrationDlg *r = RegistrationDlg::find(service);
1917
// loaded successfully
1918
ServicesDlg *w = ServicesDlg::find();
1920
w->loadFormSuccess();
1926
JT_RegForm *j = new JT_RegForm(s->serv()->ioUser());
1927
connect(j, SIGNAL(finished(JabTask *)), SLOT(slotJTDone(JabTask *)));
1933
void jabcon::slotGetRegFormResponse(const JabForm &form)
1935
ServicesDlg *w = ServicesDlg::find();
1937
w->loadFormSuccess();
1939
RegistrationDlg *r = new RegistrationDlg(form);
1940
connect(this, SIGNAL(emitLocalUpdate(const JabRosterEntry &)), r, SLOT(localUpdate(const JabRosterEntry &)));
1941
connect(r, SIGNAL(signalSubmitForm(const JabForm &, QString *)), this, SLOT(slotPutRegForm(const JabForm &, QString *)));
1946
void jabcon::slotPutRegForm(const JabForm &form, QString *id)
1948
pdb(DEBUG_JABCON, "submitting form\n");
1950
JT_RegForm *j = new JT_RegForm(s->serv()->ioUser());
1951
connect(j, SIGNAL(finished(JabTask *)), SLOT(slotJTDone(JabTask *)));
1957
void jabcon::slotPutRegFormResponse(const QString &service, bool ok, const QString &err)
1959
pdb(DEBUG_JABCON, QString("Registration result from %1: %2\n").arg(service).arg(ok ? "Success" : "Failed"));
1961
RegistrationDlg *r = RegistrationDlg::find(service);
1963
r->putRegFormResponse(ok, err);
1966
void jabcon::slotGetVCard(const QString &jid, QString *id)
1968
JT_VCard *j = new JT_VCard(s->serv()->ioUser());
1969
connect(j, SIGNAL(finished(JabTask *)), SLOT(slotJTDone(JabTask *)));
1975
void jabcon::slotGetVCardResponse(const QString &jid, VCard *vcard)
1983
// rename the contact in list [pushinfo]
1984
//UserListItem *i = userlist.findAnyByJid(jid);
1985
//if(i && !info->field[vNickname].isEmpty())
1986
// userRename(i, info->field[vNickname]);
1989
InfoDlg *w = InfoDlg::find(jid);
1994
w->updateVCard(*vcard);
2000
void jabcon::slotSetVCard(const VCard &vcard, QString *id)
2002
JT_VCard *j = new JT_VCard(s->serv()->ioUser());
2003
connect(j, SIGNAL(finished(JabTask *)), SLOT(slotJTDone(JabTask *)));
2010
void jabcon::slotSetVCardResponse(bool x)
2012
InfoDlg *w = InfoDlg::find(s->acc()->jid());
2019
void jabcon::slotGetSearchForm(const QString &service, QString *id)
2021
// do we already have this open?
2022
SearchDlg *sd = SearchDlg::find(service);
2024
// loaded successfully
2025
ServicesDlg *w = ServicesDlg::find();
2027
w->loadFormSuccess();
2033
JT_Search *j = new JT_Search(s->serv()->ioUser());
2034
connect(j, SIGNAL(finished(JabTask *)), SLOT(slotJTDone(JabTask *)));
2040
void jabcon::slotGetSearchFormResponse(const QString &service, JabForm *p)
2042
ServicesDlg *w = ServicesDlg::find();
2045
w->loadFormSuccess();
2047
SearchDlg *sd = new SearchDlg(service, *p, s->localStatus);
2048
connect(this, SIGNAL(emitLocalUpdate(const JabRosterEntry &)), sd, SLOT(localUpdate(const JabRosterEntry &)));
2049
connect(sd, SIGNAL(signalSubmitForm(const JabForm &, QString *)), this, SLOT(slotPutSearchForm(const JabForm &, QString *)));
2050
connect(sd, SIGNAL(signalCancelTransaction(const QString &)), SLOT(slotCancelTransaction(const QString &)));
2051
connect(sd, SIGNAL(aInfo(const QString &)), SLOT(actionInfo(const QString &)));
2052
connect(sd, SIGNAL(aAdd(const QString &, const QString &, const QString &)), SLOT(actionAdd(const QString &, const QString &, const QString &)));
2060
void jabcon::slotPutSearchForm(const JabForm &form, QString *id)
2062
pdb(DEBUG_JABCON, "submitting search form\n");
2064
JT_Search *j = new JT_Search(s->serv()->ioUser());
2065
connect(j, SIGNAL(finished(JabTask *)), SLOT(slotJTDone(JabTask *)));
2071
void jabcon::slotPutSearchFormResponse(const QString &service, JabRoster *p)
2073
pdb(DEBUG_JABCON, QString("Search result from %1: %2\n").arg(service).arg(p ? "Success" : "Failed"));
2075
SearchDlg *s = SearchDlg::find(service);
2077
s->putSearchFormResponse(p);
2081
void jabcon::slotGetIQGateway(const QString &service, QString *id)
2083
JT_Gateway *j = new JT_Gateway(s->serv()->ioUser());
2084
connect(j, SIGNAL(finished(JabTask *)), SLOT(slotJTDone(JabTask *)));
2090
void jabcon::slotSetIQGateway(const QString &service, const QString &prompt, QString *id)
2092
JT_Gateway *j = new JT_Gateway(s->serv()->ioUser());
2093
connect(j, SIGNAL(finished(JabTask *)), SLOT(slotJTDone(JabTask *)));
2094
j->set(service, prompt);
2100
void jabcon::slotCancelTransaction(const QString &id)
2102
pdb(DEBUG_JABCON, QString("Cancelling transaction: [%1]\n").arg(id));
2103
s->serv()->cancelTransaction(id);
2107
void jabcon::slotCheckVCard(JabTask *t)
2109
JT_VCard *j = (JT_VCard *)t;
2110
if(! (j->success() && !j->vcard.isIncomplete()) )
2115
void jabcon::doOnEvent(const QString &str)
2125
if(option.noAwaySound && (s->localStatus == STATUS_AWAY || s->localStatus == STATUS_XA || s->localStatus == STATUS_DND))
2128
#if defined(Q_WS_WIN) || defined(Q_WS_MAC)
2131
if(!option.player.isEmpty()) {
2133
args += option.player;
2141
void jabcon::enableOnEventOnline()
2143
s->onEventOnlineOk = TRUE;
2146
void jabcon::recvNextEvent()
2148
EventItem *ei = events.peekNext();
2151
UserListItem *i = s->userlist.findAnyByJid(ei->jid);
2159
/****************************************************************************
2161
****************************************************************************/
2162
EventQueue::EventQueue()
2163
:QPtrList<EventItem>()
2167
int EventQueue::count(const QString &jid)
2171
for(EventItem *i = last(); i; i = prev()) {
2179
void EventQueue::enqueue(EventItem *i)
2184
EventItem *EventQueue::dequeue(const QString &jid)
2189
for(EventItem *i = last(); i; i = prev()) {
2198
EventItem *EventQueue::peek(const QString &jid)
2203
for(EventItem *i = last(); i; i = prev()) {
2211
EventItem *EventQueue::dequeueNext()
2216
EventItem *i = last();
2222
EventItem *EventQueue::peekNext()
2227
bool EventQueue::hasChats(const QString &jid)
2232
for(EventItem *i = last(); i; i = prev()) {
2234
if(i->msg.type == MESSAGE_CHAT)
2242
// this function extracts all chats from the queue, and returns a list of queue positions
2243
void EventQueue::extractChats(const QString &jid, QPtrList<Message> *list, QValueList<int> *pos)
2249
for(EventItem *i = last(); (i = current());) {
2251
if(i->msg.type == MESSAGE_CHAT) {
2252
Message *m = new Message(i->msg);
2256
bool isLast = (i == getLast());
2269
// this function removes all events associated with the input jid
2270
void EventQueue::removeAll(const QString &jid)
2272
for(EventItem *i = first(); (i = current());) {