~ubuntu-branches/ubuntu/dapper/psi/dapper

« back to all changes in this revision

Viewing changes to src/contactview.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jan Niehusmann
  • Date: 2002-04-19 02:28:44 UTC
  • Revision ID: james.westby@ubuntu.com-20020419022844-za7xgai5qyfd9xv6
Tags: upstream-0.8.5
ImportĀ upstreamĀ versionĀ 0.8.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
** contactview.cpp - an Licq-like contact list
 
3
** Copyright (C) 2001, 2002  Justin Karneges
 
4
**
 
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.
 
9
**
 
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.
 
14
**
 
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.
 
18
**
 
19
****************************************************************************/
 
20
 
 
21
#include<qpopupmenu.h>
 
22
#include<qmessagebox.h>
 
23
#include<qinputdialog.h>
 
24
#include<qiconset.h>
 
25
#include<qheader.h>
 
26
#include<qpalette.h>
 
27
#include<qdragobject.h>
 
28
#include<qapplication.h>
 
29
#include<qdropsite.h>
 
30
 
 
31
#include"contactview.h"
 
32
#include"common.h"
 
33
#include"userlist.h"
 
34
 
 
35
 
 
36
//*******************************************************
 
37
//  ContactView
 
38
//*******************************************************
 
39
ContactView::ContactView(QWidget *parent, const char *name)
 
40
:QListView(parent, name), QToolTip(viewport())
 
41
{
 
42
        // setup the QListView
 
43
        setAllColumnsShowFocus(TRUE);
 
44
        setHScrollBarMode(AlwaysOff);
 
45
        setMinimumSize(96,64);
 
46
        //setRootIsDecorated(TRUE);
 
47
        setTreeStepSize(4);
 
48
        setSorting(-1, TRUE);
 
49
        setDefaultRenameAction(QListView::Accept);
 
50
        //setSelectionMode(QListView::Extended);
 
51
 
 
52
        // create columns and hide the header
 
53
        addColumn("Contact");
 
54
        header()->hide();
 
55
        setResizeMode(QListView::LastColumn);
 
56
        setShowToolTips(FALSE);
 
57
 
 
58
        // initialize the alerting stuff
 
59
        QTimer *t = new QTimer(this);
 
60
        connect(t, SIGNAL(timeout()), SLOT(animAlert()));
 
61
        t->start(120);
 
62
 
 
63
        // catch signals
 
64
        connect(this, SIGNAL(itemRenamed(QListViewItem *, int, const QString &)), SLOT(qlv_itemRenamed(QListViewItem *, int, const QString &)));
 
65
        connect(this, SIGNAL(mouseButtonPressed(int, QListViewItem *, const QPoint &, int)),SLOT(qlv_singleclick(int, QListViewItem *, const QPoint &, int)) );
 
66
        connect(this, SIGNAL(doubleClicked(QListViewItem *)),SLOT(qlv_doubleclick(QListViewItem *)) );
 
67
 
 
68
        v_showOffline = TRUE;
 
69
        v_showAway = TRUE;
 
70
        v_showAgents = TRUE;
 
71
 
 
72
        lcto_active = FALSE;
 
73
 
 
74
        // sorting
 
75
        sortTimer = new QTimer(this);
 
76
        connect(sortTimer, SIGNAL(timeout()), SLOT(actualContactSort()));
 
77
 
 
78
        // actions
 
79
        qa_send = new QAction("", tr("Send &message"), QListView::CTRL+QListView::Key_M, this);
 
80
        connect(qa_send, SIGNAL(activated()), SLOT(doSendMessage()));
 
81
        qa_ren = new QAction("", tr("Re&name"), QListView::Key_F2, this);
 
82
        connect(qa_ren, SIGNAL(activated()), SLOT(doRename()));
 
83
        qa_chat = new QAction("", tr("Open &chat window"), QListView::CTRL+QListView::Key_C, this);
 
84
        connect(qa_chat, SIGNAL(activated()), SLOT(doOpenChat()));
 
85
        qa_hist = new QAction("", tr("&History"), QListView::CTRL+QListView::Key_H, this);
 
86
        connect(qa_hist, SIGNAL(activated()), SLOT(doHistory()));
 
87
        qa_logon = new QAction("", tr("&Log on"), QListView::CTRL+QListView::Key_L, this);
 
88
        connect(qa_logon, SIGNAL(activated()), SLOT(doLogon()));
 
89
        qa_recv = new QAction("", tr("&Receive incoming event"), QListView::CTRL+QListView::Key_R, this);
 
90
        connect(qa_recv, SIGNAL(activated()), SLOT(doRecvEvent()));
 
91
        qa_rem = new QAction("", tr("Rem&ove"), QListView::Key_Delete, this);
 
92
        connect(qa_rem, SIGNAL(activated()), SLOT(doRemove()));
 
93
 
 
94
        optionsUpdate();
 
95
 
 
96
        setAcceptDrops(TRUE);
 
97
}
 
98
 
 
99
ContactView::~ContactView()
 
100
{
 
101
        pdb(DEBUG_CV, "ContactView::~ContactView()\n");
 
102
 
 
103
        // delete the profiles
 
104
        profiles.setAutoDelete(TRUE);
 
105
        profiles.clear();
 
106
}
 
107
 
 
108
void ContactView::resizeEvent(QResizeEvent *e)
 
109
{
 
110
        QListView::resizeEvent(e);
 
111
}
 
112
 
 
113
void ContactView::keyPressEvent(QKeyEvent *e)
 
114
{
 
115
        if(e->key() == QListView::Key_Enter || e->key() == QListView::Key_Return)
 
116
                doEnter();
 
117
        else if(e->key() == QListView::Key_Space)
 
118
                doContext();
 
119
        else
 
120
                QListView::keyPressEvent(e);
 
121
}
 
122
 
 
123
void ContactView::viewportMousePressEvent(QMouseEvent *e)
 
124
{
 
125
        QListView::viewportMousePressEvent(e);
 
126
        if(e->button() == QListView::LeftButton)
 
127
                mousePressPos = e->pos();
 
128
}
 
129
 
 
130
void ContactView::viewportMouseMoveEvent(QMouseEvent *e)
 
131
{
 
132
        ContactViewItem *i = LVI2CVI(selectedItem());
 
133
        if(!i)
 
134
                return;
 
135
        if(i->type() != CV_CONTACT)
 
136
                return;
 
137
 
 
138
        if((e->state() & QListView::LeftButton) && !mousePressPos.isNull() && (QPoint(e->pos() - mousePressPos).manhattanLength() > 8)) {
 
139
                QDragObject *d = new QTextDrag(i->jid(), this);
 
140
                d->setPixmap(*pix_online, QPoint(8,8));
 
141
                d->dragCopy();
 
142
        }
 
143
}
 
144
 
 
145
void ContactView::dragEnterEvent(QDragEnterEvent *e)
 
146
{
 
147
        QString text;
 
148
 
 
149
        // only accept text jids that are in the contact list
 
150
        if(QTextDrag::decode(e, text)) {
 
151
                if(defPro()->findCVIByJid(text)) {
 
152
                        e->accept(TRUE);
 
153
                        return;
 
154
                }
 
155
        }
 
156
 
 
157
        e->accept(FALSE);
 
158
}
 
159
 
 
160
void ContactView::dropEvent(QDropEvent *e)
 
161
{
 
162
        ContactViewItem *i = LVI2CVI(itemAt(e->pos()));
 
163
        if(!i)
 
164
                return;
 
165
 
 
166
        ContactViewItem *dest;
 
167
        if(i->type() == CV_GROUP)
 
168
                dest = i;
 
169
        else
 
170
                dest = LVI2CVI(i->parent());
 
171
 
 
172
        QString text;
 
173
 
 
174
        if(QTextDrag::decode(e, text)) {
 
175
                ContactViewItem *src = defPro()->findCVIByJid(text);
 
176
                if(!src)
 
177
                        return;
 
178
                if(src == i)
 
179
                        return;
 
180
                if(src->isAgent() || !src->inList())
 
181
                        return;
 
182
 
 
183
                QString newgroup;
 
184
                if(dest->groupType() == CVG_USER)
 
185
                        newgroup = dest->groupName();
 
186
                else
 
187
                        newgroup = "";
 
188
 
 
189
                if(src->group() == newgroup.mid(0))
 
190
                        return;
 
191
 
 
192
                pdb(DEBUG_CV, QString("dragdrop: moving [%1] to group [%2] (oldgroup=[%3])\n").arg(text).arg(newgroup).arg(src->group()));
 
193
                if(newgroup != src->group()) {
 
194
                        defPro()->scGroupChange(src->jid(), newgroup);
 
195
                        //actionGroupChange(src->jid(), newgroup);
 
196
                }
 
197
        }
 
198
}
 
199
 
 
200
/*QDragObject *ContactView::dragObject()
 
201
{
 
202
        ContactViewItem *i = LVI2CVI(selectedItem());
 
203
        if(!i)
 
204
                return 0;
 
205
 
 
206
        QDragObject *d = new QTextDrag(i->jid(), this);
 
207
        d->setPixmap(*pix_online, QPoint(8,8));
 
208
        //d->dragCopy();
 
209
        return d;
 
210
}*/
 
211
 
 
212
void ContactView::sort()
 
213
{
 
214
        setSorting(0, TRUE);
 
215
        QListView::sort();
 
216
        setSorting(-1, TRUE);
 
217
}
 
218
 
 
219
void ContactView::maybeTip(const QPoint &pos)
 
220
{
 
221
        ContactViewItem *i = LVI2CVI(itemAt(pos));
 
222
        if(!i)
 
223
                return;
 
224
        if(i->type() != CV_CONTACT)
 
225
                return;
 
226
 
 
227
        QRect r(itemRect(i));
 
228
 
 
229
        QString str = QString("<qt>");
 
230
        str += QString("<nobr>%1: %2</nobr>").arg(i->nick()).arg(status2txt(i->status()));
 
231
        if(i->jid() != i->nick())
 
232
                str += QString("<br>[%1]").arg(i->jid());
 
233
 
 
234
        // subscription
 
235
        str += QString("<br><nobr>") + QString(tr("Subscription") + ": %1").arg(i->sub()) + "</nobr>";
 
236
 
 
237
        // resources
 
238
        if(!i->resList().isEmpty()) {
 
239
                QString resources;
 
240
                int n = 0;
 
241
                JabResource *pr = i->resList().priority();
 
242
                QPtrListIterator<JabResource> it(i->resList());
 
243
                JabResource *r;
 
244
                for(; (r = it.current()); ++it) {
 
245
                        // skip 'blank' resources (non-jabber contacts)
 
246
                        if(r->name.isEmpty())
 
247
                                continue;
 
248
 
 
249
                        if(n > 0)
 
250
                                resources += ", ";
 
251
 
 
252
                        // priority?
 
253
                        if(r == pr)
 
254
                                resources += "*";
 
255
                        resources += r->name;
 
256
                        ++n;
 
257
                }
 
258
 
 
259
                if(!resources.isEmpty())
 
260
                        str += QString("<br><nobr>") + QString(tr("Resource(s)") + " : %1").arg(resources) + "</nobr>";
 
261
 
 
262
                if(pr->timeStamp.isValid()) {
 
263
                        QString d = pr->timeStamp.toString();
 
264
                        str += QString("<br><nobr>") + tr("Last Status") + " @ " + d + "</nobr>";
 
265
                }
 
266
 
 
267
                if(!pr->songTitle.isEmpty())
 
268
                        str += QString("<br><nobr>") + QString(tr("Listening to") + ": %1").arg(clipStatus(pr->songTitle, 200, 1)) + "</nobr>";
 
269
        }
 
270
 
 
271
        if(!i->statusString().isEmpty()) {
 
272
                QString head = tr("Status Message");
 
273
                str += QString("<br><nobr><u>%1</u></nobr><br>%2").arg(head).arg(plain2rich(clipStatus(i->statusString(), 200, 12)));
 
274
        }
 
275
        str += "</qt>";
 
276
 
 
277
        tip(r, str);
 
278
}
 
