~ubuntu-branches/ubuntu/vivid/psi/vivid

« back to all changes in this revision

Viewing changes to src/psicon.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jan Niehusmann
  • Date: 2008-08-28 18:46:52 UTC
  • mfrom: (1.2.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20080828184652-iiik12dl91nq7cdi
Tags: 0.12-2
Uploading to unstable (Closes: Bug#494352)

Show diffs side-by-side

added added

removed removed

Lines of Context:
29
29
#include <qcolor.h>
30
30
#include <qimage.h>
31
31
#include <qpixmapcache.h>
 
32
#include <QFile>
32
33
#include <QPixmap>
33
34
#include <QList>
34
35
#include <QImageReader>
35
36
#include <QMessageBox>
 
37
#include <QDir>
36
38
 
37
39
#include "s5b.h"
38
40
#include "psiaccount.h"
 
41
#include "activeprofiles.h"
39
42
#include "accountadddlg.h"
40
43
#include "psiiconset.h"
41
44
#include "contactview.h"
80
83
#include "pluginmanager.h"
81
84
#endif
82
85
#include "psicontactlist.h"
 
86
#include "dbus.h"
83
87
#include "tipdlg.h"
84
88
#include "shortcutmanager.h"
85
89
#include "globalshortcutmanager.h"
86
90
#include "desktoputil.h"
 
91
#include "tabmanager.h"
87
92
 
88
93
 
89
94
#ifdef Q_WS_MAC
119
124
public slots:
120
125
        void playSound(QString file)
121
126
        {
122
 
                if ( file.isEmpty() || !useSound )
 
127
                if ( file.isEmpty() || !PsiOptions::instance()->getOption("options.ui.notifications.sounds.enable").toBool() )
123
128
                        return;
124
129
 
125
130
                soundPlay(file);
170
175
        QString className;
171
176
};
172
177
 
173
 
class PsiCon::Private
 
178
class PsiCon::Private : public QObject
174
179
{
 
180
        Q_OBJECT
175
181
public:
176
182
        Private(PsiCon *parent)
177
183
                : contactList(0), iconSelect(0)
178
184
        {
179
185
                psi = parent;
180
 
                //the list 'owns' the tabs
181
 
                tabs.setAutoDelete( true );
182
 
                tabControlledChats.setAutoDelete( false );
183
186
        }
184
187
 
185
188
        ~Private()
188
191
                        delete iconSelect;
189
192
        }
190
193
 
191
 
        void saveProfile(UserAccountList acc = UserAccountList())
 
194
        void saveProfile(UserAccountList acc)
192
195
        {
193
 
                pro.recentGCList = recentGCList;
194
 
                pro.recentBrowseList = recentBrowseList;
195
 
                pro.lastStatusString = lastStatusString;
196
 
                pro.useSound = useSound;
197
 
                pro.prefs = option;
198
 
                if ( proxy )
199
 
                        pro.proxyList = proxy->itemList();
200
 
 
201
 
                if ( acc.count() )
202
 
                        pro.acc = acc;
203
 
 
204
 
                pro.toFile(pathToProfileConfig(activeProfile));
 
196
                // clear it
 
197
                accountTree.removeOption("accounts", true);
 
198
                // save accounts with known base
 
199
                QSet<QString> cbases;
 
200
                foreach(UserAccount ua, acc) {
 
201
                        if (!ua.optionsBase.isEmpty()) {
 
202
                                ua.toOptions(&accountTree);
 
203
                                cbases += ua.optionsBase;
 
204
                        }
 
205
                }
 
206
                // save new accounts
 
207
                int idx = 0;
 
208
                foreach(UserAccount ua, acc) {
 
209
                        if (ua.optionsBase.isEmpty()) {
 
210
                                QString base;
 
211
                                do {
 
212
                                        base = "accounts.a"+QString::number(idx++);
 
213
                                } while (cbases.contains(base));
 
214
                                cbases += base;
 
215
                                ua.toOptions(&accountTree, base);
 
216
                        }
 
217
                }
 
218
                QFile accountsFile(pathToProfile( activeProfile ) + "/accounts.xml");   
 
219
                accountTree.saveOptions(accountsFile.fileName(), "accounts", ApplicationInfo::optionsNS(), ApplicationInfo::version());;
 
220
                
205
221
        }
206
222
 
 
223
private slots:
207
224
        void updateIconSelect()
208
225
        {
209
226
                Iconset iss;
216
233
                }
217
234
 
218
235
                iconSelect->setIconset(iss);
 
236
                QPixmapCache::clear();
219
237
        }
220
238
 
 
239
public:
221
240
        PsiCon* psi;
222
241
        PsiContactList* contactList;
223
 
        UserProfile pro;
224
 
        QString lastStatusString;
 
242
        OptionsMigration optionsMigration;
 
243
        OptionsTree accountTree;
225
244
        MainWin *mainwin;
226
245
        Idle idle;
227
246
        QList<item_dialog*> dialogList;
228
 
        Q3PtrList<TabDlg> tabs;
229
 
        Q3PtrList<ChatDlg> tabControlledChats;
230
247
        int eventId;
231
 
        QStringList recentGCList, recentBrowseList, recentNodeList;
 
248
        QStringList recentNodeList; // FIXME move this to options system?
232
249
        EDB *edb;
233
250
        S5BServer *s5bServer;
234
251
        ProxyManager *proxy;
235
252
        IconSelectPopup *iconSelect;
236
 
        QRect mwgeom;
237
253
        FileTransDlg *ftwin;
238
254
        PsiActionList *actionList;
239
255
        //GlobalAccelManager *globalAccelManager;
240
256
        TuneController* tuneController;
241
257
        QMenuBar* defaultMenuBar;
 
258
        CapsRegistry* capsRegistry;
 
259
        TabManager *tabManager;
242
260
};
243
261
 
244
262
//----------------------------------------------------------------------------
251
269
        //pdb(DEBUG_JABCON, QString("%1 v%2\n By Justin Karneges\n    infiniti@affinix.com\n\n").arg(PROG_NAME).arg(PROG_VERSION));
252
270
 
253
271
        d = new Private(this);
 
272
        d->tabManager = new TabManager(this);
254
273
 
255
 
        d->lastStatusString = "";
256
 
        useSound = false;
257
274
        d->mainwin = 0;
258
275
        d->ftwin = 0;
259
276
 
266
283
 
267
284
        d->actionList = 0;
268
285
        d->defaultMenuBar = new QMenuBar(0);
 
286
        d->capsRegistry = new CapsRegistry();
 
287
        connect(d->capsRegistry, SIGNAL(registered(const CapsSpec&)), SLOT(saveCapabilities()));
269
288
}
270
289
 
271
290
PsiCon::~PsiCon()
272
291
{
273
292
        deinit();
274
293
 
 
294
        saveCapabilities();
 
295
        delete d->capsRegistry;
 
296
 
275
297
        delete d->actionList;
276
298
        delete d->edb;
277
299
        delete d->defaultMenuBar;
 
300
        delete d->tabManager;
278
301
        delete d;
279
302
}
280
303
 
