~ubuntu-branches/ubuntu/edgy/psi/edgy

« back to all changes in this revision

Viewing changes to src/browserdlg.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jan Niehusmann
  • Date: 2004-06-15 00:10:41 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040615001041-enywb6pcpe4sjsw6
Tags: 0.9.2-1
* New upstream release
* Set KDEDIR for ./configure so kde specific files get installed
* Don't install libpsiwidgets.so. It got installed in /usr/share
  where it doesn't belong. May be included (at a better location)
  later.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * browserdlg.cpp - main dialog for iq:browse protocol
 
3
 * Copyright (C) 2003  Michail Pishchagin
 
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 library; 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 "browserdlg.h"
 
22
 
 
23
#include <qlistview.h>
 
24
#include <qpushbutton.h>
 
25
#include <qcombobox.h>
 
26
#include <qcheckbox.h>
 
27
#include <qstringlist.h>
 
28
#include <qguardedptr.h>
 
29
#include <qptrlist.h>
 
30
#include <qlistview.h>
 
31
#include <qgroupbox.h>
 
32
#include <qpopupmenu.h>
 
33
#include <qlayout.h>
 
34
#include <qobjectlist.h>
 
35
#include <qaction.h>
 
36
#include <qtoolbar.h>
 
37
#include <qstatusbar.h>
 
38
 
 
39
#include "ui_search.h"
 
40
#include "im.h"
 
41
#include "xmpp_tasks.h"
 
42
 
 
43
#include "psicon.h"
 
44
#include "psiaccount.h"
 
45
#include "common.h"
 
46
#include "busywidget.h"
 
47
#include "tasklist.h"
 
48
#include "iconaction.h"
 
49
 
 
50
//----------------------------------------------------------------------------
 
51
// BrowserData -- a shared data struct
 
52
//----------------------------------------------------------------------------
 
53
 
 
54
struct BrowserData {
 
55
        PsiAccount *pa;
 
56
        TaskList *tasks;
 
57
};
 
58
 
 
59
//----------------------------------------------------------------------------
 
60
// BrowserItem
 
61
//----------------------------------------------------------------------------
 
62
 
 
63
class BrowserItem : public QObject, public QListViewItem
 
64
{
 
65
        Q_OBJECT
 
66
public:
 
67
        BrowserItem (const AgentItem &item, BrowserData *p, QListView *parent);
 
68
        BrowserItem (const AgentItem &item, BrowserData *p, QListViewItem *parent);
 
69
 
 
70
        QString text (int c) const;
 
71
        const AgentItem & item() const;
 
72
        void setOpen (bool o);
 
73
 
 
74
public slots:
 
75
        void update(bool preBrowse = true, bool parentPreBrowsing = false);
 
76
 
 
77
private slots:
 
78
        void updateFinished();
 
79
 
 
80
private:
 
81
        class Private;
 
82
        Private *d;
 
83
        friend class Private;
 
84
 
 
85
        void init (const AgentItem &item, BrowserData *p);
 
86
 
 
87
public:
 
88
        BrowserDlg *dlg();
 
89
        bool preBrowsingEnabled();
 
90
};
 
91
 
 
92
class BrowserItem::Private : public QObject
 
93
{
 
94
private:
 
95
        BrowserItem *bItem;
 
96
 
 
97
public:
 
98
        Private (BrowserItem *parent)
 
99
        : QObject (parent)
 
100
        {
 
101
                bItem = parent;
 
102
                parentPreBrowsing = false;
 
103
                alreadyBrowsed = false;
 
104
        }
 
105
 
 
106
        void copyItem (const AgentItem &a)
 
107
        {
 
108
                if ( !a.name().isEmpty() )
 
109
                        item.setName( a.name() );
 
110
                if ( !a.jid().full().isEmpty() )
 
111
                        item.setJid( a.jid() );
 
112
 
 
113
                if ( !a.category().isEmpty() )
 
114
                        item.setCategory( a.category() );
 
115
                if ( !a.type().isEmpty() ) {
 
116
                        // FIXME: workaround for buggy AIM transport (it is also used for an ICQ transport)
 
117
                        if ( !((item.type() == "aim" || item.type() == "icq") && a.type() == "jabber") ) {
 
118
                                item.setType( a.type() );
 
119
                        }
 
120
                }
 
121
 
 
122
                if ( !a.category().isEmpty() )
 
123
                        bItem->setPixmap (0, category2icon(item.category(), item.type()));
 
124
                else
 
125
                        bItem->setPixmap (0, is->status(item.jid(), STATUS_ONLINE));
 
126
 
 
127
                if ( !a.features().list().isEmpty() )
 
128
                        item.setFeatures(a.features());
 
129
        }
 
130
 
 
131
        void preBrowseChilds()
 
132
        {
 
133
                if ( !bItem->preBrowsingEnabled() )
 
134
                        return;
 
135
 
 
136
                // pre-browse all child items
 
137
                BrowserItem *child = (BrowserItem *)bItem->firstChild();
 
138
                while ( child ) {
 
139
                        child->update(false, true); // checkout update(bool, bool) function, if you change this
 
140
 
 
141
                        child = (BrowserItem *)child->nextSibling();
 
142
                }
 
143
        }
 
144
 
 
145
        AgentItem item;
 
146
        BrowserData *p;
 
147
        bool isRoot;
 
148
        BrowserItem *root;
 
149
        bool preBrowsing, parentPreBrowsing;
 
150
        bool alreadyBrowsed;
 
151
};
 