279
 
 
280
void ContactView::qlv_singleclick(int button, QListViewItem *i, const QPoint &pos, int c)
 
281
{
 
282
        lcto_active = FALSE;
 
283
        QToolTip::hide();
 
284
 
 
285
        if(!i)
 
286
                return;
 
287
 
 
288
        ContactViewItem *item = LVI2CVI(i);
 
289
        setSelected(item, TRUE);
 
290
 
 
291
        if(option.useleft) {
 
292
                if(button == QListView::LeftButton) {
 
293
                        if(option.singleclick) {
 
294
                                qlv_contextPopup(i, pos, c);
 
295
                        }
 
296
                        else {
 
297
                                lcto_active = TRUE;
 
298
                                lcto_pos = pos;
 
299
                                lcto_item = i;
 
300
                                QTimer::singleShot(QApplication::doubleClickInterval()/2, this, SLOT(leftClickTimeOut()));
 
301
                        }
 
302
                }
 
303
                else if(option.singleclick && button == QListView::RightButton) {
 
304
                        if(item->type() == CV_CONTACT)
 
305
                                owner(item)->scActionDefault(item);
 
306
                }
 
307
        }
 
308
        else {
 
309
                if(button == QListView::RightButton) {
 
310
                        qlv_contextPopup(i, pos, c);
 
311
                }
 
312
                else if(button == QListView::LeftButton && option.singleclick) {
 
313
                        if(item->type() == CV_CONTACT)
 
314
                                owner(item)->scActionDefault(item);
 
315
                }
 
316
        }
 
317
}
 
318
 
 
319
void ContactView::qlv_doubleclick(QListViewItem *i)
 
320
{
 
321
        lcto_active = FALSE;
 
322
 
 
323
        if(!i)
 
324
                return;
 
325
 
 
326
        if(option.singleclick)
 
327
                return;
 
328
 
 
329
        ContactViewItem *item = LVI2CVI(i);
 
330
 
 
331
        if(item->type() == CV_CONTACT)
 
332
                owner(item)->scActionDefault(item);
 
333
}
 
334
 
 
335
void ContactView::leftClickTimeOut()
 
336
{
 
337
        if(lcto_active) {
 
338
                QToolTip::hide();
 
339
                qlv_contextPopup(lcto_item, lcto_pos, 0);
 
340
                lcto_active = FALSE;
 
341
        }
 
342
}
 
343
 
 
344
 
 
345
// Profile related functions
 
346
ContactProfile *ContactView::createProfile(const QString &jid, const QString &name, bool unique)
 
347
{
 
348
        ContactProfile *pro = findProfile(jid);
 
349
        if(pro)
 
350
                removeProfile(pro);
 
351
 
 
352
        pro = new ContactProfile(jid, name, STATUS_OFFLINE, unique, this);
 
353
        profiles.append(pro);
 
354
 
 
355
        return pro;
 
356
}
 
357
 
 
358
ContactProfile *ContactView::findProfile(const QString &jid)
 
359
{
 
360
        QPtrListIterator<ContactProfile> it(profiles);
 
361
        for(ContactProfile *p; (p = it.current()); ++it) {
 
362
                if(jidcmp(p->jid, jid))
 
363
                        return p;
 
364
        }
 
365
        return 0;
 
366
}
 
367
 
 
368
void ContactView::removeProfile(const QString &jid)
 
369
{
 
370
        ContactProfile *pro = findProfile(jid);
 
371
        if(pro)
 
372
                removeProfile(pro);
 
373
}
 
374
 
 
375
void ContactView::removeProfile(ContactProfile *p)
 
376
{
 
377
        profiles.remove(p);
 
378
}
 
379
 
 
380
ContactProfile *ContactView::defPro()
 
381
{
 
382
        return profiles.first();
 
383
}
 
384
 
 
385
// which profile likely deals with this item?
 
386
ContactProfile *ContactView::owner(ContactViewItem *i)
 
387
{
 
388
        QPtrListIterator<ContactProfile> it(profiles);
 
389
        for(ContactProfile *p; (p = it.current()); ++it) {
 
390
                if(p->isMine(i))
 
391
                        return p;
 
392
        }
 
393
        return 0;
 
394
}
 
395
 
 
396
void ContactView::ensureVisible(ContactViewItem *item)
 
397
{
 
398
        // ensure the item is visible
 
399
        ContactViewItem *group_item = LVI2CVI(item->parent());
 
400
 
 
401
        // if the group is a user group, go up a step
 
402
        if(group_item && group_item->groupType() == CVG_USER)
 
403
                group_item = LVI2CVI(group_item->parent());
 
404
 
 
405
        if(group_item && !group_item->isVisible()) {
 
406
                if(group_item->groupType() == CVG_OFFLINE)
 
407
                        setShowOffline(TRUE);
 
408
                if(group_item->groupType() == CVG_AGENTS)
 
409
                        setShowAgents(TRUE);
 
410
        }
 
411
        if(!isShowAway() && item->isAway()) {
 
412
                setShowAway(TRUE);
 
413
        }
 
414
 
 
415
        ensureItemVisible(item);
 
416
}
 
417
 
 
418
void ContactView::animAlert()
 
419
{
 
420
        // are any of the items animating?
 
421
        QListViewItemIterator it(this);
 
422
        ContactViewItem *item;
 
423
 
 
424
        for(; it.current() ; ++it) {
 
425
                item = LVI2CVI(it.current());
 
426
                if(item->isAlert())
 
427
                        item->animate();
 
428
                if(item->isAnimateNick())
 
429
                        item->animateNick();
 
430
        }
 
431
}
 
432
 
 
433
void ContactView::clear()
 
434
{
 
435
        profiles.setAutoDelete(TRUE);
 
436
        profiles.clear();
 
437
        profiles.setAutoDelete(FALSE);
 
438
}
 
439
 
 
440
// right-click context menu
 
441
void ContactView::qlv_contextPopup(QListViewItem *xi, const QPoint &pos, int)
 
442
{
 
443
        ContactViewItem *i = LVI2CVI(xi);
 
444
        if(!i)
 
445
                return;
 
446
 
 
447
        owner(i)->doContextMenu(i, pos);
 
448
}
 
449
 
 
450
void ContactView::doRecvEvent()
 
451
{
 
452
        ContactViewItem *i = LVI2CVI(selectedItem());
 
453
        if(!i)
 
454
                return;
 
455
 
 
456
        if(i->type() == CV_CONTACT)
 
457
                owner(i)->scRecvEvent(i);
 
458
}
 
459
 
 
460
void ContactView::doRename()
 
461
{
 
462
        ContactViewItem *i = LVI2CVI(selectedItem());
 
463
        if(!i)
 
464
                return;
 
465
 
 
466
        owner(i)->scRename(i);
 
467
}
 
468
 
 
469
void ContactView::doEnter()
 
470
{
 
471
        ContactViewItem *i = LVI2CVI(selectedItem());
 
472
        if(!i)
 
473
                return;
 
474
 
 
475
        if(i->type() == CV_CONTACT)
 
476
                owner(i)->scActionDefault(i);
 
477
}
 
478
 
 
479
void ContactView::doContext()
 
480
{
 
481
        ContactViewItem *i = LVI2CVI(selectedItem());
 
482
        if(!i)
 
483
                return;
 
484
        ensureItemVisible(i);
 
485
 
 
486
        if(i->type() == CV_GROUP)
 
487
                setOpen(i, !i->isOpen());
 
488
        else
 
489
                qlv_contextPopup(i, viewport()->mapToGlobal(QPoint(32, itemPos(i))), 0);
 
490
}
 
491
 
 
492
void ContactView::doSendMessage()
 
493
{
 
494
        ContactViewItem *i = LVI2CVI(selectedItem());
 
495
        if(!i)
 
496
                return;
 
497
 
 
498
        owner(i)->scSendMessage(i);
 
499
}
 
500
 
 
501
void ContactView::doOpenChat()
 
502
{
 
503
        ContactViewItem *i = LVI2CVI(selectedItem());
 
504
        if(!i)
 
505
                return;
 
506
 
 
507
        owner(i)->scOpenChat(i);
 
508
}
 
509
 
 
510
void ContactView::doHistory()
 
511
{
 
512
        ContactViewItem *i = LVI2CVI(selectedItem());
 
513
        if(!i)
 
514
                return;
 
515
 
 
516
        owner(i)->scHistory(i);
 
517
}
 
518
 
 
519
void ContactView::doLogon()
 
520
{
 
521
        ContactViewItem *i = LVI2CVI(selectedItem());
 
522
        if(!i)
 
523
                return;
 
524
        if(i->type() != CV_CONTACT)
 
525
                return;
 
526
 
 
527
        if(i->isAgent())
 
528
                owner(i)->scAgentSetStatus(i, STATUS_ONLINE);
 
529
}
 
530
 
 
531
void ContactView::doRemove()
 
532
{
 
533
        ContactViewItem *i = LVI2CVI(selectedItem());
 
534
        if(!i)
 
535
                return;
 
536
 
 
537
        owner(i)->scRemove(i);
 
538
}
 
539
 
 
540
void ContactView::qlv_itemRenamed(QListViewItem *xi, int, const QString &text)
 
541
{
 
542
        ContactViewItem *i = LVI2CVI(xi);
 
543
 
 
544
        owner(i)->doItemRenamed(i, text);
 
545
}
 
546
 
 
547
void ContactView::setShowOffline(bool x)
 