281
304
bool PsiCon::init()
282
305
{
 
306
        // check active profiles
 
307
        if (!ActiveProfiles::instance()->setThisProfile(activeProfile))
 
308
                return false;
 
309
 
 
310
        connect(qApp, SIGNAL(forceSavePreferences()), SLOT(forceSavePreferences()));
 
311
 
283
312
        // PGP initialization (needs to be before any gpg usage!)
284
313
        PGPUtil::instance();
285
314
 
291
320
        connect(d->contactList, SIGNAL(accountActivityChanged()), SIGNAL(accountActivityChanged()));
292
321
        connect(d->contactList, SIGNAL(saveAccounts()), SLOT(saveAccounts()));
293
322
 
 
323
        // do some backuping in case we are about to start migration from config.xml+options.xml
 
324
        // to options.xml only.
 
325
        QString backupfile = optionsFile() + "-preOptionsMigration";
 
326
        if (QFile::exists(pathToProfileConfig(activeProfile))
 
327
                && QFile::exists(optionsFile())
 
328
                && !QFile::exists(backupfile)) {
 
329
                QFile::copy(optionsFile(), backupfile);
 
330
        }
 
331
        
 
332
        // advanced widget
 
333
        GAdvancedWidget::setStickEnabled( false ); //until this is bugless
 
334
        GAdvancedWidget::setStickToWindows( false ); //again
 
335
        GAdvancedWidget::setStickAt( 5 );
 
336
        
 
337
        
294
338
        // To allow us to upgrade from old hardcoded options gracefully, be careful about the order here
295
339
        PsiOptions *options=PsiOptions::instance();
296
340
        //load the system-wide defaults, if they exist
304
348
        d->tuneController = new CombinedTuneController();
305
349
#endif
306
350
 
 
351
        // calculate the small font size
 
352
        const int minimumFontSize = 7;
 
353
        common_smallFontSize = qApp->font().pointSize();
 
354
        common_smallFontSize -= 2;
 
355
        if ( common_smallFontSize < minimumFontSize )
 
356
                common_smallFontSize = minimumFontSize;
 
357
        FancyLabel::setSmallFontSize( common_smallFontSize );
 
358
        
 
359
        
 
360
        if (!QFile::exists(optionsFile()) && !QFile::exists(pathToProfileConfig(activeProfile))) {
 
361
                if (!options->load(":/options/newprofile.xml")) {
 
362
                        qWarning("ERROR: Failed to new profile default options");
 
363
                }
 
364
        }
 
365
        
307
366
        // load the old profile
308
 
        d->pro.reset();
309
 
        d->pro.fromFile(pathToProfileConfig(activeProfile));
 
367
        d->optionsMigration.fromFile(pathToProfileConfig(activeProfile));
310
368
        
311
369
        //load the new profile
312
 
        QString optionsFile=pathToProfile( activeProfile );
313
 
        optionsFile += "/options.xml";
314
 
        options->load(optionsFile);
315
370
        //Save every time an option is changed
316
 
        options->autoSave(true, optionsFile);
317
 
        
 
371
        options->load(optionsFile());
 
372
        options->autoSave(true, optionsFile());
 
373
 
318
374
        //just set a dummy option to trigger saving
319
375
        options->setOption("trigger-save",false);
320
376
        options->setOption("trigger-save",true);
321
377
        
322
 
        connect(options, SIGNAL(optionChanged(const QString&)), SLOT(optionsUpdate()));
 
378
        // do some late migration work
 
379
        d->optionsMigration.lateMigration();
 
380
        
 
381
        QFile accountsFile(pathToProfile( activeProfile ) + "/accounts.xml");
 
382
        bool accountMigration = false;  
 
383
        if (!accountsFile.exists()) {
 
384
                accountMigration = true;
 
385
                int idx = 0;
 
386
                foreach(UserAccount a, d->optionsMigration.accMigration) {
 
387
                        QString base = "accounts.a"+QString::number(idx++);
 
388
                        a.toOptions(&d->accountTree, base);
 
389
                }
 
390
        } else {
 
391
                d->accountTree.loadOptions(accountsFile.fileName(), "accounts", ApplicationInfo::optionsNS());
 
392
        }
323
393
 
 
394
        // proxy
 
395
        d->proxy = new ProxyManager(&d->accountTree, this);
 
396
        if (accountMigration) d->proxy->migrateItemList(d->optionsMigration.proxyMigration);
 
397
        connect(d->proxy, SIGNAL(settingsChanged()), SLOT(proxy_settingsChanged()));
 
398
        
 
399
        connect(options, SIGNAL(optionChanged(const QString&)), SLOT(optionChanged(const QString&)));
 
400
        
324
401
        QDir profileDir( pathToProfile( activeProfile ) );
325
402
        profileDir.rmdir( "info" ); // remove unused dir
326
403
 
327
 
        d->recentGCList = d->pro.recentGCList;
328
 
        d->recentBrowseList = d->pro.recentBrowseList;
329
 
        d->lastStatusString = d->pro.lastStatusString;
330
 
        useSound = d->pro.useSound;
331
 
 
332
 
        option = d->pro.prefs;
 
404
        d->iconSelect = new IconSelectPopup(0);
 
405
        connect(PsiIconset::instance(), SIGNAL(emoticonsChanged()), d, SLOT(updateIconSelect()));
333
406
 
334
407
        // first thing, try to load the iconset
335
408
        if( !PsiIconset::instance()->loadAll() ) {
336
 
                //option.iconset = "stellar";
337
 
                //if(!is.load(option.iconset)) {
 
409
                //LEGOPTS.iconset = "stellar";
 
410
                //if(!is.load(LEGOPTS.iconset)) {
338
411
                        QMessageBox::critical(0, tr("Error"), tr("Unable to load iconset!  Please make sure Psi is properly installed."));
339
412
                        return false;
340
413
                //}
347
420
                
348
421
        Anim::setMainThread(QThread::currentThread());
349
422
 
350
 
        d->iconSelect = new IconSelectPopup(0);
351
 
        d->updateIconSelect();
352
 
 
353
423
        // setup the main window
354
 
        d->mainwin = new MainWin(option.alwaysOnTop, (option.useDock && option.dockToolMW), this, "psimain"); 
355
 
        d->mainwin->setUseDock(option.useDock);
 
424
        d->mainwin = new MainWin(PsiOptions::instance()->getOption("options.ui.contactlist.always-on-top").toBool(), (PsiOptions::instance()->getOption("options.ui.systemtray.enable").toBool() && PsiOptions::instance()->getOption("options.contactlist.use-toolwindow").toBool()), this, "psimain"); 
 
425
        d->mainwin->setUseDock(PsiOptions::instance()->getOption("options.ui.systemtray.enable").toBool());
356
426
 
357
427
        connect(d->mainwin, SIGNAL(closeProgram()), SLOT(closeProgram()));
358
428
        connect(d->mainwin, SIGNAL(changeProfile()), SLOT(changeProfile()));
364
434
        connect(d->mainwin, SIGNAL(doToolbars()), SLOT(doToolbars()));
365
435
        connect(d->mainwin, SIGNAL(doFileTransDlg()), SLOT(doFileTransDlg()));
366
436
        connect(d->mainwin, SIGNAL(recvNextEvent()), SLOT(recvNextEvent()));
367
 
        connect(d->mainwin, SIGNAL(geomChanged(QRect)), SLOT(mainWinGeomChanged(QRect)));
368
437
        connect(this, SIGNAL(emitOptionsUpdate()), d->mainwin, SLOT(optionsUpdate()));
369
438
 
370
439
        connect(this, SIGNAL(emitOptionsUpdate()), d->mainwin->cvlist, SLOT(optionsUpdate()));
371
440
 
372
 
        d->mainwin->restoreSavedGeometry(d->pro.mwgeom);
373
 
        d->mwgeom = d->pro.mwgeom;
 
441
        d->mainwin->setGeometryOptionPath("options.ui.contactlist.saved-window-geometry");
374
442
        
375
 
        if(!(option.useDock && option.dockHideMW))
 
443
        if(!(PsiOptions::instance()->getOption("options.ui.systemtray.enable").toBool() && PsiOptions::instance()->getOption("options.contactlist.hide-on-start").toBool()))
376
444
                d->mainwin->show();
377
445
 
378
446
        d->ftwin = new FileTransDlg(this);
383
451
        d->s5bServer = new S5BServer;
384
452
        s5b_init();
385
453
 
386
 
        // proxy
387
 
        d->proxy = new ProxyManager(this);
388
 
        d->proxy->setItemList(d->pro.proxyList);
389
 
        connect(d->proxy, SIGNAL(settingsChanged()), SLOT(proxy_settingsChanged()));
390
 
 
391
 
        // Disable accounts if necessary, and overwrite locked properties
392
 
        if (PsiOptions::instance()->getOption("options.ui.account.single").toBool() || !PsiOptions::instance()->getOption("options.account.domain").toString().isEmpty()) {
393
 
                bool haveEnabled = false;
394
 
                for(UserAccountList::Iterator it = d->pro.acc.begin(); it != d->pro.acc.end(); ++it) {
395
 
                        // With single accounts, only modify the first account
396
 
                        if (PsiOptions::instance()->getOption("options.ui.account.single").toBool()) {
397
 
                                if (!haveEnabled) {
398
 
                                        haveEnabled = it->opt_enabled;
399
 
                                        if (it->opt_enabled) {
400
 
                                                if (!PsiOptions::instance()->getOption("options.account.domain").toString().isEmpty())
401
 
                                                        it->jid = JIDUtil::accountFromString(Jid(it->jid).user()).bare();
402
 
                                        }
403
 
                                }
404
 
                                else
405
 
                                        it->opt_enabled = false;
406
 
                        }
407
 
                        else {
408
 
                                // Overwirte locked properties
409
 
                                if (!PsiOptions::instance()->getOption("options.account.domain").toString().isEmpty())
410
 
                                        it->jid = JIDUtil::accountFromString(Jid(it->jid).user()).bare();
411
 
                        }
412
 
                }
413
 
        }
414
 
        
415
454
        // Connect to the system monitor
416
455
        SystemWatch* sw = SystemWatch::instance();
417
456
        connect(sw, SIGNAL(sleep()), this, SLOT(doSleep()));
424
463
 
425
464
        // Global shortcuts
426
465
        setShortcuts();
427
 
 
428
 
        // Entity capabilities
429
 
        CapsRegistry::instance()->setFile(ApplicationInfo::homeDir() + "/caps.xml");
430
466
        
431
467
        // FIXME
432
468
#ifdef __GNUC__
433
469
#warning "Temporary hard-coding caps registration of own version"
434
470
#endif
435
471
        // client()->identity()
436
 
        DiscoItem::Identity identity = { "client",  ApplicationInfo::name(), "pc" };
437
 
        DiscoItem::Identities identities;
438
 
        identities += identity;
439
 
        QStringList features;
440
 
        features << "http://jabber.org/protocol/bytestreams"
441
 
                << "http://jabber.org/protocol/si" 
442
 
                << "http://jabber.org/protocol/si/profile/file-transfer" 
443
 
                << "http://jabber.org/protocol/disco#info" 
444
 
                << "http://jabber.org/protocol/commands" 
445
 
                << "http://jabber.org/protocol/rosterx" 
446
 
                << "http://jabber.org/protocol/muc" 
447
 
                << "jabber:x:data";
448
 
        CapsRegistry::instance()->registerCaps(CapsSpec(ApplicationInfo::capsNode(),ApplicationInfo::capsVersion(),ApplicationInfo::capsVersion()),identities,Features(features));
449
 
        CapsRegistry::instance()->registerCaps(CapsSpec(ApplicationInfo::capsNode(),ApplicationInfo::capsVersion(),"cs"),identities,Features("http://jabber.org/protocol/chatstates"));
450
 
        features.clear();
451
 
        features << "http://jabber.org/protocol/mood"
452
 
                << "http://jabber.org/protocol/tune" 
453
 
                << "http://jabber.org/protocol/physloc" 
454
 
                << "http://jabber.org/protocol/geoloc" 
455
 
                << "http://www.xmpp.org/extensions/xep-0084.html#ns-data" 
456
 
                << "http://www.xmpp.org/extensions/xep-0084.html#ns-metadata";
457
 
        CapsRegistry::instance()->registerCaps(CapsSpec(ApplicationInfo::capsNode(),ApplicationInfo::capsVersion(),"ep"),identities,features);
458
 
        features.clear();
459
 
        features << "http://jabber.org/protocol/mood+notify"
460
 
                << "http://jabber.org/protocol/tune+notify" 
461
 
                << "http://jabber.org/protocol/physloc+notify" 
462
 
                << "http://jabber.org/protocol/geoloc+notify" 
463
 
                << "http://www.xmpp.org/extensions/xep-0084.html#ns-metadata+notify";
464
 
        CapsRegistry::instance()->registerCaps(CapsSpec(ApplicationInfo::capsNode(),ApplicationInfo::capsVersion(),"ep-notify"),identities,features);
465
 
        CapsRegistry::instance()->registerCaps(CapsSpec(ApplicationInfo::capsNode(),ApplicationInfo::capsVersion(),"html"),identities,Features("http://jabber.org/protocol/xhtml-im"));
466
 
 
 
472
 
 
473
        registerCaps(ApplicationInfo::capsVersion(), QStringList()
 
474
                     << "http://jabber.org/protocol/bytestreams"
 
475
                     << "http://jabber.org/protocol/si"
 
476
                     << "http://jabber.org/protocol/si/profile/file-transfer"
 
477
                     << "http://jabber.org/protocol/disco#info"
 
478
                     << "http://jabber.org/protocol/commands"
 
479
                     << "http://jabber.org/protocol/rosterx"
 
480
                     << "http://jabber.org/protocol/muc"
 
481
                     << "jabber:x:data"
 
482
                    );
 
483
 
 
484
        registerCaps("ep", QStringList()
 
485
                     << "http://jabber.org/protocol/mood"
 
486
                     << "http://jabber.org/protocol/tune"
 
487
                     << "http://jabber.org/protocol/physloc"
 
488
                     << "http://jabber.org/protocol/geoloc"
 
489
                     << "http://www.xmpp.org/extensions/xep-0084.html#ns-data"
 
490
                     << "http://www.xmpp.org/extensions/xep-0084.html#ns-metadata"
 
491
                    );
 
492
 
 
493
        registerCaps("ep-notify", QStringList()
 
494
                     << "http://jabber.org/protocol/mood+notify"
 
495
                     << "http://jabber.org/protocol/tune+notify"
 
496
                     << "http://jabber.org/protocol/physloc+notify"
 
497
                     << "http://jabber.org/protocol/geoloc+notify"
 
498
                     << "http://www.xmpp.org/extensions/xep-0084.html#ns-metadata+notify"
 
499
                    );
 
500
 
 
501
        registerCaps("html", QStringList("http://jabber.org/protocol/xhtml-im"));
 
502
        registerCaps("cs", QStringList("http://jabber.org/protocol/chatstates"));
 
503
        //I've commented out the automatic replies, so commenting out support as well - KIS
 
504
        registerCaps("mr", QStringList("urn:xmpp:receipts"));
467
505
 
468
506
        // load accounts
469
 
        d->contactList->loadAccounts(d->pro.acc);
 
507
        {
 
508
                QList<UserAccount> accs;
 
509
                QStringList bases = d->accountTree.getChildOptionNames("accounts", true, true);
 
510
                foreach (QString base, bases) {
 
511
                        UserAccount ua;
 
512
                        ua.fromOptions(&d->accountTree, base);
 
513
                        accs += ua;
 
514
                }
 
515
                
 
516
                // Disable accounts if necessary, and overwrite locked properties
 
517
                if (PsiOptions::instance()->getOption("options.ui.account.single").toBool() || !PsiOptions::instance()->getOption("options.account.domain").toString().isEmpty()) {
 
518
                        bool haveEnabled = false;
 
519
                        for(UserAccountList::Iterator it = accs.begin(); it != accs.end(); ++it) {
 
520
                                // With single accounts, only modify the first account
 
521
                                if (PsiOptions::instance()->getOption("options.ui.account.single").toBool()) {
 
522
                                        if (!haveEnabled) {
 
523
                                                haveEnabled = it->opt_enabled;
 
524
                                                if (it->opt_enabled) {
 
525
                                                        if (!PsiOptions::instance()->getOption("options.account.domain").toString().isEmpty())
 
526
                                                                it->jid = JIDUtil::accountFromString(Jid(it->jid).user()).bare();
 
527
                                                }
 
528
                                        }
 
529
                                        else
 
530
                                                it->opt_enabled = false;
 
531
                                }
 
532
                                else {
 
533
                                        // Overwirte locked properties
 
534
                                        if (!PsiOptions::instance()->getOption("options.account.domain").toString().isEmpty())
 
535
                                                it->jid = JIDUtil::accountFromString(Jid(it->jid).user()).bare();
 
536
                                }
 
537
                        }
 
538
                }
 
539
                
 
540
                d->contactList->loadAccounts(accs);
 
541
        }       
 
542
        
470
543
        checkAccountsEmpty();
 
544
        
 
545
        
471
546
        // try autologin if needed
472
547
        foreach(PsiAccount* account, d->contactList->accounts()) {
473
548
                account->autoLogin();
474
549
        }
475
 
 
 
550
        
476
551
        // show tip of the day
477
 
        if ( PsiOptions::instance()->getOption("options.ui.tip.show").toBool() )
 
552
        if ( PsiOptions::instance()->getOption("options.ui.tip.show").toBool() ) {
478
553
                TipDlg::show(this);
 
554
        }
 
555
 
 
556
#ifdef USE_DBUS
 
557
        addPsiConAdapter(this);
 
558
#endif
 
559
 
 
560
        connect(ActiveProfiles::instance(), SIGNAL(raiseMainWindow()), SLOT(raiseMainwin()));
479
561
 
480
562
        return true;
481
563
}
482
564
 
 
565
void PsiCon::registerCaps(const QString& ext, const QStringList& features)
 
566
{
 
567
        DiscoItem::Identity identity = { "client", ApplicationInfo::name(), "pc" };
 
568
        DiscoItem::Identities identities;
 
569
        identities += identity;
 
570
 
 
571
        d->capsRegistry->registerCaps(CapsSpec(ApplicationInfo::capsNode(),
 
572
                                               ApplicationInfo::capsVersion(), ext),
 
573
                                      identities,
 
574
                                      Features(features));
 
575
}
 
576
 
483
577
void PsiCon::deinit()
484
578
{
485
579
        // this deletes all dialogs except for mainwin
488
582
        d->idle.stop();
489
583
 
490
584
        // shut down all accounts
491
 
        UserAccountList acc = d->contactList->getUserAccountList();
492
 
        delete d->contactList;
 
585
        UserAccountList acc;
 
586
        if(d->contactList) {
 
587
                acc = d->contactList->getUserAccountList();
 
588
                delete d->contactList;
 
589
        }
493
590
 
494
591
        // delete s5b server
495
592
        delete d->s5bServer;
497
594
        delete d->ftwin;
498
595
 
499
596
        if(d->mainwin) {
500
 
                // shut down mainwin
501
 
                QRect mwgeom;
502
 
                if ( !d->mainwin->isHidden() && !d->mainwin->isMinimized() )
503
 
                        mwgeom = d->mainwin->saveableGeometry();
504
 
                else
505
 
                        mwgeom = d->mwgeom;
506
 
 
507
597
                delete d->mainwin;
508
598
                d->mainwin = 0;
509
 
 
510
 
                d->pro.mwgeom = mwgeom;
511
599
        }
512
600
 
513
601
        // TuneController
514
602
        delete d->tuneController;
515
603
 
516
604
        // save profile
517
 
        d->saveProfile(acc);
518
 
}
519
 
 
520
 
void PsiCon::optionsUpdate()
521
 
{
522
 
        // Global shortcuts
523
 
        setShortcuts();
524
 
}
 
605
        if(d->contactList)
 
606
                d->saveProfile(acc);
 
607
 
 
608
        GlobalShortcutManager::clear();
 
609
}
 