152
 
 
153
BrowserItem::BrowserItem (const AgentItem &item, BrowserData *p, QListView *parent)
 
154
: QListViewItem (parent)
 
155
{
 
156
        init (item, p);
 
157
        d->isRoot = true;
 
158
}
 
159
 
 
160
BrowserItem::BrowserItem (const AgentItem &item, BrowserData *p, QListViewItem *parent)
 
161
: QListViewItem (parent)
 
162
{
 
163
        init (item, p);
 
164
        d->isRoot = false;
 
165
}
 
166
 
 
167
void BrowserItem::init (const AgentItem &item, BrowserData *p)
 
168
{
 
169
        d = new Private (this);
 
170
        d->item = (AgentItem)item;
 
171
        d->p = p;
 
172
 
 
173
        // find 'root' BrowserItem
 
174
        d->root = this;
 
175
        while ( d->root->QListViewItem::parent() )
 
176
                d->root = (BrowserItem *)d->root->QListViewItem::parent();
 
177
 
 
178
        d->copyItem(item); // hmm... guess this is too much, concerning that we do 'd->item = item' already
 
179
 
 
180
        if ( !preBrowsingEnabled() )
 
181
                setExpandable (true);
 
182
}
 
183
 
 
184
QString BrowserItem::text (int c) const
 
185
{
 
186
        if ( c == 0 )
 
187
                return d->item.name();
 
188
        else if ( c == 1 )
 
189
                return d->item.jid().full();
 
190
        return "Oops :)";
 
191
}
 
192
 
 
193
const AgentItem & BrowserItem::item() const
 
194
{
 
195
        return d->item;
 
196
}
 
197
 
 
198
BrowserDlg *BrowserItem::dlg()
 
199
{
 
200
        return (BrowserDlg *)listView()->parent()->parent();
 
201
}
 
202
 
 
203
bool BrowserItem::preBrowsingEnabled()
 
204
{
 
205
        return dlg()->cb_preBrowse->isChecked();
 
206
}
 
207
 
 
208
void BrowserItem::setOpen (bool o)
 
209
{
 
210
        if ( o ) {
 
211
                if ( !childCount() )
 
212
                        update();
 
213
                else
 
214
                        d->preBrowseChilds();
 
215
        }
 
216
 
 
217
        QListViewItem::setOpen (o);
 
218
}
 
219
 
 
220
void BrowserItem::update(bool preBrowse, bool parentPreBrowsing)
 
221
{
 
222
        if ( preBrowse == false && parentPreBrowsing == true ) {
 
223
                // to save some traffic
 
224
                if ( d->alreadyBrowsed )
 
225
                        return;
 
226
 
 
227
                // FIXME: currently, JUD doesn't seem to answer to browsing requests
 
228
                if ( d->item.category() == "service" && d->item.type() == "jud" )
 
229
                        return;
 
230
        }
 
231
 
 
232
        if ( d->root == this )
 
233
                preBrowse = true;
 
234
 
 
235
        if ( !preBrowsingEnabled() )
 
236
                preBrowse = false;
 
237
 
 
238
        d->preBrowsing = preBrowse;
 
239
        d->parentPreBrowsing = parentPreBrowsing;
 
240
 
 
241
        JT_Browse *jt = new JT_Browse(d->p->pa->client()->rootTask());
 
242
        connect(jt, SIGNAL(finished()), SLOT(updateFinished()));
 
243
        jt->get(d->item.jid());
 
244
        jt->go(true);
 
245
        d->p->tasks->append(jt);
 
246
}
 