548
{
 
549
        bool oldstate = v_showOffline;
 
550
        v_showOffline = x;
 
551
 
 
552
        if(v_showOffline != oldstate) {
 
553
                showOffline(v_showOffline);
 
554
 
 
555
                // set the visibility of all the offline groups
 
556
                QPtrListIterator<ContactProfile> it(profiles);
 
557
                for(ContactProfile *p; (p = it.current()); ++it) {
 
558
                        ContactViewItem *group_item = p->checkGroup(CVG_OFFLINE);
 
559
                        if(group_item)
 
560
                                group_item->setVisible(v_showOffline);
 
561
                }
 
562
        }
 
563
}
 
564
 
 
565
void ContactView::setShowAway(bool x)
 
566
{
 
567
        bool oldstate = v_showAway;
 
568
        v_showAway = x;
 
569
 
 
570
        if(v_showAway != oldstate) {
 
571
                showAway(v_showAway);
 
572
 
 
573
                // we want to modify _all_ profiles, so just burn down the list
 
574
                QListViewItemIterator it(this);
 
575
                ContactViewItem *item;
 
576
                for(; it.current() ; ++it) {
 
577
                        item = LVI2CVI(it.current());
 
578
                        if(item->type() != CV_CONTACT)
 
579
                                continue;
 
580
 
 
581
                        if(!item->isAgent())
 
582
                                setVisibility(item);
 
583
                }
 
584
        }
 
585
}
 
586
 
 
587
void ContactView::setShowAgents(bool x)
 
588
{
 
589
        bool oldstate = v_showAgents;
 
590
        v_showAgents = x;
 
591
 
 
592
        if(v_showAgents != oldstate) {
 
593
                showAgents(v_showAgents);
 
594
 
 
595
                // set the visibility of all the offline groups
 
596
                QPtrListIterator<ContactProfile> it(profiles);
 
597
                for(ContactProfile *p; (p = it.current()); ++it) {
 
598
                        ContactViewItem *group_item = p->checkGroup(CVG_AGENTS);
 
599
                        if(group_item)
 
600
                                group_item->setVisible(v_showAgents);
 
601
                }
 
602
        }
 
603
}
 
604
 
 
605
void ContactView::optionsUpdate()
 
606
{
 
607
        // set the font
 
608
        QFont f;
 
609
        f.fromString(option.font[fRoster]);
 
610
        QListView::setFont(f);
 
611
 
 
612
        // set the text and background colors
 
613
        QPalette mypal = QListView::palette();
 
614
        mypal.setColor(QColorGroup::Text, option.color[cOnline]);
 
615
        mypal.setColor(QColorGroup::Base, option.color[cListBack]);
 
616
        QListView::setPalette(mypal);
 
617
 
 
618
        // reload the icons
 
619
        QListViewItemIterator it(this);
 
620
        ContactViewItem *item;
 
621
        for(; it.current() ; ++it) {
 
622
                item = LVI2CVI(it.current());
 
623
                item->optionsUpdate();
 
624
        }
 
625
 
 
626
        update();
 
627
}
 
628
 
 
629
void ContactView::setVisibility(ContactViewItem *i)
 
630
{
 
631
        ContactViewItem *par = LVI2CVI(i->parent());
 
632
        if(par && !par->isVisible())
 
633
                return;
 
634
 
 
635
        if(!isShowAway() && i->isAway())
 
636
                i->setVisible(FALSE);
 
637
        else
 
638
                i->setVisible(TRUE);
 
639
}
 
640
 
 
641
void ContactView::deferredContactSort()
 
642
{
 
643
        sortTimer->start(500, TRUE);
 
644
}
 
645
 
 
646
void ContactView::actualContactSort()
 
647
{
 
648
        QListViewItemIterator it(this);
 
649
        ContactViewItem *item;
 
650
 
 
651
        for(; it.current() ; ++it) {
 
652
                item = LVI2CVI(it.current());
 
653
                if(item->type() != CV_GROUP)
 
654
                        continue;
 
655
 
 
656
                if(item->needSorting)
 
657
                        item->sort();
 
658
 
 
659
                owner(item)->updateGroupInfo(item);
 
660
        }
 
661
 
 
662
        sort();
 
663
}
 
664
 
 
665
 
 
666
//*******************************************************
 
667
//  ContactViewItem
 
668
//*******************************************************
 
669
ContactViewItem::ContactViewItem(const QString &xgroupname, int xgrouptype, QListView *parent)
 
670
:QListViewItem(parent)
 
671
{
 
672
        v_type = CV_GROUP;
 
673
        v_groupName = xgroupname;
 
674
        v_groupType = xgrouptype;
 
675
        v_isAlert = FALSE;
 
676
        v_isAnimateNick = FALSE;
 
677
 
 
678
        resetGroupName();
 
679
        setOpen(TRUE);
 
680
 
 
681
        // sorting stuff
 
682
        needSorting = FALSE;
 
683
 
 
684
        //if(xgrouptype == CVG_USER)
 
685
                //setRenameEnabled(1, TRUE);
 
686
 
 
687
        drawGroupIcon();
 
688
 
 
689
        //setDropEnabled(TRUE);
 
690
}
 
691
 
 
692
ContactViewItem::ContactViewItem(const QString &xgroupname, int xgrouptype, QListViewItem *parent)
 
693
:QListViewItem(parent)
 
694
{
 
695
        if(!parent->isVisible())
 
696
                setVisible(FALSE);
 
697
 
 
698
        v_type = CV_GROUP;
 
699
        v_groupName = xgroupname;
 
700
        v_groupType = xgrouptype;
 
701
        v_isAlert = FALSE;
 
702
        v_isAnimateNick = FALSE;
 
703
 
 
704
        resetGroupName();
 
705
        setOpen(TRUE);
 
706
 
 
707
        // sorting stuff
 
708
        needSorting = FALSE;
 
709
 
 
710
        //if(xgrouptype == CVG_USER)
 
711
                //setRenameEnabled(1, TRUE);
 
712
 
 
713
        drawGroupIcon();
 
714
 
 
715
        //setDropEnabled(TRUE);
 
716
}
 
717
 
 
718
ContactViewItem::ContactViewItem(const QString &xjid, const QString &xnick, bool xisAgent, QListViewItem *parent)
 
719
:QListViewItem(parent)
 
720
{
 
721
        if(!parent->isVisible())
 
722
                setVisible(FALSE);
 
723
 
 
724
        v_type = CV_CONTACT;
 
725
        v_jid = xjid;
 
726
        v_nick = xnick;
 
727
        v_group = "";
 
728
        v_isAgent = xisAgent;
 
729
        v_isAlert = FALSE;
 
730
        v_isAnimateNick = FALSE;
 
731
        v_status = STATUS_OFFLINE;
 
732
 
 
733
        resetStatus();
 
734
        resetNick();
 
735
 
 
736
        //setDragEnabled(TRUE);
 
737
        //setDropEnabled(TRUE);
 
738
}
 
739
 
 
740
ContactViewItem::~ContactViewItem()
 
741
{
 
742
        // delete the alert queue
 
743
        while(!alertQueue.isEmpty()) {
 
744
                int *x = alertQueue.last();
 
745
                alertQueue.remove(x);
 
746
                delete x;
 
747
        }
 
748
}
 
749
 
 
750
void ContactViewItem::optionsUpdate()
 
751
{
 
752
        if(v_type == CV_GROUP) {
 
753
                drawGroupIcon();
 
754
        }
 
755
        else {
 
756
                if(!v_isAlert)
 
757
                        resetStatus();
 
758
                else
 
759
                        resetAnim();
 
760
        }
 
761
}
 
762
 
 
763
void ContactViewItem::resetAnim()
 
764
{
 
765
        animStep = 0;
 
766
        if(v_isAlert) {
 
767
                if(option.alertStyle == 0)
 
768
                        setPixmap(0, messagetype2anim(alertType)->base());
 
769
        }
 
770
}
 
771
 
 
772
void ContactViewItem::paintFocus(QPainter *, const QColorGroup &, const QRect &)
 
773
{
 
774
        // re-implimented to do nothing.  selection is enough of a focus
 
775
}
 
776
 
 
777
void ContactViewItem::paintBranches(QPainter *p, const QColorGroup &cg, int w, int, int h)
 
778
{
 
779
        // paint a square of nothing
 
780
        p->fillRect(0, 0, w, h, cg.base());
 
781
}
 
782
 
 
783
void ContactViewItem::paintCell(QPainter *p, const QColorGroup & cg, int column, int width, int alignment)
 
784
{
 
785
        if(v_type == CV_CONTACT) {
 
786
                QColorGroup xcg = cg;
 
787
                if(v_status == STATUS_AWAY || v_status == STATUS_XA)
 
788
                        xcg.setColor(QColorGroup::Text, option.color[cAway]);
 
789
                else if(v_status == STATUS_DND)
 
790
                        xcg.setColor(QColorGroup::Text, option.color[cDND]);
 
791
                else if(v_status == STATUS_OFFLINE)
 
792
                        xcg.setColor(QColorGroup::Text, option.color[cOffline]);
 
793
 
 
794
                if(v_isAnimateNick) {
 
795
                        xcg.setColor(QColorGroup::Text, animateNickColor ? Qt::red : Qt::black);
 
796
                        xcg.setColor(QColorGroup::HighlightedText, animateNickColor ? Qt::red : Qt::black);
 
797
                }
 
798
 
 
799
                QListViewItem::paintCell(p, xcg, column, width, alignment);
 
800
        }
 
801
        else if(v_type == CV_GROUP) {
 
802
                QColorGroup xcg = cg;
 
803
                xcg.setColor(QColorGroup::Text, option.color[cGroupFore]);
 
804
                xcg.setColor(QColorGroup::Base, option.color[cGroupBack]);
 
805
 
 
806
                //QFont f = p->font();
 
807
                //f.setPixelSize(8);
 
808
                //p->setFont(f);
 
809
 
 
810
                QListViewItem::paintCell(p, xcg, column, width, alignment);
 
811
 
 
812
                //QFontMetrics fm(p->font());
 
813
                //int x1 = fm.width(text(0)) + pixmap().width() + 4;
 
814
 
 
815
                //if(column == 0) {
 
816
                        int x1, x2, y1, y2;
 
817
 
 
818
                        x1 = 0;
 
819
                        x2 = width - 1;
 
820
                        y1 = 0;
 
821
                        y2 = height() - 1;
 
822
 
 
823
                        p->setPen(QPen(option.color[cGroupFore]));
 
824
                        p->drawLine(x1, y1, x2, y1);
 
825
                        p->drawLine(x1, y2, x2, y2);
 
826
                        p->drawLine(x1, y1, x1, y2);
 
827
                        p->drawLine(x2, y1, x2, y2);
 
828
                //}
 
829
                /*else {
 
830
                        int x1, x2, y1, y2;
 
831
 
 
832
                        x1 = 0;
 
833
                        x2 = width - 1;
 
834
                        y1 = 0;
 
835
                        y2 = height() - 1;
 
836
 
 
837
                        p->setPen(QPen(option.color[cGroupFore]));
 
838
                        p->drawLine(x1, y1, x2, y1);
 
839
                        p->drawLine(x1, y2, x2, y2);
 
840
                        p->drawLine(x2, y1, x2, y2);
 
841
                }*/
 
842
        }
 
843
}
 