610
 
525
611
 
526
612
void PsiCon::setShortcuts()
527
613
{
575
661
 
576
662
void PsiCon::changeProfile()
577
663
{
 
664
        ActiveProfiles::instance()->unsetThisProfile();
578
665
        if(d->contactList->haveActiveAccounts()) {
579
666
                QMessageBox::information(0, CAP(tr("Error")), tr("Please disconnect before changing the profile."));
580
667
                return;
663
750
        return d->defaultMenuBar;
664
751
}
665
752
 
666
 
TabDlg* PsiCon::newTabs()
667
 
{
668
 
        TabDlg *tab;
669
 
        tab=new TabDlg(this);
670
 
        d->tabs.append(tab);
671
 
        connect (tab, SIGNAL ( isDying(TabDlg*) ), SLOT ( tabDying(TabDlg*) ) );
672
 
        connect(this, SIGNAL(emitOptionsUpdate()), tab, SLOT(optionsUpdate()));
673
 
        return tab;
674
 
}
675
 
 
676
 
TabDlg* PsiCon::getTabs()
677
 
{
678
 
        if (!d->tabs.isEmpty())
679
 
        {
680
 
                return d->tabs.getFirst();
681
 
        }
682
 
        else
683
 
        {
684
 
                return newTabs();
685
 
        }
686
 
}
687
 
 
688
 
void PsiCon::tabDying(TabDlg* tab)
689
 
{
690
 
        d->tabs.remove(tab);
691
 
}
692
 
 
693
 
bool PsiCon::isChatTabbed(ChatDlg* chat)
694
 
{
695
 
        for (uint i = 0; i < d->tabs.count(); ++i)
696
 
        {
697
 
                if ( d->tabs.at(i)->managesChat(chat) )
698
 
                                return true;
699
 
        }
700
 
        return false;
701
 
}
702
 
 
703
 
ChatDlg* PsiCon::getChatInTabs(QString jid){
704
 
        for (uint i = 0; i < d->tabs.count(); ++i)
705
 
        {
706
 
                if ( d->tabs.at(i)->getChatPointer(jid) )
707
 
                                return d->tabs.at(i)->getChatPointer(jid);
708
 
        }
709
 
        return NULL;
710
 
 
711
 
}
712
 
 
713
 
TabDlg* PsiCon::getManagingTabs(ChatDlg* chat)
714
 
{
715
 
        for (uint i = 0; i < d->tabs.count(); ++i)
716
 
        {
717
 
                if ( d->tabs.at(i)->managesChat(chat) )
718
 
                                return d->tabs.at(i);
719
 
        }
720
 
        return NULL;
721
 
 
722
 
}
723
 
 
724
 
Q3PtrList<TabDlg>* PsiCon::getTabSets()
725
 
{
726
 
        return &d->tabs;
727
 
}
728
 
 
729
 
bool PsiCon::isChatActiveWindow(ChatDlg* chat)
730
 
{
731
 
        //returns true if chat is on top of a tab pile
732
 
        if ( chat->isHidden() )
733
 
        {
734
 
                return false;
735
 
        }
736
 
        if (!option.useTabs)
737
 
        {
738
 
                return chat->isActiveWindow();
739
 
        }
740
 
        for (uint i = 0; i < d->tabs.count(); ++i)
741
 
        {
742
 
                if ( d->tabs.at(i)->isActiveWindow() )
743
 
                {
744
 
                        if ( d->tabs.at(i)->chatOnTop( chat ) )
745
 
                        {
746
 
                                return true;
747
 
                        }
748
 
                }
749
 
        }
750
 
        return false;
751
 
}
752
753
 
753
754
void PsiCon::dialogRegister(QWidget *w)
754
755
{
778
779
                delete i->widget;
779
780
                delete i;
780
781
        }
781
 
        d->tabs.clear();
 
782
        d->tabManager->deleteAll();
782
783
}
783
784
 
784
785
AccountsComboBox *PsiCon::accountsComboBox(QWidget *parent, bool online_only)
785
786
{
786
 
        AccountsComboBox *acb = new AccountsComboBox(this, parent, online_only);
 
787
        AccountsComboBox* acb = new AccountsComboBox(parent);
 
788
        acb->setController(this);
 
789
        acb->setOnlineOnly(online_only);
787
790
        return acb;
788
791
}
789
792
 
790
 
void PsiCon::createAccount(const QString &name, const Jid &j, const QString &pass, bool opt_host, const QString &host, int port, bool legacy_ssl_probe, UserAccount::SSLFlag ssl, int proxy)
 
793
void PsiCon::createAccount(const QString &name, const Jid &j, const QString &pass, bool opt_host, const QString &host, int port, bool legacy_ssl_probe, UserAccount::SSLFlag ssl, QString proxy)
791
794
{
792
795
        d->contactList->createAccount(name, j, pass, opt_host, host, port, legacy_ssl_probe, ssl, proxy);
793
796
}
794
797
 
795
798
PsiAccount *PsiCon::createAccount(const UserAccount& acc)
796
799
{
797
 
        PsiAccount *pa = new PsiAccount(acc, d->contactList);
 
800
        PsiAccount *pa = new PsiAccount(acc, d->contactList, d->capsRegistry, d->tabManager);
798
801
        connect(&d->idle, SIGNAL(secondsIdle(int)), pa, SLOT(secondsIdle(int)));
799
802
        connect(pa, SIGNAL(updatedActivity()), SLOT(pa_updatedActivity()));
800
803
        connect(pa, SIGNAL(updatedAccount()), SLOT(pa_updatedAccount()));
801
804
        connect(pa, SIGNAL(queueChanged()), SLOT(queueChanged()));
802
 
        if(d->s5bServer)
 
805
        connect(pa, SIGNAL(startBounce()), SLOT(startBounce()));
 
806
        if (d->s5bServer) {
803
807
                pa->client()->s5bManager()->setServer(d->s5bServer);
 
808
        }
804
809
        return pa;
805
810
}
806
811
 
811
816
 
812
817
void PsiCon::statusMenuChanged(int x)
813
818
{
814
 
        if(x == STATUS_OFFLINE && !option.askOffline) {
815
 
                setGlobalStatus(Status("","Logged out",0,false));
816
 
                if(option.useDock == true)
817
 
                        d->mainwin->setTrayToolTip(Status("","",0,false));
 
819
        if(x == STATUS_OFFLINE && !PsiOptions::instance()->getOption("options.status.ask-for-message-on-offline").toBool()) {
 
820
                setGlobalStatus(Status(Status::Offline, "Logged out", 0));
 
821
                if(PsiOptions::instance()->getOption("options.ui.systemtray.enable").toBool() == true)
 
822
                        d->mainwin->setTrayToolTip(Status(Status::Offline, "", 0));
818
823
        }
819
824
        else {
820
 
                if(x == STATUS_ONLINE && !option.askOnline) {
 
825
                if(x == STATUS_ONLINE && !PsiOptions::instance()->getOption("options.status.ask-for-message-on-online").toBool()) {
821
826
                        setGlobalStatus(Status());
822
 
                        if(option.useDock == true)
 
827
                        if(PsiOptions::instance()->getOption("options.ui.systemtray.enable").toBool() == true)
823
828
                                d->mainwin->setTrayToolTip(Status());
824
829
                }
825
830
                else if(x == STATUS_INVISIBLE){
826
831
                        Status s("","",0,true);
827
832
                        s.setIsInvisible(true);
828
833
                        setGlobalStatus(s);
829
 
                        if(option.useDock == true)
 
834
                        if(PsiOptions::instance()->getOption("options.ui.systemtray.enable").toBool() == true)
830
835
                                d->mainwin->setTrayToolTip(s);
831
836
                }
832
837
                else {
833
838
                        // Create a dialog with the last status message
834
 
                        StatusSetDlg *w = new StatusSetDlg(this, makeStatus(x, d->lastStatusString));
 
839
                        StatusSetDlg *w = new StatusSetDlg(this, makeStatus(x, PsiOptions::instance()->getOption("options.status.last-message").toString()));
835
840
                        connect(w, SIGNAL(set(const XMPP::Status &, bool)), SLOT(setStatusFromDialog(const XMPP::Status &, bool)));
836
841
                        connect(w, SIGNAL(cancelled()), SLOT(updateMainwinStatus()));
837
 
                        if(option.useDock == true)
 
842
                        if(PsiOptions::instance()->getOption("options.ui.systemtray.enable").toBool() == true)
838
843
                                connect(w, SIGNAL(set(const XMPP::Status &, bool)), d->mainwin, SLOT(setTrayToolTip(const XMPP::Status &, bool)));
839
844
                        w->show();
840
845
                }
843
848
 
844
849
void PsiCon::setStatusFromDialog(const Status &s, bool withPriority)
845
850
{
846
 
        d->lastStatusString = s.status();
 
851
        PsiOptions::instance()->setOption("options.status.last-message", s.status());
847
852
        setGlobalStatus(s, withPriority);
848
853
}
849
854
 
886
891
void PsiCon::saveAccounts()
887
892
{
888
893
        UserAccountList acc = d->contactList->getUserAccountList();
889
 
 
890
 
        d->pro.proxyList = d->proxy->itemList();
891
 
        //d->pro.acc = acc;
892
 
        //d->pro.toFile(pathToProfileConfig(activeProfile));
893
894
        d->saveProfile(acc);
894
895
}
895
896
 
 
897
void PsiCon::saveCapabilities()
 
898
{
 
899
        QFile file(ApplicationInfo::homeDir() + "/caps.xml");
 
900
        d->capsRegistry->save(file);
 
901
}
 
902
 
896
903
void PsiCon::updateMainwinStatus()
897
904
{
898
905
        bool active = false;
916
923
        }
917
924
}
918
925
 
919
 
void PsiCon::setToggles(bool tog_offline, bool tog_away, bool tog_agents, bool tog_hidden, bool tog_self)
920
 
{
921
 
        if(d->contactList->enabledAccounts().count() > 1)
922
 
                return;
923
 
 
924
 
        d->mainwin->cvlist->setShowOffline(tog_offline);
925
 
        d->mainwin->cvlist->setShowAway(tog_away);
926
 
        d->mainwin->cvlist->setShowAgents(tog_agents);
927
 
        d->mainwin->cvlist->setShowHidden(tog_hidden);
928
 
        d->mainwin->cvlist->setShowSelf(tog_self);
929
 
}
930
 
 
931
 
void PsiCon::getToggles(bool *tog_offline, bool *tog_away, bool *tog_agents, bool *tog_hidden, bool *tog_self)
932
 
{
933
 
        *tog_offline = d->mainwin->cvlist->isShowOffline();
934
 
        *tog_away = d->mainwin->cvlist->isShowAway();
935
 
        *tog_agents = d->mainwin->cvlist->isShowAgents();
936
 
        *tog_hidden = d->mainwin->cvlist->isShowHidden();
937
 
        *tog_self = d->mainwin->cvlist->isShowSelf();
938
 
}
939
 
 
940
926
void PsiCon::doOptions()
941
927
{
942
928
        OptionsDlg *w = (OptionsDlg *)dialogFind("OptionsDlg");
943
929
        if(w)
944
930
                bringToFront(w);
945
931
        else {
946
 
                w = new OptionsDlg(this, option);
947
 
                connect(w, SIGNAL(applyOptions(const Options &)), SLOT(slotApplyOptions(const Options &)));
 
932
                w = new OptionsDlg(this);
 
933
                connect(w, SIGNAL(applyOptions()), SLOT(slotApplyOptions()));
948
934
                w->show();
949
935
        }
950
936
}
956
942
 
957
943
void PsiCon::checkAccountsEmpty()
958
944
{
959
 
        if (d->pro.acc.count() == 0) {
 
945
        if (d->contactList->accounts().count() == 0) {
960
946
                promptUserToCreateAccount();
961
947
        }
962
948
}
963
949
 
 
950
void PsiCon::doOpenUri(const QUrl &uriToOpen)
 
951
{
 
952
        Q_UNUSED(uriToOpen);    
 
953
        
 
954
/*
 
955
        QUrl uri(uriToOpen);    // got to copy, because setQueryDelimiters() is not const
 
956
 
 
957
        qWarning("uri:  " + uri.toString());
 
958
 
 
959
        // scheme
 
960
 
 
961
        if (uri.scheme() != "xmpp") {   // try handling legacy URIs
 
962
                QMessageBox::warning(0, tr("Warning"), QString("URI (link) type \"%1\" is unsupported.").arg(uri.scheme()));
 
963
        }
 
964
 
 
965
        // authority
 
966
 
 
967
        PsiAccount *pa = 0;
 
968
        if (uri.authority().isEmpty()) {
 
969
                pa = d->contactList->defaultAccount();
 
970
                if (!pa) {
 
971
                        QMessageBox::warning(0, tr("Warning"), QString("You don't have any account enabled."));
 
972
                }
 
973
        }
 
974
        else {
 
975
                qWarning("uri auth: [" + uri.authority() + "]");
 
976
 
 
977
                Jid authJid = JIDUtil::fromString(uri.authority());
 
978
                foreach(PsiAccount* acc, d->contactList->enabledAccounts()) {
 
979
                        if (acc->jid().compare(authJid, false)) {
 
980
                                pa = acc;
 
981
                        }
 
982
                }
 
983
 
 
984
                if (!pa) {
 
985
                        foreach(PsiAccount* acc, d->contactList->accounts()) {
 
986
                                if (acc->jid().compare(authJid, false)) {
 
987
                                        QMessageBox::warning(0, tr("Warning"), QString("The account for %1 JID is disabled right now.").arg(authJid.bare()));
 
988
                                        return; // FIX-ME: Should suggest enabling it now
 
989
                                }
 
990
                        }
 
991
                }
 
992
                if (!pa) {
 
993
                        QMessageBox::warning(0, tr("Warning"), QString("You don't have an account for %1.").arg(authJid.bare()));
 
994
                        return;
 
995
                }
 
996
        }
 
997
 
 
998
        // entity
 
999
 
 
1000
        QString path = uri.path();
 
1001
        if (path.startsWith('/'))       // this happens when authority part is present
 
1002
                path = path.mid(1);
 
1003
        Jid entity = JIDUtil::fromString(path);
 
1004
 
 
1005
        // query
 
1006
 
 
1007
        uri.setQueryDelimiters('=', ';');
 
1008
 
 
1009
        QString querytype = uri.queryItems().value(0).first;    // defaults to empty string
 
1010
 
 
1011
        if (querytype == "message") {
 
1012
                if (uri.queryItemValue("type") == "chat")
 
1013
                        pa->actionOpenChat(entity);
 
1014
                else {
 
1015
                        pa->dj_newMessage(entity, uri.queryItemValue("body"), uri.queryItemValue("subject"), uri.queryItemValue("thread"));
 
1016
                }
 
1017
        }
 
1018
        else if (querytype == "roster") {
 
1019
                pa->openAddUserDlg(entity, uri.queryItemValue("name"), uri.queryItemValue("group"));
 
1020
        }
 
1021
        else if (querytype == "join") {
 
1022
                pa->actionJoin(entity, uri.queryItemValue("password"));
 
1023
        }
 
1024
        else if (querytype == "vcard") {
 
1025
                pa->actionInfo(entity);
 
1026
        }
 
1027
        else if (querytype == "disco") {
 
1028
                pa->actionDisco(entity, uri.queryItemValue("node"));
 
1029
        }
 
1030
        else {
 
1031
                pa->actionSendMessage(entity);
 
1032
        }
 
1033
*/}
 
1034
 
964
1035
void PsiCon::doToolbars()
965
1036
{
966
1037
        OptionsDlg *w = (OptionsDlg *)dialogFind("OptionsDlg");
969
1040
                bringToFront(w);
970
1041
        }
971
1042
        else {
972
 
                w = new OptionsDlg(this, option);
973
 
                connect(w, SIGNAL(applyOptions(const Options &)), SLOT(slotApplyOptions(const Options &)));
 
1043
                w = new OptionsDlg(this);
 
1044
                connect(w, SIGNAL(applyOptions()), SLOT(slotApplyOptions()));
974
1045
                w->openTab("toolbars");
975
1046
                w->show();
976
1047
        }
977
1048
}
978
1049
 
979
 
void PsiCon::slotApplyOptions(const Options &opt)
 
1050
void PsiCon::optionChanged(const QString& option)
980
1051
{
981
 
        Options oldOpt = option;
982
1052
        bool notifyRestart = true;
983
1053
 
984
 
        option = opt;
 
1054
        // Global shortcuts
 
1055
        setShortcuts();
 
1056
 
 
1057
        if (option == "options.ui.notifications.alert-style") {
 
1058
                alertIconUpdateAlertStyle();
 
1059
        }
 
1060
 
 
1061
        if (option == "options.ui.tabs.use-tabs") {
 
1062
                QMessageBox::information(0, tr("Information"), tr("Some of the options you changed will only have full effect upon restart."));
 
1063
                notifyRestart = false;
 
1064
        }
 
1065
 
 
1066
        // update s5b
 
1067
        if (option == "options.p2p.bytestreams.listen-port") {
 
1068
                s5b_init();
 
1069
        }
 
1070
}
 
1071
 
 
1072
void PsiCon::slotApplyOptions()
 
1073
{
 
1074
        PsiOptions *o = PsiOptions::instance();
 
1075
        PsiIconset::instance()->reloadRoster();
985
1076
 
986
1077
#ifndef Q_WS_MAC
987
 
        if (option.hideMenubar) {
 
1078
        if (!PsiOptions::instance()->getOption("options.ui.contactlist.show-menubar").toBool()) {
988
1079
                // check if all toolbars are disabled
989
1080
                bool toolbarsVisible = false;
990
 
                QList<Options::ToolbarPrefs>::ConstIterator it = option.toolbars["mainWin"].begin();
991
 
                for ( ; it != option.toolbars["mainWin"].end() && !toolbarsVisible; ++it) {
992
 
                        toolbarsVisible = toolbarsVisible || (*it).on;
 
1081
                foreach(QString base, o->getChildOptionNames("options.ui.contactlist.toolbars", true, true)) {
 
1082
                        if (o->getOption( base + ".visible").toBool()) {
 
1083
                                toolbarsVisible = true;
 
1084
                                break;
 
1085
                        }
993
1086
                }
994
1087
 
995
1088
                // Check whether it is legal to disable the menubar
996
1089
                if ( !toolbarsVisible ) {
997
1090
                        QMessageBox::warning(0, tr("Warning"),
998
 
                                tr("You can not disable <i>all</i> toolbars <i>and</i> the menubar. If you do so, you will be unable to enable them back, when you'll change your mind.\n"
999
 
                                        "<br><br>\n"
1000
 
                                        "If you really-really want to disable all toolbars and the menubar, you need to edit the config.xml file by hand."),
 
1091
                                tr("You can not disable <i>all</i> toolbars <i>and</i> the menubar. If you do so, you will be unable to enable them back, when you'll change your mind."),
1001
1092
                                tr("I understand"));
1002
 
                        option.hideMenubar = false;
 
1093
                        PsiOptions::instance()->setOption("options.ui.contactlist.show-menubar", true);
1003
1094
                }
1004
1095
        }
1005
1096
#endif
1006
1097
 
1007
 
        if ( option.useTabs != oldOpt.useTabs ) {
1008
 
                QMessageBox::information(0, tr("Information"), tr("Some of the options you changed will only have full effect upon restart."));
1009
 
                notifyRestart = false;
1010
 
        }
1011
 
 
1012
 
        // change icon set
1013
 
        if ( option.systemIconset               != oldOpt.systemIconset         ||
1014
 
             option.emoticons                   != oldOpt.emoticons             ||
1015
 
             option.defaultRosterIconset        != oldOpt.defaultRosterIconset  ||
1016
 
             operator!=(option.serviceRosterIconset,oldOpt.serviceRosterIconset)        ||
1017
 
             operator!=(option.customRosterIconset,oldOpt.customRosterIconset) )
1018
 
        {
1019
 
                if ( notifyRestart && PsiIconset::instance()->optionsChanged(&oldOpt) )
1020
 
                        QMessageBox::information(0, tr("Information"), tr("The complete iconset update will happen on next Psi start."));
1021
 
 
1022
 
                // update icon selector
1023
 
                d->updateIconSelect();
1024
 
 
1025
 
                // flush the QPixmapCache
1026
 
                QPixmapCache::clear();
1027
 
        }
1028
 
 
1029
 
        if ( oldOpt.alertStyle != option.alertStyle )
1030
 
                alertIconUpdateAlertStyle();
1031
 
 
1032
 
        d->mainwin->buildToolbars();
1033
 
 
1034
 
        /*// change pgp engine
1035
 
        if(option.pgp != oldpgp) {
1036
 
                if(d->pgp) {
1037
 
                        delete d->pgp;
1038
 
                        d->pgp = 0;
1039
 
                        pgpToggled(false);
1040
 
                }
1041
 
                pgp_init(option.pgp);
1042
 
        }*/
1043
 
 
1044
 
        // update s5b
1045
 
        if(oldOpt.dtPort != option.dtPort)
1046
 
                s5b_init();
1047
1098
        updateS5BServerAddresses();
1048
1099
 
1049
1100
        // mainwin stuff
1050
 
        d->mainwin->setWindowOpts(option.alwaysOnTop, (option.useDock && option.dockToolMW));
1051
 
        d->mainwin->setUseDock(option.useDock);
 
1101
        d->mainwin->setWindowOpts(PsiOptions::instance()->getOption("options.ui.contactlist.always-on-top").toBool(), (PsiOptions::instance()->getOption("options.ui.systemtray.enable").toBool() && PsiOptions::instance()->getOption("options.contactlist.use-toolwindow").toBool()));
 
1102
        d->mainwin->setUseDock(PsiOptions::instance()->getOption("options.ui.systemtray.enable").toBool());
 
1103
        d->mainwin->buildToolbars();
1052
1104
 
1053
1105
        // notify about options change
1054
 
        emitOptionsUpdate();
1055
 
 
1056
 
        // save just the options
1057
 
        //d->pro.prefs = option;
1058
 
        //d->pro.toFile(pathToProfileConfig(activeProfile));
1059
 
        d->saveProfile();
 
1106
        emit emitOptionsUpdate();
1060
1107
}
1061
1108
 
1062
1109
int PsiCon::getId()
1074
1121
 
1075
1122
#ifdef Q_WS_MAC
1076
1123
        {
1077
 
                // The Mac Dock icon
1078
 
 
1079
1124
                // Update the event count
1080
 
                if (nextAmount) 
1081
 
                        MacDock::overlay(QString::number(nextAmount));
1082
 
                else 
1083
 
                        MacDock::overlay(QString::null);
1084
 
 
1085
 
                // Check if bouncing is necessary
1086
 
                bool doBounce = false;
1087
 
                foreach(PsiAccount* account, d->contactList->enabledAccounts()) {
1088
 
                        if (account->eventQueue()->count() && pa->status().type() != XMPP::Status::DND) {
1089
 
                                doBounce = true;
1090
 
                                break;
1091
 
                        }
1092
 
                }
1093
 
 
1094
 
                // Bouncy bouncy
1095
 
                if (doBounce) {
1096
 
                        if (option.bounceDock != Options::NoBounce) {
1097
 
                                MacDock::startBounce();
1098
 
                                if (option.bounceDock == Options::BounceOnce) 
1099
 
                                        MacDock::stopBounce();
1100
 
                        }
1101
 
                }
1102
 
                else 
 
1125
                MacDock::overlay(nextAmount ? QString::number(nextAmount) : QString());
 
1126
 
 
1127
                if (!nextAmount) {
1103
1128
                        MacDock::stopBounce();
 
1129
                }
1104
1130
        }
1105
1131
#endif
1106
1132
 
1107
1133
        d->mainwin->updateReadNext(nextAnim, nextAmount);
1108
1134
}
1109
1135
 
 
1136
void PsiCon::startBounce()
 
1137
{
 
1138
#ifdef Q_WS_MAC
 
1139
        if (PsiOptions::instance()->getOption("options.ui.notifications.bounce-dock").toString() != "never") {
 
1140
                MacDock::startBounce();
 
1141
                if (PsiOptions::instance()->getOption("options.ui.notifications.bounce-dock").toString() == "once") {
 
1142
                        MacDock::stopBounce();
 
1143
                }
 
1144
        }
 
1145
#endif
 
1146
}
 
1147
 
1110
1148
void PsiCon::recvNextEvent()
1111
1149
{
1112
1150
        /*printf("--- Queue Content: ---\n");
1117
1155
        }*/
1118
1156
        PsiAccount *pa = d->contactList->queueLowestEventId();
1119
1157
        if(pa)
1120
 
                pa->openNextEvent();
 
1158
                pa->openNextEvent(UserAction);
1121
1159
}
1122
1160
 
1123
1161
void PsiCon::playSound(const QString &str)
1124
1162
{
1125
 
        if(str.isEmpty() || !useSound)
 
1163
        if(str.isEmpty() || !PsiOptions::instance()->getOption("options.ui.notifications.sounds.enable").toBool())
1126
1164
                return;
1127
1165
 
1128
1166
        soundPlay(str);
1133
1171
        d->mainwin->showNoFocus();
1134
1172
}
1135
1173
 
1136
 
const QStringList & PsiCon::recentGCList() const
 
1174
QStringList PsiCon::recentGCList() const
1137
1175
{
1138
 
        return d->recentGCList;
 
1176
        return PsiOptions::instance()->getOption("options.muc.recent-joins.jids").toStringList();
1139
1177
}
1140
1178
 
1141
1179
void PsiCon::recentGCAdd(const QString &str)
1142
1180
{
 
1181
        QStringList recentList = recentGCList();
 
1182
        
1143
1183
        // remove it if we have it
1144
 
        for(QStringList::Iterator it = d->recentGCList.begin(); it != d->recentGCList.end(); ++it) {
 
1184
        for(QStringList::Iterator it = recentList.begin(); it != recentList.end(); ++it) {
1145
1185
                if(*it == str) {
1146
 
                        d->recentGCList.remove(it);
 
1186
                        recentList.remove(it);
1147
1187
                        break;
1148
1188
                }
1149
1189
        }
1150
1190
 
1151
1191
        // put it in the front
1152
 
        d->recentGCList.prepend(str);
 
1192
        recentList.prepend(str);
1153
1193
 
1154
1194
        // trim the list if bigger than 10
1155
 
        while(d->recentGCList.count() > PsiOptions::instance()->getOption("options.muc.recent-joins.maximum").toInt())
1156
 
                d->recentGCList.remove(d->recentGCList.fromLast());
 
1195
        while(recentList.count() > PsiOptions::instance()->getOption("options.muc.recent-joins.maximum").toInt()) {
 
1196
                recentList.remove(recentList.fromLast());
 
1197
        }
 
1198
        
 
1199
        PsiOptions::instance()->setOption("options.muc.recent-joins.jids", recentList);
1157
1200
}
1158
1201
 
1159
 
const QStringList & PsiCon::recentBrowseList() const
 
1202
QStringList PsiCon::recentBrowseList() const
1160
1203
{
1161
 
        return d->recentBrowseList;
 
1204
        return PsiOptions::instance()->getOption("options.ui.service-discovery.recent-jids").toStringList();
1162
1205
}
1163
1206
 
1164
1207
void PsiCon::recentBrowseAdd(const QString &str)
1165
1208
{
 
1209
        QStringList recentList = recentBrowseList();
1166
1210
        // remove it if we have it
1167
 
        for(QStringList::Iterator it = d->recentBrowseList.begin(); it != d->recentBrowseList.end(); ++it) {
 
1211
        for(QStringList::Iterator it = recentList.begin(); it != recentList.end(); ++it) {
1168
1212
                if(*it == str) {
1169
 
                        d->recentBrowseList.remove(it);
 
1213
                        recentList.remove(it);
1170
1214
                        break;
1171
1215
                }
1172
1216
        }
1173
1217
 
1174
1218
        // put it in the front
1175
 
        d->recentBrowseList.prepend(str);
 
1219
        recentList.prepend(str);
1176
1220
 
1177
1221
        // trim the list if bigger than 10
1178
 
        while(d->recentBrowseList.count() > 10)
1179
 
                d->recentBrowseList.remove(d->recentBrowseList.fromLast());
 
1222
        while(recentList.count() > 10) {
 
1223
                recentList.remove(recentList.fromLast());
 
1224
        }
 
1225
        
 
1226
        PsiOptions::instance()->setOption("options.ui.service-discovery.recent-jids", recentList);
1180
1227
}
1181
1228
 
1182
1229
const QStringList & PsiCon::recentNodeList() const
1204
1251
 
1205
1252
void PsiCon::proxy_settingsChanged()
1206
1253
{
1207
 
        // properly index accounts
1208
 
        foreach(PsiAccount* account, d->contactList->accounts()) {
1209
 
                UserAccount acc = account->userAccount();
1210
 
                if(acc.proxy_index > 0) {
1211
 
                        int x = d->proxy->findOldIndex(acc.proxy_index-1);
1212
 
                        if(x == -1)
1213
 
                                acc.proxy_index = 0;
1214
 
                        else
1215
 
                                acc.proxy_index = x+1;
1216
 
                        account->setUserAccount(acc);
1217
 
                }
1218
 
        }
1219
 
 
1220
1254
        saveAccounts();
1221
1255
}
1222
1256
 
1225
1259
        return d->iconSelect;
1226
1260
}
1227
1261
 
1228
 
void PsiCon::processEvent(PsiEvent *e)
 
1262
void PsiCon::processEvent(PsiEvent *e, ActivationType activationType)
1229
1263
{
1230
1264
        if ( e->type() == PsiEvent::PGP ) {
1231
1265
                e->account()->eventQueue()->dequeue(e);
1270
1304
        }
1271
1305
 
1272
1306
        if ( isChat ) {
1273
 
                if ( option.alertOpenChats && sentToChatWindow ) {
 
1307
                PsiAccount* account = e->account();
 
1308
                XMPP::Jid from = e->from();
 
1309
 
 
1310
                if ( PsiOptions::instance()->getOption("options.ui.chat.alert-for-already-open-chats").toBool() && sentToChatWindow ) {
1274
1311
                        // Message already displayed, need only to pop up chat dialog, so that
1275
1312
                        // it will be read (or marked as read)
1276
 
                        ChatDlg *c = e->account()->findDialog<ChatDlg*>(e->from());
 
1313
                        ChatDlg *c = account->findChatDialog(from);
1277
1314
                        if(!c)
1278
 
                                c = e->account()->findDialog<ChatDlg*>(e->jid());
 
1315
                                c = account->findChatDialog(e->jid());
1279
1316
                        if(!c)
1280
1317
                                return; // should never happen
1281
1318
 
1282
 
                        e->account()->processChats(e->from()); // this will delete all events, corresponding to that chat dialog
1283
 
                        //KIS: I changed the following line with the one following that to attempt to get tabs to behave correctly. Lots of this stuff isn't great.
1284
 
                        bringToFront((QWidget *)c);
1285
 
                        if ( option.useTabs)
1286
 
                        {
1287
 
                                TabDlg* tabSet = getManagingTabs(c);
1288
 
                                if (tabSet) tabSet->selectTab(c);
1289
 
                        }
 
1319
                        account->processChats(from); // this will delete all events, corresponding to that chat dialog
1290
1320
                }
1291
 
                else
1292
 
                        e->account()->openChat(e->from());
 
1321
 
 
1322
                // as the event could be deleted just above, we're using cached account and from values
 
1323
                account->openChat(from, activationType);
1293
1324
        }
1294
1325
        else {
1295
1326
                // search for an already opened eventdlg
1307
1338
        }
1308
1339
}
1309
1340
 
1310
 
void PsiCon::mainWinGeomChanged(QRect saveableGeometry)
1311
 
{
1312
 
        d->mwgeom = saveableGeometry;
1313
 
}
1314
 
 
1315
1341
void PsiCon::updateS5BServerAddresses()
1316
1342
{
1317
1343
        if(!d->s5bServer)
1344
1370
                slist += (*hit).toString();
1345
1371
 
1346
1372
        // add external
1347
 
        if(!option.dtExternal.isEmpty()) {
 
1373
        if(!PsiOptions::instance()->getOption("options.p2p.bytestreams.external-address").toString().isEmpty()) {
1348
1374
                bool found = false;
1349
1375
                for(QStringList::ConstIterator sit = slist.begin(); sit != slist.end(); ++sit) {
1350
1376
                        const QString &s = *sit;
1351
 
                        if(s == option.dtExternal) {
 
1377
                        if(s == PsiOptions::instance()->getOption("options.p2p.bytestreams.external-address").toString()) {
1352
1378
                                found = true;
1353
1379
                                break;
1354
1380
                        }
1355
1381
                }
1356
1382
                if(!found)
1357
 
                        slist += option.dtExternal;
 
1383
                        slist += PsiOptions::instance()->getOption("options.p2p.bytestreams.external-address").toString();
1358
1384
        }
1359
1385
 
1360
1386
        // set up the server
1366
1392
        if(d->s5bServer->isActive())
1367
1393
                d->s5bServer->stop();
1368
1394
 
1369
 
        if (option.dtPort) {
1370
 
                if(!d->s5bServer->start(option.dtPort)) {
1371
 
                        QMessageBox::warning(0, tr("Warning"), tr("Unable to bind to port %1 for Data Transfer.\nThis may mean you are already running another instance of Psi. You may experience problems sending and/or receiving files.").arg(option.dtPort));
 
1395
        if (PsiOptions::instance()->getOption("options.p2p.bytestreams.listen-port").toInt()) {
 
1396
                if(!d->s5bServer->start(PsiOptions::instance()->getOption("options.p2p.bytestreams.listen-port").toInt())) {
 
1397
                        QMessageBox::warning(0, tr("Warning"), tr("Unable to bind to port %1 for Data Transfer.\nThis may mean you are already running another instance of Psi. You may experience problems sending and/or receiving files.").arg(PsiOptions::instance()->getOption("options.p2p.bytestreams.listen-port").toInt()));
1372
1398
                }
1373
1399
        }
1374
1400
}
1375
1401
 
1376
1402
void PsiCon::doSleep()
1377
1403
{
1378
 
        setGlobalStatus(Status("",tr("Computer went to sleep"),0,false));
 
1404
        setGlobalStatus(Status(Status::Offline, tr("Computer went to sleep"), 0));
1379
1405
}
1380
1406
 
1381
1407
void PsiCon::doWakeup()
1384
1410
        //setGlobalStatus(Status());
1385
1411
 
1386
1412
        foreach(PsiAccount* account, d->contactList->enabledAccounts()) {
1387
 
                if (account->userAccount().opt_reconn) {
 
1413
                if (account->userAccount().opt_connectAfterSleep) {
1388
1414
                        // Should we do this when the network comes up ?
1389
1415
                        account->setStatus(Status("", "", account->userAccount().priority));
1390
1416
                }
1391
1417
        }
1392
1418
}
1393
1419
 
1394
 
 
1395
 
QList<PsiToolBar*> PsiCon::toolbarList() const
1396
 
{
1397
 
        return d->mainwin->toolbars;
1398
 
}
1399
 
 
1400
 
PsiToolBar *PsiCon::findToolBar(QString group, int index)
1401
 
{
1402
 
        PsiToolBar *toolBar = 0;
1403
 
 
1404
 
        if (( group == "mainWin" ) && (index < d->mainwin->toolbars.size()))
1405
 
                toolBar = d->mainwin->toolbars.at(index);
1406
 
 
1407
 
        return toolBar;
1408
 
}
1409
 
 
1410
 
void PsiCon::buildToolbars()
1411
 
{
1412
 
        d->mainwin->buildToolbars();
1413
 
}
1414
 
 
1415
 
bool PsiCon::getToolbarLocation(Q3DockWindow* dw, Qt::Dock& dock, int& index, bool& nl, int& extraOffset) const
1416
 
{
1417
 
        return d->mainwin->getLocation(dw, dock, index, nl, extraOffset);
1418
 
}
1419
 
 
1420
1420
PsiActionList *PsiCon::actionList() const
1421
1421
{
1422
1422
        return d->actionList;
1445
1445
        }
1446
1446
}
1447
1447
 
 
1448
QString PsiCon::optionsFile() const
 
1449
{
 
1450
        return pathToProfile(activeProfile) + "/options.xml";
 
1451
}
1448
1452
 
 
1453
void PsiCon::forceSavePreferences()
 
1454
{
 
1455
        PsiOptions::instance()->save(optionsFile());
 
1456
}
 
1457
 
1449
1458
#include "psicon.moc"