247
 
 
248
void BrowserItem::updateFinished()
 
249
{
 
250
        QObject *senderObj = (QObject *)sender();
 
251
        JT_GetServices *jtAgents = 0;
 
252
        JT_Browse *jtBrowse = (senderObj->inherits("XMPP::JT_Browse") ? (JT_Browse *)senderObj : 0);
 
253
        if ( !jtBrowse )
 
254
                jtAgents = (senderObj->inherits("XMPP::JT_GetServices") ? (JT_GetServices *)senderObj : 0);
 
255
 
 
256
        if( (jtBrowse && jtBrowse->success()) || (jtAgents && jtAgents->success()) ) {
 
257
                if ( jtBrowse )
 
258
                        d->copyItem ( jtBrowse->root() );
 
259
                else {
 
260
                        // iq:agents doesn't have as much useful info as iq:browse has,
 
261
                        // so we're gonna to provide it by ourselves :-)
 
262
                        AgentItem ai;
 
263
 
 
264
                        ai.setName     ( "Jabber Service" );
 
265
                        ai.setCategory ( "services" );
 
266
                        ai.setType     ( "jabber" );
 
267
 
 
268
                        d->copyItem ( ai );
 
269
                }
 
270
 
 
271
                if ( !d->parentPreBrowsing )
 
272
                        QListViewItem::setOpen (true);
 
273
 
 
274
                AgentList agents;
 
275
                if ( jtBrowse )
 
276
                        agents = jtBrowse->agents();
 
277
                else
 
278
                        agents = jtAgents->agents();
 
279
 
 
280
                // add/update items
 
281
                for(AgentList::ConstIterator it = agents.begin(); it != agents.end(); ++it) {
 
282
                        const AgentItem a = *it;
 
283
                        bool found = false;
 
284
 
 
285
                        BrowserItem *child = (BrowserItem *)firstChild();
 
286
                        while ( child ) {
 
287
                                if ( child->item().jid().full() == a.jid().full() ) {
 
288
                                        child->d->copyItem ( a );
 
289
                                        child->repaint();
 
290
                                        found = true;
 
291
                                        break;
 
292
                                }
 
293
 
 
294
                                child = (BrowserItem *)child->nextSibling();
 
295
                        }
 
296
 
 
297
                        if ( !found )
 
298
                                new BrowserItem (a, d->p, this);
 
299
                }
 
300
 
 
301
                // check for removed items
 
302
                QPtrList<BrowserItem> removeList;
 
303
                removeList.setAutoDelete (true);
 
304
                BrowserItem *child = (BrowserItem *)firstChild();
 
305
                while ( child ) {
 
306
                        bool found = false;
 
307
 
 
308
                        for(AgentList::ConstIterator it = agents.begin(); it != agents.end(); ++it) {
 
309
                                const AgentItem a = *it;
 
310
 
 
311
                                if ( child->item().jid().full() == a.jid().full() ) {
 
312
                                        found = true;
 
313
                                        break;
 
314
                                }
 
315
                        }
 
316
 
 
317
                        if ( !found )
 
318
                                removeList.append ( child ); // items will be deleted later
 
319
 
 
320
                        child = (BrowserItem *)child->nextSibling();
 
321
                }
 
322
 
 
323
                if ( jtBrowse && !d->parentPreBrowsing ) // comment this to auto-browse entire server tree
 
324
                        d->preBrowseChilds();
 
325
 
 
326
                // don't forget to remove '+' (or '-') sign in case, that the child list is empty
 
327
                setExpandable ( !agents.isEmpty() );
 
328
 
 
329
                // root item is initially hidden
 
330
                if ( d->isRoot )
 
331
                        setVisible (true);
 
332
        }
 
333
        else {
 
334
                setExpandable ( false );
 
335
 
 
336
                if ( jtBrowse && d->isRoot ) {
 
337
                        // there are chances, that server just doesn't support browsing (this is
 
338
                        // true for the Jabber Inc. commercial server). Go to jabber.com for
 
339
                        // example
 
340
 
 
341
                        JT_GetServices *jt = new JT_GetServices(d->p->pa->client()->rootTask());
 
342
                        connect(jt, SIGNAL(finished()), SLOT(updateFinished()));
 
343
                        jt->get(d->item.jid());
 
344
                        jt->go(true);
 
345
                        d->p->tasks->append(jt);
 
346
                }
 
347
                else {
 
348
                        if ( !d->parentPreBrowsing ) {
 
349
                                QString error;
 
350
                                if ( jtBrowse )
 
351
                                        error = jtBrowse->statusString();
 
352
                                else
 
353
                                        error = jtAgents->statusString();
 
354
                                QMessageBox::critical(dlg(), tr("Error"), tr("There was an error browsing the <b>%1</b>.\nReason: %2").arg(item().jid().full()).arg(error));
 
355
                        }
 
356
                }
 
357
        }
 
358
 
 
359
        dlg()->itemSelected (dlg()->lv_browse->selectedItem());
 
360
 
 
361
        d->alreadyBrowsed = true;
 
362
        d->preBrowsing = false;
 
363
        d->parentPreBrowsing = false;
 
364
        repaint();
 
365
}
 