844
 
 
845
void ContactViewItem::setOpen(bool o)
 
846
{
 
847
        QListViewItem::setOpen(o);
 
848
 
 
849
        drawGroupIcon();
 
850
}
 
851
 
 
852
int ContactViewItem::parentGroupType()
 
853
{
 
854
        ContactViewItem *item = LVI2CVI(parent());
 
855
        return item->groupType();
 
856
}
 
857
 
 
858
void ContactViewItem::setStatus(int xstatus)
 
859
{
 
860
        if(v_status == xstatus)
 
861
                return;
 
862
 
 
863
        v_status = xstatus;
 
864
        resetStatus();
 
865
 
 
866
        ContactViewItem *i = LVI2CVI(parent());
 
867
        if(i)
 
868
                i->needSorting = TRUE;
 
869
}
 
870
 
 
871
void ContactViewItem::resetStatus()
 
872
{
 
873
        if(v_isAlert)
 
874
                return;
 
875
 
 
876
        setPixmap(0, v_isAgent ? transport2icon(v_jid, v_status) : status2pix(v_status));
 
877
}
 
878
 
 
879
void ContactViewItem::setNick(const QString &xnick)
 
880
{
 
881
        if(v_nick == xnick)
 
882
                return;
 
883
 
 
884
        v_nick = xnick;
 
885
        resetNick();
 
886
 
 
887
        ContactViewItem *i = LVI2CVI(parent());
 
888
        if(i)
 
889
                i->needSorting = TRUE;
 
890
}
 
891
 
 
892
void ContactViewItem::resetNick()
 
893
{
 
894
        setPixmap(0, v_isAgent ? transport2icon(v_jid, v_status) : status2pix(v_status));
 
895
        setText(0, v_nick);
 
896
}
 
897
 
 
898
void ContactViewItem::setGroup(const QString &xgroup)
 
899
{
 
900
        v_group = xgroup;
 
901
}
 
902
 
 
903
void ContactViewItem::setSub(const QString &xsub)
 
904
{
 
905
        v_sub = xsub;
 
906
}
 
907
 
 
908
void ContactViewItem::setStatusString(const QString &xstatusString)
 
909
{
 
910
        v_statusString = xstatusString;
 
911
}
 
912
 
 
913
void ContactViewItem::setInList(bool xinList)
 
914
{
 
915
        v_inList = xinList;
 
916
}
 
917
 
 
918
void ContactViewItem::setIsAgent(bool xisAgent)
 
919
{
 
920
        bool oldstate = v_isAgent;
 
921
 
 
922
        v_isAgent = xisAgent;
 
923
 
 
924
        // if different, then update the status
 
925
        if(v_isAgent != oldstate)
 
926
                resetStatus();
 
927
}
 
928
 
 
929
void ContactViewItem::setAlert(int xtype)
 
930
{
 
931
        if(!v_isAlert) {
 
932
                v_isAlert = TRUE;
 
933
                alertType = xtype;
 
934
                animStep = 0;
 
935
                if(option.alertStyle == 0)
 
936
                        setPixmap(0, messagetype2anim(alertType)->base());
 
937
        }
 
938
 
 
939
        int *x = new int(xtype);
 
940
        alertQueue.insert(0, x);
 
941
}
 
942
 
 
943
void ContactViewItem::clearAlert(int at)
 
944
{
 
945
        if(alertQueue.isEmpty())
 
946
                return;
 
947
 
 
948
        // find and destroy
 
949
        int *x = alertQueue.last();
 
950
        for(int n = 0; n < at; ++n) {
 
951
                x = alertQueue.prev();
 
952
        }
 
953
        if(x) {
 
954
                alertQueue.remove(x);
 
955
                delete x;
 
956
        }
 
957
 
 
958
        // set the next alert (or stop alerting if empty)
 
959
        if(alertQueue.isEmpty()) {
 
960
                v_isAlert = FALSE;
 
961
                resetStatus();
 
962
        }
 
963
        else {
 
964
                x = alertQueue.last();
 
965
                alertType = *x;
 
966
                animStep = 0;
 
967
        }
 
968
}
 
969
 
 
970
void ContactViewItem::setAttr(const QString &xnick, const QString xgroup, const QString &sub, int status)
 
971
{
 
972
        setNick(xnick);
 
973
        setGroup(xgroup);
 
974
        setSub(sub);
 
975
        setStatus(status);
 
976
}
 
977
 
 
978
void ContactViewItem::setGroupName(const QString &name)
 
979
{
 
980
        v_groupName = name;
 
981
        resetGroupName();
 
982
}
 
983
 
 
984
void ContactViewItem::setGroupInfo(const QString &info)
 
985
{
 
986
        v_groupInfo = info;
 
987
        resetGroupName();
 
988
}
 
989
 
 
990
void ContactViewItem::resetGroupName(bool showInfo)
 
991
{
 
992
        QString str = v_groupName;
 
993
        if(showInfo && !v_groupInfo.isEmpty())
 
994
                str += QString(" ") + v_groupInfo;
 
995
 
 
996
        setText(0, str);
 
997
}
 
998
 
 
999
void ContactViewItem::animate()
 
1000
{
 
1001
        Anim *anim = messagetype2anim(alertType);
 
1002
 
 
1003
        if(anim->isAnim() && option.alertStyle == 2) {
 
1004
                setPixmap(0, anim->frame(animStep));
 
1005
                ++animStep;
 
1006
                if(animStep >= anim->numFrames()-1)
 
1007
                        animStep = 0;
 
1008
        }
 
1009
        else if(option.alertStyle != 0) {
 
1010
                if(animStep == 0)
 
1011
                        setPixmap(0, anim->base());
 
1012
                else if(animStep == 4)
 
1013
                        setPixmap(0, *pix_blank);
 
1014
 
 
1015
                ++animStep;
 
1016
                if(animStep == 8)
 
1017
                        animStep = 0;
 
1018
        }
 
1019
}
 
1020
 
 
1021
int ContactViewItem::rankGroup(int groupType) const
 
1022
{
 
1023
        static int rankgroups[7] = {
 
1024
                CVG_SELF,
 
1025
                CVG_ONLINE,
 
1026
                CVG_USER,
 
1027
                CVG_OFFLINE,
 
1028
                CVG_AUTHWAIT,
 
1029
                CVG_AGENTS,
 
1030
                CVG_NOTINLIST,
 
1031
        };
 
1032
 
 
1033
        int n;
 
1034
        for(n = 0; n < 7; ++n) {
 
1035
                if(rankgroups[n] == groupType)
 
1036
                        break;
 
1037
        }
 
1038
        if(n == 7)
 
1039
                return 6;
 
1040
 
 
1041
        return n;
 
1042
}
 
1043
 
 
1044
int ContactViewItem::rankStatus(int status) const
 
1045
{
 
1046
        static int rankstatuses[5] = {
 
1047
                STATUS_ONLINE,
 
1048
                STATUS_AWAY,
 
1049
                STATUS_XA,
 
1050
                STATUS_DND,
 
1051
                STATUS_OFFLINE,
 
1052
        };
 
1053
 
 
1054
        int n;
 
1055
        for(n = 0; n < 5; ++n) {
 
1056
                if(rankstatuses[n] == status)
 
1057
                        break;
 
1058
        }
 
1059
        if(n == 5)
 
1060
                return 4;
 
1061
 
 
1062
        return n;
 
1063
}
 
1064
 
 
1065
int ContactViewItem::compare(QListViewItem *xi, int, bool) const
 
1066
{
 
1067
        ContactViewItem *i = LVI2CVI(xi);
 
1068
        int ret = 0;
 
1069
 
 
1070
        if(v_type == CV_GROUP) {
 
1071
                // contacts always go before groups
 
1072
                if(i->type() == CV_CONTACT)
 
1073
                        ret = 1;
 
1074
                else {
 
1075
                        ret = rankGroup(v_groupType) - rankGroup(i->groupType());
 
1076
                        if(ret == 0)
 
1077
                                ret = text(0).lower().localeAwareCompare(i->text(0).lower());
 
1078
                }
 
1079
        }
 
1080
        else if(v_type == CV_CONTACT) {
 
1081
                // contacts always go before groups
 
1082
                if(i->type() == CV_GROUP)
 
1083
                        ret = -1;
 
1084
                else {
 
1085
                        //int x1 = v_isAlert ? 0 : (rankStatus(v_status) + 1);
 
1086
                        //int x2 = i->isAlert() ? 0 : (rankStatus(i->status()) + 1);
 
1087
 
 
1088
                        ret = rankStatus(v_status) - rankStatus(i->status());
 
1089
                        //ret = x1 - x2;
 
1090
                        if(ret == 0)
 
1091
                                ret = text(0).lower().localeAwareCompare(i->text(0).lower());
 
1092
                }
 
1093
        }
 
1094
 
 
1095
        return ret;
 
1096
}
 
1097
 
 
1098
void ContactViewItem::drawGroupIcon()
 
1099
{
 
1100
        if(childCount() == 0)
 
1101
                setPixmap(0, *pix_arrow[2]);
 
1102
        else if(isOpen())
 
1103
                setPixmap(0, *pix_arrow[1]);
 
1104
        else
 
1105
                setPixmap(0, *pix_arrow[0]);
 
1106
}
 
1107
 
 
1108
void ContactViewItem::insertItem(QListViewItem * newChild)
 
1109
{
 
1110
        QListViewItem::insertItem(newChild);
 
1111
 
 
1112
        drawGroupIcon();
 
1113
}
 
1114
 
 
1115
void ContactViewItem::takeItem(QListViewItem * item)
 
1116
{
 
1117
        QListViewItem::takeItem(item);
 
1118
 
 
1119
        drawGroupIcon();
 
1120
}
 
1121
 
 
1122
void ContactViewItem::setAnimateNick()
 
1123
{
 
1124
        stopAnimateNick();
 
1125
 
 
1126
        v_isAnimateNick = TRUE;
 
1127
        animateNickX = 0;
 
1128
        animateNick();
 
1129
}
 
1130
 
 
1131
void ContactViewItem::stopAnimateNick()
 
1132
{
 
1133
        if(!v_isAnimateNick)
 
1134
                return;
 
1135
 
 
1136
        v_isAnimateNick = FALSE;
 
1137
        repaint();
 
1138
}
 
1139
 
 
1140
void ContactViewItem::animateNick()
 
1141
{
 
1142
        animateNickColor = (animateNickX % 10) >= 5 ? 1: 0;
 
1143
        if((animateNickX % 5) == 0)
 
1144
                repaint();
 
1145
 
 
1146
        ++animateNickX;
 
1147
        if(animateNickX == 80)
 
1148
                stopAnimateNick();
 
1149
}
 
1150
 
 
1151
bool ContactViewItem::isAway()
 
1152
{
 
1153
        if(v_status == STATUS_AWAY || v_status == STATUS_XA || v_status == STATUS_DND)
 
1154
                return TRUE;
 
1155
 
 
1156
        return FALSE;
 
1157
}
 
1158
 
 
1159
void ContactViewItem::sort()
 
1160
{
 
1161
        QListView *i = listView();
 
1162
        if(!i)
 
1163
                return;
 
1164
 
 
1165
        i->setSorting(0, TRUE);
 
1166
        QListViewItem::sort();
 
1167
        i->setSorting(-1, TRUE);
 
1168
 
 
1169
        needSorting = FALSE;
 
1170
}
 
1171
 
 
1172
/*bool ContactViewItem::acceptDrop(const QMimeSource *mime) const
 
1173
{
 
1174
        printf("accept?\n");
 
1175
        return TRUE;// QTextDrag::canDecode(mime);
 
1176
}
 
1177
 
 
1178
void ContactViewItem::dropped(QDropEvent *e)
 
1179
{
 
1180
        QString text;
 
1181
 
 
1182
        if(QTextDrag::decode(e, text)) {
 
1183
                printf("dropped on %s, this text: %s\n", v_jid.latin1(), text.latin1());
 
1184
        }
 
1185
}
 
1186
*/
 
1187
 
 
1188
 
 
1189
//*******************************************************
 
1190
//  ContactProfile
 
1191
//*******************************************************
 
1192
ContactProfile::ContactProfile(const QString &_jid, const QString &_name, int _localStatus, bool unique, ContactView *_cv)
 
1193
{
 
1194
        jid = _jid;
 
1195
        name = _name;
 
1196
        localStatus = _localStatus;
 
1197
        cv = _cv;
 
1198
 
 
1199
        roster = new QDict<ContactProfileItem>(50, TRUE);
 
1200
        roster->setAutoDelete(TRUE);
 
1201
 
 
1202
        if(!unique)
 
1203
                cvi = new ContactViewItem(name, CVG_USER, cv);
 
1204
        else
 
1205
                cvi = 0;
 
1206
 
 
1207
        cvi_online = addGroup(CVG_ONLINE);
 
1208
        cvi_offline = addGroup(CVG_OFFLINE);
 
1209
}
 
1210
 
 
1211
ContactProfile::~ContactProfile()
 
1212
{
 
1213
        // delete the roster
 
1214
        clear();
 
1215
 
 
1216
        // clean up
 
1217
        delete cvi_online;
 
1218
        delete cvi_offline;
 
1219
        if(cvi)
 
1220
                delete cvi;
 
1221
 
 
1222
        delete roster;
 
1223
}
 
1224
 
 
1225
ContactProfileItem *ContactProfile::cvi2cpi(ContactViewItem *i)
 
1226
{
 
1227
        return roster->find(i->jid().lower());
 
1228
}
 
1229
 
 
1230
ContactProfileItem *ContactProfile::findByJid(const QString &jid)
 
1231
{
 
1232
        return roster->find(jid.lower());
 
1233
}
 
1234
 
 
1235
bool ContactProfile::isMine(ContactViewItem *i)
 
1236
{
 
1237
        // unique?  we'll take it
 
1238
        if(cvi == 0)
 
1239
                return TRUE;
 
1240
 
 
1241
        while(i) {
 
1242
                if(i == cvi)
 
1243
                        return TRUE;
 
1244
 
 
1245
                // reduce the depth until we hit the base
 
1246
                i = LVI2CVI(i->parent());
 
1247
        }
 
1248
 
 
1249
        return FALSE;
 
1250
}
 
1251
 
 
1252
ContactViewItem *ContactProfile::findCVIByJid(const QString &jid)
 
1253
{
 
1254
        ContactProfileItem *i = findByJid(jid);
 
1255
        if(!i)
 
1256
                return 0;
 
1257
        return i->cvi;
 
1258
}
 
1259
 
 
1260
ContactViewItem *ContactProfile::addGroup(int type)
 
1261
{
 
1262
        ContactViewItem *item;
 
1263
 
 
1264
        QString gname;
 
1265
        if(type == CVG_ONLINE)
 
1266
                gname = tr("Online");
 
1267
        else if(type == CVG_OFFLINE)
 
1268
                gname = tr("Offline");
 
1269
        else if(type == CVG_NOTINLIST)
 
1270
                gname = tr("Not in list");
 
1271
        else if(type == CVG_AUTHWAIT)
 
1272
                gname = tr("Need Authorization");
 
1273
        else if(type == CVG_AGENTS)
 
1274
                gname = tr("Agents/Transports");
 
1275
 
 
1276
        if(cvi)
 
1277
                item = new ContactViewItem(gname, type, cvi);
 
1278
        else
 
1279
                item = new ContactViewItem(gname, type, cv);
 
1280
 
 
1281
        if((type == CVG_OFFLINE && !cv->isShowOffline()) || (type == CVG_AGENTS && !cv->isShowAgents()))
 
1282
                item->setVisible(FALSE);
 
1283
 
 
1284
        cv->deferredContactSort();
 
1285
 
 
1286
        // debug
 
1287
        QString dstr; dstr.sprintf("ContactProfile::addGroup: [%s]\n", gname.latin1());
 
1288
        pdb(DEBUG_CV, dstr);
 
1289
 
 
1290
        return item;
 
1291
}
 
1292
 
 
1293
ContactViewItem *ContactProfile::addGroup(const QString &name, ContactViewItem *par)
 
1294
{
 
1295
        ContactViewItem *item = new ContactViewItem(name, CVG_USER, par);
 
1296
        cv->deferredContactSort();
 
1297
        return item;
 
1298
}
 
1299
 
 
1300
ContactViewItem *ContactProfile::checkGroup(int group)
 
1301
{
 
1302
        ContactViewItem *item;
 
1303
        if(cvi)
 
1304
                item = LVI2CVI(cvi->firstChild());
 
1305
        else
 
1306
                item = LVI2CVI(cv->firstChild());
 
1307
 
 
1308
        // do we have it?
 
1309
        for(; item; item = LVI2CVI(item->nextSibling()) ) {
 
1310
                if(item->type() == CV_GROUP && item->groupType() == group)
 
1311
                        return item;
 
1312
        }
 
1313
 
 
1314
        return 0;
 
1315
}
 
1316
 
 
1317
ContactViewItem *ContactProfile::checkGroup(const QString &group, ContactViewItem *par)
 
1318
{
 
1319
        // do we have it?
 
1320
        ContactViewItem *item = LVI2CVI(par->firstChild());
 
1321
        for(; item; item = LVI2CVI(item->nextSibling()) ) {
 
1322
                if(item->type() == CV_GROUP && item->groupType() == CVG_USER) {
 
1323
                        if(item->groupName() == group)
 
1324
                                return item;
 
1325
                }
 
1326
        }
 
1327
 
 
1328
        return 0;
 
1329
}
 
1330
 
 
1331
ContactViewItem *ContactProfile::ensureGroup(int group)
 
1332
{
 
1333
        ContactViewItem *group_item = checkGroup(group);
 
1334
        if(group_item)
 
1335
                return group_item;
 
1336
 
 
1337
        return addGroup(group);
 
1338
}
 
1339
 
 
1340
ContactViewItem *ContactProfile::ensureGroup(const QString &group, int status)
 
1341
{
 
1342
        // empty string == default group (online/offline)
 
1343
        if(group.isEmpty()) {
 
1344
                int gtype = (status == STATUS_OFFLINE) ? CVG_OFFLINE : CVG_ONLINE;
 
1345
                return ensureGroup(gtype);
 
1346
        }
 
1347
 
 
1348
        ContactViewItem *group_item;
 
1349
        ContactViewItem *par = (status == STATUS_OFFLINE) ? offline(): online();
 
1350
 
 
1351
        group_item = checkGroup(group, par);
 
1352
 
 
1353
        // doesn't exist?  make it!
 
1354
        if(!group_item)
 
1355
                group_item = addGroup(group, par);
 
1356
 
 
1357
        return group_item;
 
1358
}
 
1359
 
 
1360
ContactProfileItem *ContactProfile::addEntry(const UserListItem &i)
 
1361
{
 
1362
        ContactViewItem *group_item;
 
1363
        if(i.inList == FALSE)
 
1364
                group_item = ensureGroup(CVG_NOTINLIST);
 
1365
        else if(i.isTransport == TRUE)
 
1366
                group_item = ensureGroup(CVG_AGENTS);
 
1367
        else if(i.sub == "from" || i.sub == "none")
 
1368
                group_item = ensureGroup(CVG_AUTHWAIT);
 
1369
        else
 
1370
                group_item = ensureGroup(i.group, i.state);
 
1371
 
 
1372
        QString nick = jidnick(i.jid, i.nick);
 
1373
        ContactViewItem *item = new ContactViewItem(i.jid, nick, i.isTransport, group_item);
 
1374
        item->setAttr(nick, i.group, i.sub, i.state);
 
1375
        item->setInList(i.inList);
 
1376
        item->setStatusString(i.statusString);
 
1377
 
 
1378
        item->resList() = i.res;
 
1379
 
 
1380
        // insert into the profile roster
 
1381
        ContactProfileItem *pi = new ContactProfileItem;
 
1382
        pi->uli = i;
 
1383
        pi->cvi = item;
 
1384
        roster->insert(i.jid.lower(), pi);
 
1385
 
 
1386
        // debug
 
1387
        QString dstr; dstr.sprintf("ContactProfile::addEntry: adding [%s] to group [%s]\n", i.jid.latin1(), group_item->groupName().latin1());
 
1388
        pdb(DEBUG_CV, dstr);
 
1389
 
 
1390
        return pi;
 
1391
}
 
1392
 
 
1393
void ContactProfile::updateEntry(const UserListItem &i)
 
1394
{
 
1395
        ContactProfileItem *pi = findByJid(i.jid);
 
1396
        ContactViewItem *item;
 
1397
        if(!pi) {
 
1398
                item = addEntry(i)->cvi;
 
1399
        }
 
1400
        else {
 
1401
                item = pi->cvi;
 
1402
 
 
1403
                // if the group is different, we may need to remove a floating user group
 
1404
                QString oldgroup = item->group();
 
1405
 
 
1406
                item->setAttr(jidnick(i.jid, i.nick), i.group, i.sub, i.state);
 
1407
                item->setInList(i.inList);
 
1408
                item->setStatusString(i.statusString);
 
1409
 
 
1410
                item->resList() = i.res;
 
1411
 
 
1412
                // it is possible that a contact could be recognized later as an agent i guess
 
1413
                item->setIsAgent(i.isTransport); // ok 99, go-go-gadget shoe phone
 
1414
 
 
1415
                // update the group
 
1416
                changeGroup(item, i.group);
 
1417
 
 
1418
                // destroy original group?
 
1419
                checkDestroyGroup(oldgroup);
 
1420
 
 
1421
                // stop animating the nick if going offline
 
1422
                if(i.state == STATUS_OFFLINE)
 
1423
                        item->stopAnimateNick();
 
1424
        }
 
1425
 
 
1426
        cv->setVisibility(item);
 
1427
        cv->deferredContactSort();
 
1428
}
 