366
 
 
367
//----------------------------------------------------------------------------
 
368
// BrowserDlg
 
369
//----------------------------------------------------------------------------
 
370
 
 
371
class BrowserDlg::Private : public QObject
 
372
{
 
373
        Q_OBJECT
 
374
 
 
375
public:
 
376
        Private (BrowserDlg *parent, PsiAccount *pa)
 
377
        : QObject(parent)
 
378
        {
 
379
                dlg = parent;
 
380
                data.pa = pa;
 
381
 
 
382
                busy = parent->busy;
 
383
                connect(busy, SIGNAL(destroyed(QObject *)), SLOT(objectDestroyed(QObject *)));
 
384
 
 
385
                data.tasks = new TaskList;
 
386
                connect(data.tasks, SIGNAL(started()), SLOT(itemUpdateStarted()));
 
387
                connect(data.tasks, SIGNAL(finished()), SLOT(itemUpdateFinished()));
 
388
 
 
389
                // create actions
 
390
                actBrowse = new IconAction (tr("Browse"), "psi/jabber", tr("&Browse"), 0, dlg);
 
391
                connect (actBrowse, SIGNAL(activated()), SLOT(actionBrowse()));
 
392
                actRefresh = new IconAction (tr("Refresh"), "psi/reload", tr("&Refresh"), 0, dlg);
 
393
                connect (actRefresh, SIGNAL(activated()), SLOT(actionRefresh()));
 
394
                actStop = new IconAction (tr("Stop"), "psi/stop", tr("Sto&p"), 0, dlg);
 
395
                connect (actStop, SIGNAL(activated()), SLOT(actionStop()));
 
396
 
 
397
                actRegister = new IconAction (tr("Register"), "psi/register", tr("&Register"), 0, dlg);
 
398
                connect (actRegister, SIGNAL(activated()), SLOT(actionRegister()));
 
399
                actSearch = new IconAction (tr("Search"), "psi/search", tr("&Search"), 0, dlg);
 
400
                connect (actSearch, SIGNAL(activated()), SLOT(actionSearch()));
 
401
                actJoin = new IconAction (tr("Join"), "psi/groupChat", tr("&Join"), 0, dlg);
 
402
                connect (actJoin, SIGNAL(activated()), SLOT(actionJoin()));
 
403
 
 
404
                actInfo = new IconAction (tr("Info"), "psi/vCard", tr("&Info"), 0, dlg);
 
405
                connect (actInfo, SIGNAL(activated()), SLOT(actionInfo()));
 
406
 
 
407
                /*actTime = new QAction (tr("Get Time"), QIconSet(is.getTime), tr("Get &Time"), 0, dlg);
 
408
                connect (actTime, SIGNAL(activated()), SLOT(actionGetTime()));
 
409
                actLast = new QAction (tr("Last Time"), QIconSet(is.getLastTime), tr("&Last Time"), 0, dlg);
 
410
                connect (actLast, SIGNAL(activated()), SLOT(actionGetLast()));
 
411
                actVersion = new QAction (tr("Get Version"), QIconSet(is.getVersion), tr("Get &Version"), 0, dlg);
 
412
                connect (actVersion, SIGNAL(activated()), SLOT(actionVersion()));
 
413
                actMessage = new QAction (tr("Send Message"), QIconSet(is.message.base()), tr("Send &Message"), 0, dlg);
 
414
                connect (actMessage, SIGNAL(activated()), SLOT(actionMessage()));
 
415
                actChat = new QAction (tr("Open Chat"), QIconSet(is.chat.base()), tr("Open &Chat"), 0, dlg);
 
416
                connect (actChat, SIGNAL(activated()), SLOT(actionChat()));
 
417
                actAdd = new QAction (tr("Add to roster"), QIconSet(is.add), tr("Add to &roster"), 0, dlg);
 
418
                connect (actAdd, SIGNAL(activated()), SLOT(actionAdd()));*/
 
419
 
 
420
                actBack = new IconAction (tr("Back"), "psi/arrowLeft", tr("&Back"), 0, dlg);
 
421
                connect (actBack, SIGNAL(activated()), SLOT(actionBack()));
 
422
                actForward = new IconAction (tr("Forward"), "psi/arrowRight", tr("&Forward"), 0, dlg);
 
423
                connect (actForward, SIGNAL(activated()), SLOT(actionForward()));
 
424
 
 
425
                toolBar = new QToolBar(dlg);
 
426
 
 
427
                actBack->addTo(toolBar);
 
428
                actBrowse->addTo(toolBar);
 
429
                actForward->addTo(toolBar);
 
430
 
 
431
                toolBar->addSeparator();
 
432
                actRefresh->addTo(toolBar);
 
433
                actStop->addTo(toolBar);
 
434
 
 
435
                toolBar->addSeparator();
 
436
                actRegister->addTo(toolBar);
 
437
                actSearch->addTo(toolBar);
 
438
                actJoin->addTo(toolBar);
 
439
 
 
440
                toolBar->addSeparator();
 
441
                actInfo->addTo(toolBar);
 
442
                /*actVersion->addTo(toolBar);
 
443
                actTime->addTo(toolBar);
 
444
                actLast->addTo(toolBar);
 
445
 
 
446
                toolBar->addSeparator();
 
447
                actMessage->addTo(toolBar);
 
448
                actChat->addTo(toolBar);
 
449
 
 
450
                toolBar->addSeparator();
 
451
                actAdd->addTo(toolBar);*/
 
452
 
 
453
                toolBar->setStretchableWidget(new StretchWidget(toolBar));
 
454
                pa->accountLabel(toolBar, true);
 
455
 
 
456
                backHistory.setAutoDelete(true);
 
457
                forwardHistory.setAutoDelete(true);
 
458
 
 
459
                disableButtons();
 
460
                actStop->setEnabled(false); // stop action is not handled by disableButtons()
 
461
                updateBackForward(); // same applies to back & forward
 
462
        }
 
463
 
 
464
        ~Private()
 
465
        {
 
466
                delete data.tasks;
 
467
        }
 
468
 
 
469
public slots:
 
470
        void objectDestroyed(QObject *obj)
 
471
        {
 
472
                if ( obj == busy )
 
473
                        busy = 0;
 
474
        }
 
475
 
 
476
        void actionBrowse()
 
477
        {
 
478
                BrowserItem *it = (BrowserItem *)dlg->lv_browse->selectedItem();
 
479
                if ( !it )
 
480
                        return;
 
481
 
 
482
                doBrowse( it->item().jid().full() );
 
483
        }
 
484
 
 
485
        void actionRefresh()
 
486
        {
 
487
                BrowserItem *it = (BrowserItem *)dlg->lv_browse->selectedItem();
 
488
                if ( !it )
 
489
                        return;
 
490
 
 
491
                it->update();
 
492
        }
 
493
 
 
494
        void actionStop()
 
495
        {
 
496
                actStop->setEnabled(false);
 
497
                if ( busy )
 
498
                             busy->stop();
 
499
                data.tasks->clear();
 
500
        }
 
501
 
 
502
        void actionRegister()
 
503
        {
 
504
                BrowserItem *it = (BrowserItem *)dlg->lv_browse->selectedItem();
 
505
                if ( !it )
 
506
                        return;
 
507
 
 
508
                emit dlg->signalRegister( it->item().jid() );
 
509
        }
 
510
 
 
511
        void actionSearch()
 
512
        {
 
513
                BrowserItem *it = (BrowserItem *)dlg->lv_browse->selectedItem();
 
514
                if ( !it )
 
515
                        return;
 
516
 
 
517
                emit dlg->signalSearch( it->item().jid() );
 
518
        }
 
519
 
 
520
        void actionJoin()
 
521
        {
 
522
                BrowserItem *it = (BrowserItem *)dlg->lv_browse->selectedItem();
 
523
                if ( !it )
 
524
                        return;
 
525
 
 
526
                emit dlg->signalJoin( it->item().jid() );
 
527
        }
 
528
 
 
529
        void actionInfo()
 
530
        {
 
531
                BrowserItem *it = (BrowserItem *)dlg->lv_browse->selectedItem();
 
532
                if ( !it )
 
533
                        return;
 
534
 
 
535
                data.pa->actionInfo( it->item().jid() );
 
536
        }
 
537
 
 
538
        /*void actionGetTime()
 
539
        {
 
540
                BrowserItem *it = (BrowserItem *)dlg->lv_browse->selectedItem();
 
541
                if ( !it )
 
542
                        return;
 
543
 
 
544
                // emit ...
 
545
        }
 
546
 
 
547
        void actionGetLast()
 
548
        {
 
549
                BrowserItem *it = (BrowserItem *)dlg->lv_browse->selectedItem();
 
550
                if ( !it )
 
551
                        return;
 
552
 
 
553
                // emit ...
 
554
        }*/
 
555
 
 
556
 
 
557
        void actionBack()
 
558
        {
 
559
                // add current selection to forward history
 
560
                QListViewItem *item = dlg->lv_browse->firstChild();
 
561
                if ( item )
 
562
                        dlg->lv_browse->takeItem( item );
 
563
 
 
564
                forwardHistory.append( new History(jid, item) );
 
565
 
 
566
                // now, take info from back history...
 
567
                History *h = backHistory.last();
 
568
                Jid j            = h->jid();
 
569
                QListViewItem *i = h->takeItem();
 
570
                backHistory.removeLast();
 
571
 
 
572
                // and restore view
 
573
                doBrowse(j.full(), true, i);
 
574
        }
 
575
 
 
576
        void actionForward()
 
577
        {
 
578
                // add current selection to back history
 
579
                QListViewItem *item = dlg->lv_browse->firstChild();
 
580
                if ( item )
 
581
                        dlg->lv_browse->takeItem( item );
 
582
 
 
583
                backHistory.append( new History(jid, item) );
 
584
 
 
585
                // now, take info from forward history...
 
586
                History *h = forwardHistory.last();
 
587
                Jid j            = h->jid();
 
588
                QListViewItem *i = h->takeItem();
 
589
                forwardHistory.removeLast();
 
590
 
 
591
                // and restore view
 
592
                doBrowse(j.full(), true, i);
 
593
        }
 
594
 
 
595
 
 
596
        void itemUpdateStarted()
 
597
        {
 
598
                actStop->setEnabled(true);
 
599
                if ( busy )
 
600
                        busy->start();
 
601
        }
 
602
 
 
603
        void itemUpdateFinished()
 
604
        {
 
605
                actStop->setEnabled(false);
 
606
                if ( busy )
 
607
                        busy->stop();
 
608
        }
 
609
 
 
610
        void doBrowse(const QString &host = QString::null, bool backForwardClicked = false, QListViewItem *rootItem = 0)
 
611
        {
 
612
                PsiAccount *pa = data.pa;
 
613
                if(!pa->checkConnected(dlg))
 
614
                        return;
 
615
 
 
616
                Jid j;
 
617
                QString h = host;
 
618
 
 
619
                if ( h.isEmpty() )
 
620
                        h = dlg->cb_browse->currentText();
 
621
 
 
622
                j = h.stripWhiteSpace();
 
623
 
 
624
                if ( !j.isValid() )
 
625
                        return;
 
626
 
 
627
                if ( !backForwardClicked && jid.full() != j.full() ) {
 
628
                        QListViewItem *item = dlg->lv_browse->firstChild();
 
629
                        if ( item )
 
630
                                dlg->lv_browse->takeItem( item );
 
631
 
 
632
                        backHistory.append( new History(jid, item) );
 
633
                        forwardHistory.clear();
 
634
                }
 
635
 
 
636
                updateBackForward();
 
637
 
 
638
                jid = j;
 
639
                pa->psi()->recentBrowseAdd( jid.full() );
 
640
                dlg->cb_browse->clear();
 
641
                dlg->cb_browse->insertStringList(pa->psi()->recentBrowseList());
 
642
 
 
643
                data.tasks->clear(); // also will call all all necessary functions
 
644
                disableButtons();
 
645
 
 
646
                if ( !rootItem ) {
 
647
                        dlg->lv_browse->clear();
 
648
 
 
649
                        AgentItem ai;
 
650
                        ai.setJid( j );
 
651
                        BrowserItem *root = new BrowserItem (ai, &data, dlg->lv_browse);
 
652
                        root->setVisible (false); // don't confuse users
 
653
 
 
654
                        root->setOpen(true); // begin browsing
 
655
                }
 
656
                else {
 
657
                        dlg->lv_browse->insertItem( rootItem );
 
658
 
 
659
                        // fixes multiple selection bug
 
660
                        QListViewItemIterator it( dlg->lv_browse );
 
661
                        while ( it.current() ) {
 
662
                                QListViewItem *item = it.current();
 
663
                                ++it;
 
664
 
 
665
                                if ( item->isSelected() )
 
666
                                        for (int i = 0; i <= 1; i++) // its boring to write same line twice :)
 
667
                                                dlg->lv_browse->setSelected(item, (bool)i);
 
668
                        }
 
669
                }
 
670
        }
 
671
 
 
672
public:
 
673
        BrowserDlg *dlg;
 
674
        Jid jid;
 
675
        BrowserData data;
 
676
        BusyWidget *busy;
 
677
 
 
678
        QToolBar *toolBar;
 
679
        QAction *actBrowse, *actRegister, *actSearch,
 
680
                *actJoin, *actInfo, /* *actTime, *actVersion,
 
681
                *actLast,*/ *actRefresh, *actStop,
 
682
                *actMessage, *actChat, *actAdd;
 
683
 
 
684
        QAction *actBack, *actForward;
 
685
 
 
686
        // helper class for use in toolbar
 
687
        class StretchWidget : public QWidget
 
688
        {
 
689
        public:
 
690
                StretchWidget(QWidget *parent)
 
691
                : QWidget(parent)
 
692
                {
 
693
                        setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
 
694
                }
 
695
        };
 
696
 
 
697
        // helper class to store browser history
 
698
        class History {
 
699
        private:
 
700
                QListViewItem *item;
 
701
                Jid j;
 
702
        public:
 
703
                History(Jid jj, QListViewItem *it) {
 
704
                        item = it;
 
705
                        j = jj;
 
706
                }
 
707
 
 
708
                ~History() {
 
709
                        if ( item )
 
710
                                delete item;
 
711
                }
 
712
 
 
713
                QListViewItem *takeItem() {
 
714
                        QListViewItem *i = item;
 
715
                        item = 0;
 
716
                        return i;
 
717
                }
 
718
 
 
719
                Jid jid() {
 
720
                        return j;
 
721
                }
 
722
        };
 
723
 
 
724
        typedef QPtrList<History> HistoryList;
 
725
        HistoryList backHistory, forwardHistory;
 
726
 
 
727
        void disableButtons()
 
728
        {
 
729
                actRefresh->setEnabled(false);
 
730
                //actStop->setEnabled(false);
 
731
 
 
732
                actRegister->setEnabled(false);
 
733
                actSearch->setEnabled(false);
 
734
                actJoin->setEnabled(false);
 
735
 
 
736
                actBrowse->setEnabled(false);
 
737
                actInfo->setEnabled(false);
 
738
 
 
739
                /*actTime->setEnabled(false);
 
740
                actLast->setEnabled(false);
 
741
                actVersion->setEnabled(false);
 
742
                actMessage->setEnabled(false);
 
743
                actChat->setEnabled(false);
 
744
                actAdd->setEnabled(false);*/
 
745
        }
 
746
 
 
747
        void enableButtons(const AgentItem &agent)
 
748
        {
 
749
                const Features &f = agent.features();
 
750
 
 
751
                actBrowse->setEnabled(true);
 
752
                actRefresh->setEnabled(true);
 
753
                //actStop->setEnabled(false);
 
754
                actRegister->setEnabled( f.canRegister() );
 
755
                actSearch->setEnabled( f.canSearch() );
 
756
                actJoin->setEnabled( f.canGroupchat() );
 
757
                actInfo->setEnabled(true);
 
758
                /*actTime->setEnabled(false);
 
759
                actLast->setEnabled(false);*/
 
760
        }
 
761
 
 
762
        bool eventFilter (QObject *object, QEvent *event)
 
763
        {
 
764
                if ( object == dlg->lv_browse ) {
 
765
                        if ( event->type() == QEvent::ContextMenu ) {
 
766
                                QContextMenuEvent *e = (QContextMenuEvent *)event;
 
767
 
 
768
                                BrowserItem *item = (BrowserItem *)dlg->lv_browse->selectedItem();
 
769
                                if ( !item )
 
770
                                        return true;
 
771
                                enableButtons ( item->item() );
 
772
 
 
773
                                QPopupMenu p;
 
774
 
 
775
                                actBrowse->addTo (&p);
 
776
                                actRefresh->addTo (&p);
 
777
                                actStop->addTo (&p);
 
778
 
 
779
                                p.insertSeparator();
 
780
                                actRegister->addTo (&p);
 
781
                                actSearch->addTo (&p);
 
782
                                actJoin->addTo (&p);
 
783
 
 
784
                                p.insertSeparator();
 
785
                                actInfo->addTo (&p);
 
786
                                /*actVersion->addTo (&p);
 
787
                                actTime->addTo (&p);
 
788
                                actLast->addTo (&p);
 
789
 
 
790
                                p.insertSeparator();
 
791
                                actMessage->addTo (&p);
 
792
                                actChat->addTo (&p);
 
793
 
 
794
                                p.insertSeparator();
 
795
                                actAdd->addTo (&p);*/
 
796
 
 
797
                                e->accept();
 
798
                                p.exec ( e->globalPos() );
 
799
 
 
800
                                return true;
 
801
                        }
 
802
                }
 
803
 
 
804
                return false;
 
805
        }
 
806
 
 
807
        void updateBackForward()
 
808
        {
 
809
                actBack->setEnabled( !backHistory.isEmpty() );
 
810
                actForward->setEnabled( !forwardHistory.isEmpty() );
 
811
        }
 
812
};
 