1429
 
 
1430
 
 
1431
void ContactProfile::changeGroup(ContactViewItem *item, ContactViewItem *group_new)
 
1432
{
 
1433
        // contacts are always children of groups, so this should be safe:
 
1434
        ContactViewItem *group_in = LVI2CVI(item->parent());
 
1435
 
 
1436
        if(group_in != group_new) {
 
1437
                // take from the rich, give to the poor
 
1438
                group_in->takeItem(item);
 
1439
                group_new->insertItem(item);
 
1440
 
 
1441
                // visibility of item should match that of group_new
 
1442
                item->setVisible(group_new->isVisible());
 
1443
        }
 
1444
 
 
1445
        // we may need to destroy the original group(s):
 
1446
        checkDestroyGroup(group_in);
 
1447
 
 
1448
        if(item->isAlert()) {
 
1449
                if(option.scrollTo)
 
1450
                        cv->ensureVisible(item);
 
1451
        }
 
1452
}
 
1453
 
 
1454
void ContactProfile::changeGroup(ContactViewItem *item, const QString &group)
 
1455
{
 
1456
        ContactViewItem *group_item;
 
1457
 
 
1458
        if(item->inList() == FALSE) {
 
1459
                item->setStatus(STATUS_OFFLINE);
 
1460
                group_item = ensureGroup(CVG_NOTINLIST);
 
1461
        }
 
1462
        else if(item->isAgent() == TRUE)
 
1463
                group_item = ensureGroup(CVG_AGENTS);
 
1464
        else if(item->sub() == "from" || item->sub() == "none") {
 
1465
                item->setStatus(STATUS_OFFLINE);
 
1466
                group_item = ensureGroup(CVG_AUTHWAIT);
 
1467
        }
 
1468
        else
 
1469
                group_item = ensureGroup(group, item->status());
 
1470
 
 
1471
        changeGroup(item, group_item);
 
1472
}
 
1473
 
 
1474
void ContactProfile::checkDestroyGroup(const QString &group)
 
1475
{
 
1476
        if(group.isEmpty())
 
1477
                return;
 
1478
 
 
1479
        ContactViewItem *group_item;
 
1480
 
 
1481
        group_item = checkGroup(group, offline());
 
1482
        if(group_item)
 
1483
                checkDestroyGroup(group_item);
 
1484
        group_item = checkGroup(group, online());
 
1485
        if(group_item)
 
1486
                checkDestroyGroup(group_item);
 
1487
}
 
1488
 
 
1489
void ContactProfile::checkDestroyGroup(ContactViewItem *group)
 
1490
{
 
1491
        // don't destroy online/offline psuedogroups
 
1492
        if(group->groupType() == CVG_ONLINE || group->groupType() == CVG_OFFLINE)
 
1493
                return;
 
1494
 
 
1495
        if(group->childCount() == 0) {
 
1496
                // debug
 
1497
                QString dstr; dstr.sprintf("ContactProfile::checkDestroyGroup: removing group [%s]\n", group->groupName().latin1());
 
1498
                pdb(DEBUG_CV, dstr);
 
1499
 
 
1500
                delete group;
 
1501
        }
 
1502
}
 
1503
 
 
1504
void ContactProfile::removeEntry(const QString &jid)
 
1505
{
 
1506
        ContactProfileItem *pi = findByJid(jid);
 
1507
        if(!pi)
 
1508
                return;
 
1509
        removeEntry(pi);
 
1510
}
 
1511
 
 
1512
void ContactProfile::removeEntry(ContactProfileItem *pi)
 
1513
{
 
1514
        ContactViewItem *item = pi->cvi;
 
1515
 
 
1516
        // prepare to delete the parent group
 
1517
        ContactViewItem *group_in = LVI2CVI(item->parent());
 
1518
 
 
1519
        // debug
 
1520
        //QString dstr; dstr.sprintf("ContactProfile::removeEntry: removing contact [%s]\n", item->jid().latin1());
 
1521
        //pdb(DEBUG_CV, dstr);
 
1522
 
 
1523
        clearAllAlerts(item);
 
1524
        delete item;
 
1525
 
 
1526
        QString key = pi->uli.jid.lower();
 
1527
        roster->remove(key);
 
1528
 
 
1529
        updateGroupInfo(group_in);
 
1530
 
 
1531
        // remove the group?
 
1532
        checkDestroyGroup(group_in);
 
1533
}
 
1534
 
 
1535
void ContactProfile::showAlert(const QString &jid, int type)
 
1536
{
 
1537
        ContactProfileItem *pi = findByJid(jid);
 
1538
        if(!pi)
 
1539
                return;
 
1540
        ContactViewItem *item = pi->cvi;
 
1541
 
 
1542
        // reset all animations (so they are in sync with this new one)
 
1543
        for(QListViewItemIterator it(cv); it.current() ; ++it) {
 
1544
                ContactViewItem *item = LVI2CVI(it.current());
 
1545
                if(item->type() == CV_CONTACT)
 
1546
                        item->resetAnim();
 
1547
        }
 
1548
 
 
1549
        // flag the alert, and account the total
 
1550
        item->setAlert(type);
 
1551
 
 
1552
        if(option.scrollTo)
 
1553
                cv->ensureVisible(item);
 
1554
}
 
1555
 
 
1556
void ContactProfile::clearAlert(const QString &jid, int at)
 
1557
{
 
1558
        ContactProfileItem *pi = findByJid(jid);
 
1559
        if(!pi)
 
1560
                return;
 
1561
        ContactViewItem *item = pi->cvi;
 
1562
        clearAlert(item, at);
 
1563
}
 
1564
 
 
1565
void ContactProfile::clearAllAlerts(const QString &jid)
 
1566
{
 
1567
        ContactProfileItem *pi = findByJid(jid);
 
1568
        if(!pi)
 
1569
                return;
 
1570
        ContactViewItem *item = pi->cvi;
 
1571
        clearAllAlerts(item);
 
1572
}
 
1573
 
 
1574
void ContactProfile::clearAlert(ContactViewItem *item, int at)
 
1575
{
 
1576
        if(item->isAlert())
 
1577
                item->clearAlert(at);
 
1578
}
 
1579
 
 
1580
void ContactProfile::clearAllAlerts(ContactViewItem *item)
 
1581
{
 
1582
        while(item->isAlert())
 
1583
                item->clearAlert();
 
1584
}
 
1585
 
 
1586
void ContactProfile::animateNick(const QString &jid)
 
1587
{
 
1588
        ContactProfileItem *pi = findByJid(jid);
 
1589
        if(!pi)
 
1590
                return;
 
1591
        ContactViewItem *item = pi->cvi;
 
1592
        item->setAnimateNick();
 
1593
}
 
1594
 
 
1595
void ContactProfile::clear()
 
1596
{
 
1597
        QDictIterator<ContactProfileItem> it(*roster);
 
1598
 
 
1599
        for(ContactProfileItem *pi; (pi = it.current());)
 
1600
                removeEntry(pi);
 
1601
}
 
1602
 
 
1603
QStringList ContactProfile::buildGroupList()
 
1604
{
 
1605
        QStringList groupList;
 
1606
 
 
1607
        QListViewItemIterator it(cv);
 
1608
        ContactViewItem *item;
 
1609
 
 
1610
        for(; it.current() ; ++it) {
 
1611
                item = LVI2CVI(it.current());
 
1612
                if(item->type() != CV_CONTACT)
 
1613
                        continue;
 
1614
 
 
1615
                if(item->group().isEmpty())
 
1616
                        continue;
 
1617
 
 
1618
                // weed out duplicates
 
1619
                if(qstringlistmatch(groupList, item->group()) == -1)
 
1620
                        groupList.append(item->group());
 
1621
        }
 
1622
 
 
1623
        groupList.sort();
 
1624
        return groupList;
 
1625
}
 
1626
 
 
1627
void ContactProfile::doContextMenu(ContactViewItem *i, const QPoint &pos)
 
1628
{
 
1629
        //ContactProfileItem *pi = cvi2cpi(i);
 
1630
        QStringList groupList = buildGroupList();
 
1631
 
 
1632
        if(i->type() == CV_CONTACT) {
 
1633
                QPopupMenu *popup = new QPopupMenu;
 
1634
 
 
1635
                if(i->parentGroupType() == CVG_NOTINLIST) {
 
1636
                        popup->insertItem(QIconSet(*pix_add), tr("Add/Authorize to contact list"), 10);
 
1637
                        if(localStatus == STATUS_OFFLINE)
 
1638
                                popup->setItemEnabled(10, FALSE);
 
1639
 
 
1640
                        popup->insertSeparator();
 
1641
                }
 
1642
                if(i->isAlert()) {
 
1643
                        cv->qa_recv->addTo(popup);
 
1644
                        popup->insertSeparator();
 
1645
                }
 
1646
 
 
1647
                cv->qa_send->setIconSet(*pix_send);
 
1648
                cv->qa_send->addTo(popup);
 
1649
 
 
1650
                popup->insertItem(QIconSet(*pix_url), tr("Send &URL"), 2);
 
1651
 
 
1652
                cv->qa_chat->setIconSet(anim_chat->base());
 
1653
                cv->qa_chat->addTo(popup);
 
1654
 
 
1655
                popup->insertItem("Offer &file", 3);
 
1656
                popup->setItemEnabled(3, FALSE);
 
1657
                popup->insertSeparator();
 
1658
 
 
1659
                if(i->parentGroupType() != CVG_NOTINLIST)
 
1660
                        cv->qa_ren->addTo(popup);
 
1661
 
 
1662
                if(!i->isAgent()) {
 
1663
                        if(i->parentGroupType() != CVG_NOTINLIST) {
 
1664
 
 
1665
                                // --- groups ---
 
1666
                                QPopupMenu *groupmenu = new QPopupMenu(popup);
 
1667
 
 
1668
                                groupmenu->setCheckable(TRUE);
 
1669
                                groupmenu->insertItem(tr("&None"), 8);
 
1670
                                groupmenu->insertSeparator();
 
1671
 
 
1672
                                if(i->group().isEmpty())
 
1673
                                        groupmenu->setItemChecked(8, TRUE);
 
1674
 
 
1675
                                int n = 0;
 
1676
                                for(QStringList::Iterator it = groupList.begin(); it != groupList.end(); ++it, ++n) {
 
1677
                                        QString str;
 
1678
                                        if(n < 9)
 
1679
                                                str = "&";
 
1680
                                        str += QString("%1. %2").arg(n+1).arg(*it);
 
1681
                                        groupmenu->insertItem(str, n+32);
 
1682
 
 
1683
                                        if(i->group() == *it)
 
1684
                                                groupmenu->setItemChecked(n+32, TRUE);
 
1685
                                }
 
1686
                                if(n > 0)
 
1687
                                        groupmenu->insertSeparator();
 
1688
 
 
1689
                                groupmenu->insertItem(tr("&Create new..."), 9);
 
1690
 
 
1691
                                popup->insertItem(tr("&Group"), groupmenu, 5);
 
1692
                                // --- groups ---
 
1693
                        }
 
1694
 
 
1695
                        popup->insertItem(tr("(Re)send &authorization to"), 6);
 
1696
                        if(localStatus == STATUS_OFFLINE)
 
1697
                                popup->setItemEnabled(6, FALSE);
 
1698
 
 
1699
                        //if(i->parentGroupType() == CVG_AUTHWAIT)
 
1700
                                popup->insertItem(tr("Rerequest authorization from"), 11);
 
1701
                        if(localStatus == STATUS_OFFLINE)
 
1702
                                popup->setItemEnabled(11, FALSE);
 
1703
                }
 
1704
                else {
 
1705
                        popup->insertSeparator();
 
1706
 
 
1707
                        if(i->status() != STATUS_OFFLINE || localStatus == STATUS_OFFLINE)
 
1708
                                cv->qa_logon->setEnabled(FALSE);
 
1709
                        else
 
1710
                                cv->qa_logon->setEnabled(TRUE);
 
1711
 
 
1712
                        cv->qa_logon->setIconSet(transport2icon(i->jid()));
 
1713
                        cv->qa_logon->addTo(popup);
 
1714
 
 
1715
                        popup->insertItem(transport2icon(i->jid(), STATUS_OFFLINE), tr("Log off"), 16);
 
1716
                        if(i->status() == STATUS_OFFLINE || localStatus == STATUS_OFFLINE)
 
1717
                                popup->setItemEnabled(16, FALSE);
 
1718
                }
 
1719
                popup->insertSeparator();
 
1720
 
 
1721
                if(localStatus == STATUS_OFFLINE && i->inList())
 
1722
                        cv->qa_rem->setEnabled(FALSE);
 
1723
                else
 
1724
                        cv->qa_rem->setEnabled(TRUE);
 
1725
                cv->qa_rem->setIconSet(*pix_remove);
 
1726
                cv->qa_rem->addTo(popup);
 
1727
 
 
1728
                //popup->insertItem(QIconSet(*pix_remove), tr("Rem&ove"), 7);
 
1729
                //if(localStatus == STATUS_OFFLINE && i->inList())
 
1730
                //      popup->setItemEnabled(7, FALSE);
 
1731
                popup->insertSeparator();
 
1732
 
 
1733
                popup->insertItem(tr("Check &Status"), 4);
 
1734
                popup->insertItem(QIconSet(*pix_info), tr("User &Info"), 12);
 
1735
 
 
1736
                cv->qa_hist->setIconSet(*pix_history);
 
1737
                cv->qa_hist->addTo(popup);
 
1738
 
 
1739
                int x = popup->exec(pos);
 
1740
                delete popup;
 
1741
 
 
1742
                if(x == -1)
 
1743
                        return;
 
1744
                if(x == 0)
 
1745
                        actionRecvEvent(i);
 
1746
                else if(x == 1)
 
1747
                        actionSendMessage(i);
 
1748
                else if(x == 2) {
 
1749
                        actionSendUrl(i->jid());
 
1750
                }
 
1751
                else if(x == 3) {
 
1752
                        actionOfferFile(i->jid());
 
1753
                }
 
1754
                else if(x == 4) {
 
1755
                        actionStatusShow(i->jid());
 
1756
                }
 
1757
                else if(x == 6) {
 
1758
                        if(localStatus != STATUS_OFFLINE) {
 
1759
                                QString name = i->jid();
 
1760
                                if(i->nick() != i->jid())
 
1761
                                        name += QString(" (%1)").arg(i->nick());
 
1762
 
 
1763
                                actionAuthorize(i);
 
1764
                                QMessageBox::information(cv, CAP(tr("Authorize")),
 
1765
                                QString(tr("Authorization sent to <b>%1</b>.")).arg(name));
 
1766
                        }
 
1767
                }
 
1768
                else if(x == 8) {
 
1769
                        QString dstr; dstr.sprintf("contextPopup: groupchange: None\n");
 
1770
                        pdb(DEBUG_CV, dstr);
 
1771
 
 
1772
                        // only send signal if we are actually changing group
 
1773
                        if(!i->group().isEmpty()) {
 
1774
                                actionGroupChange(i->jid(), "");
 
1775
 
 
1776
                                //if(i->status() == STATUS_OFFLINE)
 
1777
                                //      warnOfflineGroupChange();
 
1778
                        }
 
1779
                }
 
1780
                else if(x == 9) {
 
1781
                        while(1) {
 
1782
                                bool ok = FALSE;
 
1783
                                QString newgroup = QInputDialog::getText(CAP(tr("Create New Group")), tr("Enter the new Group name:"), QLineEdit::Normal, QString::null, &ok, cv);
 
1784
                                if(!ok)
 
1785
                                        break;
 
1786
 
 
1787
                                if(newgroup.isEmpty()) {
 
1788
                                        continue;
 
1789
                                }
 
1790
 
 
1791
                                // make sure we don't have it already
 
1792
                                if(qstringlistmatch(groupList, newgroup) == -1) {
 
1793
                                        QString dstr; dstr.sprintf("contextPopup: groupchange: [%s]\n", newgroup.latin1());
 
1794
                                        pdb(DEBUG_CV, dstr);
 
1795
 
 
1796
                                        // only send signal if we are actually changing group
 
1797
                                        if(i->group() != newgroup) {
 
1798
                                                actionGroupChange(i->jid(), newgroup);
 
1799
 
 
1800
                                                //if(i->status() == STATUS_OFFLINE)
 
1801
                                                //      warnOfflineGroupChange();
 
1802
                                        }
 
1803
                                        break;
 
1804
                                }
 
1805
                        }
 
1806
                }
 
1807
                else if(x == 10) {
 
1808
                        if(localStatus != STATUS_OFFLINE) {
 
1809
                                QString name = i->jid();
 
1810
                                if(i->nick() != i->jid())
 
1811
                                        name += QString(" (%1)").arg(i->nick());
 
1812
 
 
1813
                                actionAuthorize(i);
 
1814
 
 
1815
                                // only add if it's _not_ a transport.  see jabcon.
 
1816
                                if(!i->isAgent())
 
1817
                                        actionAdd(i);
 
1818
 
 
1819
                                QMessageBox::information(cv, CAP(tr("Add")),
 
1820
                                QString(tr("Added/Authorized <b>%1</b> to the contact list.")).arg(name));
 
1821
                        }
 
1822
                }
 
1823
                else if(x == 11) {
 
1824
                        if(localStatus != STATUS_OFFLINE) {
 
1825
                                QString name = i->jid();
 
1826
                                if(i->nick() != i->jid())
 
1827
                                        name += QString(" (%1)").arg(i->nick());
 
1828
 
 
1829
                                actionAdd(i);
 
1830
                                QMessageBox::information(cv, CAP(tr("Authorize")),
 
1831
                                QString(tr("Rerequested authorization from <b>%1</b>.")).arg(name));
 
1832
                        }
 
1833
                }
 
1834
                else if(x == 12) {
 
1835
                        actionInfo(i->jid());
 
1836
                }
 
1837
                else if(x == 13) {
 
1838
                        actionHistory(i->jid());
 
1839
                }
 
1840
                else if(x == 14) {
 
1841
                        if(!i->isAlert())
 
1842
                                removeEntry(i->jid());
 
1843
                }
 
1844
                else if(x == 16) {
 
1845
                        actionAgentSetStatus(i->jid(), STATUS_OFFLINE);
 
1846
                }
 
1847
                else if(x >= 32) {
 
1848
                        int n = 0;
 
1849
                        int n2 = x - 32;
 
1850
 
 
1851
                        QString newgroup;
 
1852
                        for(QStringList::Iterator it = groupList.begin(); it != groupList.end(); ++it, ++n) {
 
1853
                                if(n == n2) {
 
1854
                                        newgroup = *it;
 
1855
                                        break;
 
1856
                                }
 
1857
                        }
 
1858
                        if(n == n2) {
 
1859
                                if(i->group() != newgroup) {
 
1860
                                        QString dstr; dstr.sprintf("contextPopup: group change [%s].\n", newgroup.latin1());
 
1861
                                        pdb(DEBUG_CV, dstr);
 
1862
 
 
1863
                                        // only send signal if we are actually changing group
 
1864
                                        if(i->group() != newgroup) {
 
1865
                                                actionGroupChange(i->jid(), newgroup);
 
1866
 
 
1867
                                                //if(i->status() == STATUS_OFFLINE)
 
1868
                                                //      warnOfflineGroupChange();
 
1869
                                        }
 
1870
                                }
 
1871
                        }
 
1872
                }
 
1873
        }
 
1874
        else if(i->type() == CV_GROUP) {
 
1875
                QPopupMenu *popup = new QPopupMenu(cv);
 
1876
                popup->insertItem(QIconSet(*pix_send), tr("Send message to group"), 0);
 
1877
                popup->insertItem(tr("Re&name"), cv, SLOT(doRename()), QListView::Key_F2, 1);
 
1878
                popup->insertSeparator();
 
1879
                popup->insertItem(tr("Remove group"), 2);
 
1880
                popup->insertItem(tr("Remove group and contacts"), 3);
 
1881
 
 
1882
                // disable if it's not a user group
 
1883
                if(i->groupType() != CVG_USER) {
 
1884
                        popup->setItemEnabled(1,FALSE);
 
1885
                        popup->setItemEnabled(2,FALSE);
 
1886
                        popup->setItemEnabled(3,FALSE);
 
1887
                }
 
1888
 
 
1889
                if(i->groupType() == CVG_OFFLINE || i->groupType() == CVG_AGENTS) {
 
1890
                        popup->insertSeparator();
 
1891
                        popup->insertItem(tr("Hide"), 4);
 
1892
                }
 
1893
 
 
1894
                if(localStatus == STATUS_OFFLINE) {
 
1895
                        popup->setItemEnabled(2,FALSE);
 
1896
                        popup->setItemEnabled(3,FALSE);
 
1897
                }
 
1898
 
 
1899
                int x = popup->exec(pos);
 
1900
                delete popup;
 
1901
 
 
1902
                if(x == -1)
 
1903
                        return;
 
1904
                if(x == 0) {
 
1905
                        QStringList list;
 
1906
 
 
1907
                        list = contactListFromCVGroup(i);
 
1908
 
 
1909
                        // send multi
 
1910
                        actionSendMessage(list);
 
1911
                }
 
1912
                else if(x == 2 && localStatus != STATUS_OFFLINE) {
 
1913
                        int n = QMessageBox::information(cv, CAP(tr("Remove Group")),tr(
 
1914
                        "Removing this group will cause all contacts associated with this group\n"
 
1915
                        "to be associated with no group (affects both online and offline contacts).\n"
 
1916
                        "\n"
 
1917
                        "Proceed?"), tr("&Yes"), tr("&No"));
 
1918
 
 
1919
                        if(n == 0) {
 
1920
                                QStringList list = contactListFromGroup(i->groupName());
 
1921
                                for(QStringList::Iterator it = list.begin(); it != list.end(); ++it)
 
1922
                                        actionGroupChange(*it, "");
 
1923
                        }
 
1924
                }
 
1925
                else if(x == 3 && localStatus != STATUS_OFFLINE) {
 
1926
                        int n = QMessageBox::information(cv, CAP(tr("Remove Group and Contacts")),tr(
 
1927
                        "WARNING!  This will remove all contacts associated with this group (affects\n"
 
1928
                        "both online and offline contacts)!\n"
 
1929
                        "\n"
 
1930
                        "Proceed?"), tr("&Yes"), tr("&No"));
 
1931
 
 
1932
                        if(n == 0) {
 
1933
                                QStringList list = contactListFromGroup(i->groupName());
 
1934
                                for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) {
 
1935
                                        removeEntry(*it);
 
1936
                                        actionRemove(*it);
 
1937
                                }
 
1938
                        }
 
1939
                }
 
1940
                else if(x == 4) {
 
1941
                        if(i->groupType() == CVG_OFFLINE)
 
1942
                                cv->setShowOffline(FALSE);
 
1943
                        if(i->groupType() == CVG_AGENTS)
 
1944
                                cv->setShowAgents(FALSE);
 
1945
                }
 
1946
        }
 