813
 
 
814
BrowserDlg::BrowserDlg (const Jid &j, PsiAccount *pa)
 
815
: BrowserUI (0, 0, WDestructiveClose)
 
816
{
 
817
        d = new Private (this, pa);
 
818
        pa->dialogRegister(this);
 
819
        d->jid = j;
 
820
 
 
821
        setCaption(CAP(caption()));
 
822
        setIcon(is->transportStatus("transport", STATUS_ONLINE));
 
823
 
 
824
        cb_browse->setInsertionPolicy(QComboBox::NoInsertion);
 
825
        cb_browse->insertStringList(pa->psi()->recentBrowseList());
 
826
        cb_browse->setFocus();
 
827
        connect(cb_browse, SIGNAL(activated(const QString &)), d, SLOT(doBrowse()));
 
828
 
 
829
        pb_browse->setDefault(true);
 
830
        cb_browse->setCurrentText(d->jid.full());
 
831
 
 
832
        connect (pb_browse, SIGNAL(clicked()), d, SLOT(doBrowse()));
 
833
 
 
834
        lv_browse->installEventFilter (d);
 
835
 
 
836
        statusBar()->hide();
 
837
 
 
838
        X11WM_CLASS("browser");
 
839
 
 
840
        if(pa->loggedIn())
 
841
                doBrowse();
 
842
}
 
843
 
 
844
BrowserDlg::~BrowserDlg()
 
845
{
 
846
        d->data.pa->dialogUnregister(this);
 
847
}
 
848
 
 
849
void BrowserDlg::doBrowse(const QString &host)
 
850
{
 
851
        d->doBrowse(host, true);
 
852
}
 
853
 
 
854
void BrowserDlg::itemSelected (QListViewItem *item)
 
855
{
 
856
        BrowserItem *it = (BrowserItem *)item;
 
857
        if ( !it ) {
 
858
                d->disableButtons();
 
859
                return;
 
860
        }
 
861
 
 
862
        const AgentItem agent = it->item();
 
863
        d->enableButtons ( agent );
 
864
}
 
865
 
 
866
void BrowserDlg::itemDoubleclicked (QListViewItem *item)
 
867
{
 
868
        BrowserItem *it = (BrowserItem *)item;
 
869
        if ( !it )
 
870
                return;
 
871
 
 
872
        const AgentItem a = it->item();
 
873
        const Features &f = a.features();
 
874
 
 
875
        // set the prior state of item
 
876
        // FIXME: causes minor flickering
 
877
        if ( f.canGroupchat() || f.canRegister() || f.canSearch() ) {
 
878
                if ( !it->isOpen() ) {
 
879
                        if ( it->isExpandable() || it->childCount() )
 
880
                                it->setOpen( true );
 
881
                }
 
882
                else {
 
883
                        it->setOpen( false );
 
884
                }
 
885
        }
 
886
 
 
887
        // trigger default action
 
888
        if ( f.canGroupchat() ) {
 
889
                d->actionJoin();
 
890
        }
 
891
        else {
 
892
                bool searchFirst = a.category() == "service" && a.type() == "jud";
 
893
 
 
894
                if ( !searchFirst ) {
 
895
                        if ( f.canRegister() )
 
896
                                d->actionRegister();
 
897
                        else if ( f.canSearch() )
 
898
                                d->actionSearch();
 
899
                }
 
900
                else {
 
901
                        if ( f.canSearch() )
 
902
                                d->actionSearch();
 
903
                        else if ( f.canRegister() )
 
904
                                d->actionRegister();
 
905
                }
 
906
        }
 
907
}
 
908
 
 
909
#include "browserdlg.moc"