1947
}
 
1948
 
 
1949
void ContactProfile::localUpdate(const JabRosterEntry &e)
 
1950
{
 
1951
        if(e.isAvailable())
 
1952
                localStatus = e.local()->status;
 
1953
        else
 
1954
                localStatus = STATUS_OFFLINE;
 
1955
}
 
1956
 
 
1957
void ContactProfile::scActionDefault(ContactViewItem *i)
 
1958
{
 
1959
        if(i->type() == CV_CONTACT)
 
1960
                actionDefault(i);
 
1961
}
 
1962
 
 
1963
void ContactProfile::scRecvEvent(ContactViewItem *i)
 
1964
{
 
1965
        if(i->type() == CV_CONTACT)
 
1966
                actionRecvEvent(i);
 
1967
}
 
1968
 
 
1969
void ContactProfile::scSendMessage(ContactViewItem *i)
 
1970
{
 
1971
        if(i->type() == CV_CONTACT)
 
1972
                actionSendMessage(i);
 
1973
}
 
1974
 
 
1975
void ContactProfile::scRename(ContactViewItem *i)
 
1976
{
 
1977
        if((i->type() == CV_CONTACT && i->inList()) || (i->type() == CV_GROUP && i->groupType() == CVG_USER)) {
 
1978
                if(i->type() == CV_GROUP)
 
1979
                        i->resetGroupName(FALSE);
 
1980
 
 
1981
                i->setRenameEnabled(0, TRUE);
 
1982
                i->startRename(0);
 
1983
                i->setRenameEnabled(0, FALSE);
 
1984
        }
 
1985
}
 
1986
 
 
1987
void ContactProfile::scGroupChange(const QString &jid, const QString &newgroup)
 
1988
{
 
1989
        actionGroupChange(jid, newgroup);
 
1990
}
 
1991
 
 
1992
void ContactProfile::scHistory(ContactViewItem *i)
 
1993
{
 
1994
        if(i->type() == CV_CONTACT)
 
1995
                actionHistory(i->jid());
 
1996
}
 
1997
 
 
1998
void ContactProfile::scOpenChat(ContactViewItem *i)
 
1999
{
 
2000
        if(i->type() == CV_CONTACT)
 
2001
                actionOpenChat(i->jid());
 
2002
}
 
2003
 
 
2004
void ContactProfile::scAgentSetStatus(ContactViewItem *i, int s)
 
2005
{
 
2006
        if(i->status() != STATUS_OFFLINE || localStatus == STATUS_OFFLINE)
 
2007
                return;
 
2008
 
 
2009
        actionAgentSetStatus(i->jid(), s);
 
2010
}
 
2011
 
 
2012
void ContactProfile::scRemove(ContactViewItem *i)
 
2013
{
 
2014
        ContactProfileItem *pi = cvi2cpi(i);
 
2015
 
 
2016
        if(!(localStatus == STATUS_OFFLINE && i->inList())) {
 
2017
                QString name = i->jid();
 
2018
                if(i->nick() != i->jid())
 
2019
                        name += QString(" (%1)").arg(i->nick());
 
2020
 
 
2021
                int n = 0;
 
2022
                if(i->parentGroupType() != CVG_NOTINLIST) {
 
2023
                        n = QMessageBox::information(cv, CAP(tr("Remove")),
 
2024
                        QString(tr("Are you sure you want to remove <b>%1</b> from your contact list?")).arg(name),
 
2025
                        tr("&Yes"), tr("&No"));
 
2026
                }
 
2027
 
 
2028
                if(n == 0) {
 
2029
                        QString jid = i->jid();
 
2030
                        removeEntry(pi);
 
2031
                        actionRemove(jid);
 
2032
                }
 
2033
        }
 
2034
}
 
2035
 
 
2036
void ContactProfile::doItemRenamed(ContactViewItem *i, const QString &text)
 
2037
{
 
2038
        if(i->type() == CV_CONTACT) {
 
2039
                // no change?
 
2040
                if(text == i->nick())
 
2041
                        return;
 
2042
                if(text.isEmpty()) {
 
2043
                        i->resetNick();
 
2044
                        QMessageBox::information(cv, CAP(tr("Error")), tr("You can't set a blank nickname."));
 
2045
                        return;
 
2046
                }
 
2047
 
 
2048
                i->setNick(text);
 
2049
                actionRename(i, text);
 
2050
        }
 
2051
        else {
 
2052
                // no change?
 
2053
                if(text == i->groupName()) {
 
2054
                        i->resetGroupName();
 
2055
                        return;
 
2056
                }
 
2057
                if(text.isEmpty()) {
 
2058
                        i->resetGroupName();
 
2059
                        QMessageBox::information(cv, CAP(tr("Error")), tr("You can't set a blank nickname."));
 
2060
                        return;
 
2061
                }
 
2062
 
 
2063
                // make sure we don't have it already
 
2064
                QStringList groupList = buildGroupList();
 
2065
                if(qstringlistmatch(groupList, text) != -1) {
 
2066
                        i->resetGroupName();
 
2067
                        QMessageBox::information(cv, CAP(tr("Error")), tr("You already have a group with that name."));
 
2068
                        return;
 
2069
                }
 
2070
 
 
2071
                QString oldName = i->groupName();
 
2072
 
 
2073
                // set group name
 
2074
                i->setGroupName(text);
 
2075
                cv->deferredContactSort();
 
2076
 
 
2077
                // send signal
 
2078
                actionGroupRename(oldName, text);
 
2079
        }
 
2080
}
 
2081
 
 
2082
// return a list of contacts from a CVI group
 
2083
QStringList ContactProfile::contactListFromCVGroup(ContactViewItem *group)
 
2084
{
 
2085
        QStringList list;
 
2086
 
 
2087
        for(ContactViewItem *item = LVI2CVI(group->firstChild()); item ; item = LVI2CVI(item->nextSibling())) {
 
2088
                if(item->type() != CV_CONTACT)
 
2089
                        continue;
 
2090
 
 
2091
                list.append(item->jid());
 
2092
        }
 
2093
 
 
2094
        return list;
 
2095
}
 
2096
 
 
2097
// return a list of contacts associated with "groupName"
 
2098
QStringList ContactProfile::contactListFromGroup(const QString &groupName)
 
2099
{
 
2100
        QStringList list;
 
2101
 
 
2102
        QDictIterator<ContactProfileItem> it(*roster);
 
2103
        ContactViewItem *item;
 
2104
        for(ContactProfileItem *pi; (pi = it.current()); ++it) {
 
2105
                item = pi->cvi;
 
2106
                if(!item->isAgent() && item->group() == groupName)
 
2107
                        list.append(item->jid());
 
2108
        }
 
2109
 
 
2110
        return list;
 
2111
}
 
2112
 
 
2113
int ContactProfile::contactSizeFromCVGroup(ContactViewItem *group)
 
2114
{
 
2115
        int total = 0;
 
2116
 
 
2117
        for(ContactViewItem *item = LVI2CVI(group->firstChild()); item ; item = LVI2CVI(item->nextSibling())) {
 
2118
                if(item->type() != CV_CONTACT)
 
2119
                        continue;
 
2120
 
 
2121
                ++total;
 
2122
        }
 
2123
 
 
2124
        return total;
 
2125
}
 
2126
 
 
2127
// return the number of contacts associated with "groupName"
 
2128
int ContactProfile::contactSizeFromGroup(const QString &groupName)
 
2129
{
 
2130
        int total = 0;
 
2131
 
 
2132
        QDictIterator<ContactProfileItem> it(*roster);
 
2133
        ContactViewItem *item;
 
2134
        for(ContactProfileItem *pi; (pi = it.current()); ++it) {
 
2135
                item = pi->cvi;
 
2136
                if(!item)
 
2137
                        //printf("null item!!!\n");
 
2138
                if(!item->parent()) {
 
2139
                        //printf("cvi: [%s]\n", item->jid().latin1());
 
2140
                        //printf("null parent!!!\n");
 
2141
                        continue;
 
2142
                }
 
2143
                int type = item->parentGroupType();
 
2144
                if((type == CVG_ONLINE || type == CVG_OFFLINE || type == CVG_USER) && item->group() == groupName)
 
2145
                                ++total;
 
2146
        }
 
2147
 
 
2148
        return total;
 
2149
}
 
2150
 
 
2151
void ContactProfile::updateGroupInfo(ContactViewItem *group)
 
2152
{
 
2153
        int inGroup;
 
2154
 
 
2155
        inGroup = contactSizeFromCVGroup(group);
 
2156
 
 
2157
        int type = group->groupType();
 
2158
        if(type == CVG_ONLINE || type == CVG_OFFLINE || type == CVG_USER) {
 
2159
                int total;
 
2160
                QString gname;
 
2161
                if(type == CVG_USER)
 
2162
                        gname = group->groupName();
 
2163
                else
 
2164
                        gname = "";
 
2165
                total = contactSizeFromGroup(gname);
 
2166
 
 
2167
                group->setGroupInfo(QString("(%1/%2)").arg(inGroup).arg(total));
 
2168
        }
 
2169
        else
 
2170
                group->setGroupInfo(QString("(%1)").arg(inGroup));
 
2171
}