source: psi/trunk/src/psicon.cpp@ 84

Last change on this file since 84 was 2, checked in by dmik, 19 years ago

Imported original Psi 0.10 sources from Affinix

File size: 35.3 KB
Line 
1/*
2 * psicon.cpp - core of Psi
3 * Copyright (C) 2001, 2002 Justin Karneges
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this 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"psicon.h"
22
23#include<qptrlist.h>
24#include<qapplication.h>
25#include<qdesktopwidget.h>
26#include<qguardedptr.h>
27#include<qiconset.h>
28#include<qcolor.h>
29#include<qimage.h>
30#include<qstylesheet.h>
31#include<qpixmapcache.h>
32
33#include"s5b.h"
34#include"psiaccount.h"
35#include"contactview.h"
36#include"common.h"
37#include"mainwin.h"
38#include"idle.h"
39#include"accountdlg.h"
40#include"statusdlg.h"
41#include"options/optionsdlg.h"
42#include"options/toolbardlg.h"
43#include"groupchatdlg.h"
44#include"userlist.h"
45#include"eventdlg.h"
46#include"eventdb.h"
47#include"openpgp.h"
48#include"gnupg.h"
49#include"proxy.h"
50#include"psipng.h"
51#ifdef PSIMNG
52#include"psimng.h"
53#endif
54#include"psitextview.h"
55#include"alerticon.h"
56#include"iconselect.h"
57#include"psitoolbar.h"
58#include"filetransfer.h"
59#include"filetransdlg.h"
60#include"psiactionlist.h"
61#include"systemwatch.h"
62#include"globalaccelman.h"
63#include "tabdlg.h"
64#include "chatdlg.h"
65
66#ifdef Q_WS_MAC
67#include "mac_dock.h"
68#endif
69
70//----------------------------------------------------------------------------
71// PsiIconFactory
72//----------------------------------------------------------------------------
73class PsiIconFactory : public QIconFactory
74{
75public:
76 PsiIconFactory();
77
78 QPixmap *createPixmap(const QIconSet &, QIconSet::Size, QIconSet::Mode, QIconSet::State);
79};
80
81PsiIconFactory::PsiIconFactory()
82{
83 setAutoDelete(true);
84}
85
86QPixmap *PsiIconFactory::createPixmap(const QIconSet &iconSet, QIconSet::Size size, QIconSet::Mode mode, QIconSet::State state)
87{
88 Q_UNUSED(size);
89 Q_UNUSED(mode);
90 Q_UNUSED(state);
91
92 QPixmap pix = iconSet.pixmap(size, QIconSet::Normal, state);
93 if ( mode == QIconSet::Disabled && !pix.isNull() ) {
94 QImage img = pix.convertToImage();
95 if ( img.depth() != 32 )
96 img = img.convertDepth(32);
97 img.setAlphaBuffer(true);
98
99 for (int x = 0; x < img.width(); x++) {
100 for (int y = 0; y < img.height(); y++) {
101 QRgb *rgb = (QRgb *)img.scanLine(y) + x;
102 QColor col(*rgb);
103
104 // bigger divisor will result in darker shades of gray
105 int gray = (col.red() + col.green() + col.blue()) / 3;
106 if ( gray > 0xFF )
107 gray = 0xFF;
108 int alpha = qAlpha(*rgb) /*+ 150*/;
109 if ( alpha > 0xFF )
110 alpha = 0xFF;
111 *rgb = qRgba(gray, gray, gray, alpha);
112 }
113 }
114
115 QPixmap *pix = new QPixmap(img);
116 return pix;
117 }
118
119 return 0;
120}
121
122//----------------------------------------------------------------------------
123// PsiConObject
124//----------------------------------------------------------------------------
125class PsiConObject : public QObject
126{
127 Q_OBJECT
128public:
129 PsiConObject(QObject *parent)
130 : QObject(parent, "PsiConObject")
131 {
132 QImage::inputFormats(); // make sure, that the Qt built-in formats are initialized before our custom ones
133
134 initPsiPngIO(); // our custom animation format
135#ifdef PSIMNG
136 initPsiMngIO();
137#endif
138 QIconFactory::installDefaultFactory(new PsiIconFactory);
139
140 QDir p(g.pathHome);
141 QDir v(g.pathHome + "/tmp-sounds");
142 if(!v.exists())
143 p.mkdir("tmp-sounds");
144 Iconset::setSoundPrefs(v.absPath(), this, SLOT(playSound(QString)));
145 URLLabel::connectOpenURL(this, SLOT(openURL(QString)));
146 QStyleSheet::setDefaultSheet( PsiTextView::styleSheet() );
147 }
148
149 ~PsiConObject()
150 {
151 // removing temp dirs
152 QDir p(g.pathHome);
153 QDir v(g.pathHome + "/tmp-sounds");
154 folderRemove(v);
155 }
156
157public slots:
158 void playSound(QString file)
159 {
160 if ( file.isEmpty() || !useSound )
161 return;
162
163 soundPlay(file);
164 }
165
166 void openURL(QString url)
167 {
168 ::openURL(url);
169 }
170
171private:
172 // ripped from profiles.cpp
173 bool folderRemove(const QDir &_d)
174 {
175 QDir d = _d;
176
177 QStringList entries = d.entryList();
178 for(QStringList::Iterator it = entries.begin(); it != entries.end(); ++it) {
179 if(*it == "." || *it == "..")
180 continue;
181 QFileInfo info(d, *it);
182 if(info.isDir()) {
183 if(!folderRemove(QDir(info.filePath())))
184 return FALSE;
185 }
186 else {
187 //printf("deleting [%s]\n", info.filePath().latin1());
188 d.remove(info.fileName());
189 }
190 }
191 QString name = d.dirName();
192 if(!d.cdUp())
193 return FALSE;
194 //printf("removing folder [%s]\n", d.filePath(name).latin1());
195 d.rmdir(name);
196
197 return TRUE;
198 }
199};
200
201//----------------------------------------------------------------------------
202// AccountsComboBox
203//----------------------------------------------------------------------------
204AccountsComboBox::AccountsComboBox(PsiCon *_psi, QWidget *parent, bool online_only)
205:QComboBox(parent), onlineOnly(online_only)
206{
207 psi = _psi;
208 // TODO: Status changes of accounts should be notified when onlineOnly is true
209 connect(psi, SIGNAL(accountCountChanged()), this, SLOT(updateAccounts()));
210 connect(psi, SIGNAL(destroyed()), SLOT(deleteMe()));
211 connect(this, SIGNAL(activated(int)), this, SLOT(changeAccount()));
212 if (online_only)
213 connect(psi, SIGNAL(accountActivityChanged()), this, SLOT(updateAccounts()));
214
215 pa = 0;
216 setSizePolicy(QSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Fixed ));
217
218 if(!psi->accountList(TRUE).isEmpty())
219 setAccount(psi->accountList(TRUE).getFirst());
220}
221
222AccountsComboBox::~AccountsComboBox()
223{
224}
225
226void AccountsComboBox::setAccount(PsiAccount *_pa)
227{
228 pa = _pa;
229 updateAccounts();
230}
231
232void AccountsComboBox::changeAccount()
233{
234 int i = currentItem();
235
236 PsiAccountListIt it(psi->accountList(TRUE));
237 int n = 0;
238 bool found = false;
239 for(PsiAccount *p; (p = it.current()); ++it) {
240 if (!onlineOnly || p->loggedIn()) {
241 if(i == n) {
242 pa = p;
243 found = true;
244 break;
245 }
246 ++n;
247 }
248 }
249 if(!found)
250 pa = 0;
251
252 activated(pa);
253}
254
255void AccountsComboBox::updateAccounts()
256{
257 clear();
258 PsiAccountListIt it(psi->accountList(TRUE));
259 int n = 0;
260 bool found = false;
261 PsiAccount *firstAccount = 0;
262 for(PsiAccount *p; (p = it.current()); ++it) {
263 if (!onlineOnly || p->loggedIn()) {
264 insertItem(p->nameWithJid());
265 if(p == pa) {
266 setCurrentItem(n);
267 found = true;
268 }
269 if (!firstAccount)
270 firstAccount = p;
271 ++n;
272 }
273 }
274 if(!found) {
275 // choose a different account
276 pa = firstAccount;
277 activated(pa);
278 }
279}
280
281void AccountsComboBox::deleteMe()
282{
283 delete this;
284}
285
286
287//----------------------------------------------------------------------------
288// PsiCon::Private
289//----------------------------------------------------------------------------
290
291struct item_dialog
292{
293 QWidget *widget;
294 QString className;
295};
296
297class PsiCon::Private
298{
299public:
300 Private() {
301 iconSelect = 0;
302 //the list 'owns' the tabs
303 tabs.setAutoDelete( true );
304 tabControlledChats.setAutoDelete( false );
305 }
306 ~Private() {
307 if ( iconSelect )
308 delete iconSelect;
309 }
310
311 void saveProfile(UserAccountList acc = UserAccountList())
312 {
313 pro.recentGCList = recentGCList;
314 pro.recentBrowseList = recentBrowseList;
315 pro.lastStatusString = lastStatusString;
316 pro.useSound = useSound;
317 pro.prefs = option;
318 if ( proxy )
319 pro.proxyList = proxy->itemList();
320
321 if ( acc.count() )
322 pro.acc = acc;
323
324 pro.toFile(pathToProfileConfig(activeProfile));
325 }
326
327 void updateIconSelect()
328 {
329 Iconset iss;
330 QPtrListIterator<Iconset> iconsets(is->emoticons);
331 Iconset *iconset;
332 while ( (iconset = iconsets.current()) != 0 ) {
333 iss += *iconset;
334
335 ++iconsets;
336 }
337
338 iconSelect->setIconset(iss);
339 }
340
341 PsiAccount *queueLowestEventId(bool includeDND)
342 {
343 PsiAccount *low = 0;
344 int low_id = 0;
345 int low_prior = option.EventPriorityDontCare;
346
347 PsiAccountListIt it(listEnabled);
348 for ( PsiAccount *pa; (pa = it.current()); ++it ) {
349 int n = pa->eventQueue()->nextId();
350 if ( n == -1 )
351 continue;
352
353 if ( !includeDND && pa->status().show() == "dnd" )
354 continue;
355
356 int p = pa->eventQueue()->peekNext()->priority();
357 if ( !low || (n < low_id && p == low_prior) || p > low_prior ) {
358 low = pa;
359 low_id = n;
360 low_prior = p;
361 }
362 }
363
364 return low;
365 }
366
367
368 PsiAccountList list;
369 PsiAccountList listEnabled;
370 UserProfile pro;
371 QString lastStatusString;
372 MainWin *mainwin;
373 Idle idle;
374 QPtrList<item_dialog> dialogList;
375 QPtrList<TabDlg> tabs;
376 QPtrList<ChatDlg> tabControlledChats;
377 int eventId;
378 QStringList recentGCList, recentBrowseList, recentNodeList;
379 EDB *edb;
380 OpenPGP::Engine *pgp;
381 bool pgpReady;
382 S5BServer *s5bServer;
383 ProxyManager *proxy;
384 IconSelectPopup *iconSelect;
385 QRect mwgeom;
386 FileTransDlg *ftwin;
387 PsiActionList *actionList;
388 GlobalAccelManager *globalAccelManager;
389};
390
391//----------------------------------------------------------------------------
392// PsiCon
393//----------------------------------------------------------------------------
394
395PsiCon::PsiCon()
396:QObject(0)
397{
398 //pdb(DEBUG_JABCON, QString("%1 v%2\n By Justin Karneges\n infiniti@affinix.com\n\n").arg(PROG_NAME).arg(PROG_VERSION));
399
400 d = new Private;
401
402 d->lastStatusString = "";
403 useSound = true;
404 d->mainwin = 0;
405 d->ftwin = 0;
406
407 d->dialogList.setAutoDelete(true);
408
409 d->eventId = 0;
410 d->edb = new EDBFlatFile;
411
412 d->pgp = 0;
413 d->pgpReady = false;
414 d->s5bServer = 0;
415 d->proxy = 0;
416
417 d->actionList = 0;
418}
419
420PsiCon::~PsiCon()
421{
422 deinit();
423
424 delete d->actionList;
425 delete d->pgp;
426 delete d->edb;
427 delete d;
428}
429
430bool PsiCon::init()
431{
432 // load the profile
433 d->pro.reset();
434 d->pro.fromFile(pathToProfileConfig(activeProfile));
435
436 QDir profileDir( pathToProfile( activeProfile ) );
437 profileDir.rmdir( "info" ); // remove unused dir
438
439 d->recentGCList = d->pro.recentGCList;
440 d->recentBrowseList = d->pro.recentBrowseList;
441 d->lastStatusString = d->pro.lastStatusString;
442 useSound = d->pro.useSound;
443
444 option = d->pro.prefs;
445
446 new PsiConObject(this);
447
448 // first thing, try to load the iconset
449 is = new PsiIconset();
450 if( !is->loadAll() ) {
451 //option.iconset = "stellar";
452 //if(!is.load(option.iconset)) {
453 QMessageBox::critical(0, tr("Error"), tr("Unable to load iconset! Please make sure Psi is properly installed."));
454 return false;
455 //}
456 }
457
458 if ( !d->actionList )
459 d->actionList = new PsiActionList( this );
460
461 d->iconSelect = new IconSelectPopup(0);
462 d->updateIconSelect();
463
464 // setup the main window
465 d->mainwin = new MainWin(option.alwaysOnTop, (option.useDock && option.dockToolMW), this, "psimain");
466 d->mainwin->setUseDock(option.useDock);
467
468 connect(d->mainwin, SIGNAL(closeProgram()), SLOT(closeProgram()));
469 connect(d->mainwin, SIGNAL(changeProfile()), SLOT(changeProfile()));
470 connect(d->mainwin, SIGNAL(doManageAccounts()), SLOT(doManageAccounts()));
471 connect(d->mainwin, SIGNAL(doGroupChat()), SLOT(doGroupChat()));
472 connect(d->mainwin, SIGNAL(blankMessage()), SLOT(doNewBlankMessage()));
473 connect(d->mainwin, SIGNAL(statusChanged(int)), SLOT(statusMenuChanged(int)));
474 connect(d->mainwin, SIGNAL(doOptions()), SLOT(doOptions()));
475 connect(d->mainwin, SIGNAL(doToolbars()), SLOT(doToolbars()));
476 connect(d->mainwin, SIGNAL(doFileTransDlg()), SLOT(doFileTransDlg()));
477 connect(d->mainwin, SIGNAL(recvNextEvent()), SLOT(recvNextEvent()));
478 connect(d->mainwin, SIGNAL(geomChanged(int, int, int, int)), SLOT(mainWinGeomChanged(int, int, int, int)));
479 connect(this, SIGNAL(emitOptionsUpdate()), d->mainwin, SLOT(optionsUpdate()));
480
481 connect(this, SIGNAL(emitOptionsUpdate()), d->mainwin->cvlist, SLOT(optionsUpdate()));
482
483 // if the coordinates are out of the desktop bounds, reset to the top left
484 QRect mwgeom = d->pro.mwgeom;
485 QDesktopWidget *pdesktop = QApplication::desktop();
486 int nscreen = pdesktop->screenNumber(mwgeom.topLeft());
487 QRect r = pdesktop->screenGeometry(nscreen);
488
489 int pad = 10;
490 if((mwgeom.width() + pad * 2) > r.width())
491 mwgeom.setWidth(r.width() - pad * 2);
492 if((mwgeom.height() + pad * 2) > r.height())
493 mwgeom.setHeight(r.height() - pad * 2);
494 if(mwgeom.left() < r.left())
495 mwgeom.moveLeft(r.left());
496 if(mwgeom.right() >= r.right())
497 mwgeom.moveRight(r.right() - 1);
498 if(mwgeom.top() < r.top())
499 mwgeom.moveTop(r.top());
500 if(mwgeom.bottom() >= r.bottom())
501 mwgeom.moveBottom(r.bottom() - 1);
502
503 d->mwgeom = mwgeom;
504 d->mainwin->move(mwgeom.x(), mwgeom.y());
505 d->mainwin->resize(mwgeom.width(), mwgeom.height());
506
507 d->ftwin = new FileTransDlg(this);
508
509 if(!(option.useDock && option.dockHideMW))
510 d->mainwin->show();
511
512 d->idle.start();
513
514 // S5B
515 d->s5bServer = new S5BServer;
516 s5b_init();
517
518 // pgp
519 if(use_gpg) {
520 option.pgp = "gpg";
521 pgp_init(option.pgp);
522 }
523
524 // proxy
525 d->proxy = new ProxyManager(this);
526 d->proxy->setItemList(d->pro.proxyList);
527 connect(d->proxy, SIGNAL(settingsChanged()), SLOT(proxy_settingsChanged()));
528
529 // load accounts
530 loadAccounts(d->pro.acc);
531
532 // Connect to the system monitor
533 SystemWatch* sw = SystemWatch::instance();
534 connect(sw, SIGNAL(sleep()), this, SLOT(doSleep()));
535 connect(sw, SIGNAL(idleSleep()), this, SLOT(doSleep()));
536 connect(sw, SIGNAL(wakeup()), this, SLOT(doWakeup()));
537
538 // global accelerator manager
539 d->globalAccelManager = new GlobalAccelManager;
540 d->globalAccelManager->setAccel(option.globalAccels[0]);
541 d->globalAccelManager->setAccel(option.globalAccels[1]);
542 connect(d->globalAccelManager, SIGNAL(activated(int)), SLOT(accel_activated(int)));
543
544 return true;
545}
546
547void PsiCon::deinit()
548{
549 // this deletes all dialogs except for mainwin
550 deleteAllDialogs();
551
552 d->idle.stop();
553
554 // shut down all accounts
555 UserAccountList acc = unloadAccounts();
556
557 // delete s5b server
558 delete d->s5bServer;
559
560 delete d->ftwin;
561
562 if(d->mainwin) {
563 // shut down mainwin
564 QRect mwgeom;
565 if ( !d->mainwin->isHidden() && !d->mainwin->isMinimized() ) {
566 mwgeom.setX(d->mainwin->x());
567 mwgeom.setY(d->mainwin->y());
568 mwgeom.setWidth(d->mainwin->width());
569 mwgeom.setHeight(d->mainwin->height());
570 }
571 else
572 mwgeom = d->mwgeom;
573
574 delete d->mainwin;
575 d->mainwin = 0;
576
577 d->pro.mwgeom = mwgeom;
578 }
579
580 // unload iconset
581 delete is;
582
583 // save profile
584 d->saveProfile(acc);
585}
586
587PsiAccount *PsiCon::loadAccount(const UserAccount &acc)
588{
589 PsiAccount *pa = new PsiAccount(acc, this);
590 connect(&d->idle, SIGNAL(secondsIdle(int)), pa, SLOT(secondsIdle(int)));
591 connect(pa, SIGNAL(updatedActivity()), SLOT(pa_updatedActivity()));
592 connect(pa, SIGNAL(updatedAccount()), SLOT(pa_updatedAccount()));
593 connect(pa, SIGNAL(queueChanged()), SLOT(queueChanged()));
594 connect(pa, SIGNAL(enabledChanged()), SIGNAL(accountCountChanged()));
595 accountAdded(pa);
596 if(d->s5bServer)
597 pa->client()->s5bManager()->setServer(d->s5bServer);
598 return pa;
599}
600
601void PsiCon::loadAccounts(const UserAccountList &list)
602{
603 if(list.count() > 0) {
604 for(UserAccountList::ConstIterator it = list.begin(); it != list.end(); ++it)
605 loadAccount(*it);
606 }
607 else {
608 // if there are no accounts, then prompt the user to add one
609 AccountAddDlg *w = new AccountAddDlg(this, 0);
610 w->show();
611 }
612}
613
614UserAccountList PsiCon::unloadAccounts()
615{
616 UserAccountList acc;
617
618 QPtrListIterator<PsiAccount> it(d->list);
619 for(PsiAccount *pa; (pa = it.current());) {
620 acc += pa->userAccount();
621 delete pa;
622 }
623
624 return acc;
625}
626
627const PsiAccountList & PsiCon::accountList(bool enabledOnly) const
628{
629 if(enabledOnly)
630 return d->listEnabled;
631 else
632 return d->list;
633}
634
635ContactView *PsiCon::contactView() const
636{
637 if(d->mainwin)
638 return d->mainwin->cvlist;
639 else
640 return 0;
641}
642
643EDB *PsiCon::edb() const
644{
645 return d->edb;
646}
647
648OpenPGP::Engine *PsiCon::pgp() const
649{
650 if(d->pgp && d->pgpReady)
651 return d->pgp;
652 else
653 return 0;
654}
655
656ProxyManager *PsiCon::proxy() const
657{
658 return d->proxy;
659}
660
661FileTransDlg *PsiCon::ftdlg() const
662{
663 return d->ftwin;
664}
665
666void PsiCon::link(PsiAccount *pa)
667{
668 d->list.append(pa);
669 if(pa->enabled() && !d->listEnabled.containsRef(pa))
670 d->listEnabled.append(pa);
671 connect(pa, SIGNAL(updatedActivity()), this, SIGNAL(accountActivityChanged()));
672 accountCountChanged();
673}
674
675void PsiCon::unlink(PsiAccount *pa)
676{
677 disconnect(pa, SIGNAL(updatedActivity()), this, SIGNAL(accountActivityChanged()));
678 d->list.remove(pa);
679 d->listEnabled.remove(pa);
680 accountCountChanged();
681}
682
683void PsiCon::closeProgram()
684{
685 quit(QuitProgram);
686}
687
688void PsiCon::changeProfile()
689{
690 bool ok = true;
691 PsiAccountListIt it(d->listEnabled);
692 for(PsiAccount *pa; (pa = it.current()); ++it) {
693 if(pa->isActive()) {
694 ok = false;
695 break;
696 }
697 }
698
699 if(!ok) {
700 QMessageBox::information(0, CAP(tr("Error")), tr("Please disconnect before changing the profile."));
701 return;
702 }
703
704 quit(QuitProfile);
705}
706
707void PsiCon::doManageAccounts()
708{
709 AccountManageDlg *w = (AccountManageDlg *)dialogFind("AccountManageDlg");
710 if(w)
711 bringToFront(w);
712 else {
713 w = new AccountManageDlg(this);
714 w->show();
715 }
716}
717
718void PsiCon::doGroupChat()
719{
720 PsiAccount *pa = d->listEnabled.getFirst();
721 if(!pa)
722 return;
723
724 GCJoinDlg *w = new GCJoinDlg(this, pa);
725 w->show();
726}
727
728void PsiCon::doNewBlankMessage()
729{
730 PsiAccount *pa = d->listEnabled.getFirst();
731 if(!pa)
732 return;
733
734 EventDlg *w = createEventDlg("", pa);
735 w->show();
736}
737
738EventDlg *PsiCon::createEventDlg(const QString &to, PsiAccount *pa)
739{
740 EventDlg *w = new EventDlg(to, this, pa);
741 connect(this, SIGNAL(emitOptionsUpdate()), w, SLOT(optionsUpdate()));
742 return w;
743}
744
745void PsiCon::updateContactGlobal(PsiAccount *pa, const Jid &j)
746{
747 QPtrListIterator<item_dialog> it(d->dialogList);
748 for(item_dialog *i; (i = it.current()); ++it) {
749 if(i->className == "EventDlg") {
750 EventDlg *e = (EventDlg *)i->widget;
751 if(e->psiAccount() == pa)
752 e->updateContact(j);
753 }
754 }
755}
756
757QWidget *PsiCon::dialogFind(const char *className)
758{
759 QPtrListIterator<item_dialog> it(d->dialogList);
760 for(item_dialog *i; (i = it.current()); ++it) {
761 // does the classname and jid match?
762 if(i->className == className) {
763 return i->widget;
764 }
765 }
766 return 0;
767}
768
769TabDlg* PsiCon::newTabs()
770{
771 TabDlg *tab;
772 tab=new TabDlg(this);
773 d->tabs.append(tab);
774 connect (tab, SIGNAL ( isDying(TabDlg*) ), SLOT ( tabDying(TabDlg*) ) );
775 return tab;
776}
777
778TabDlg* PsiCon::getTabs()
779{
780 if (!d->tabs.isEmpty())
781 {
782 return d->tabs.getFirst();
783 }
784 else
785 {
786 return newTabs();
787 }
788}
789
790void PsiCon::tabDying(TabDlg* tab)
791{
792 d->tabs.remove(tab);
793}
794
795bool PsiCon::isChatTabbed(ChatDlg* chat)
796{
797 for (uint i = 0; i < d->tabs.count(); ++i)
798 {
799 if ( d->tabs.at(i)->managesChat(chat) )
800 return true;
801 }
802 return false;
803}
804
805ChatDlg* PsiCon::getChatInTabs(QString jid){
806 for (uint i = 0; i < d->tabs.count(); ++i)
807 {
808 if ( d->tabs.at(i)->getChatPointer(jid) )
809 return d->tabs.at(i)->getChatPointer(jid);
810 }
811 return NULL;
812
813}
814
815TabDlg* PsiCon::getManagingTabs(ChatDlg* chat)
816{
817 for (uint i = 0; i < d->tabs.count(); ++i)
818 {
819 if ( d->tabs.at(i)->managesChat(chat) )
820 return d->tabs.at(i);
821 }
822 return NULL;
823
824}
825
826QPtrList<TabDlg>* PsiCon::getTabSets()
827{
828 return &d->tabs;
829}
830
831bool PsiCon::isChatActiveWindow(ChatDlg* chat)
832{
833 //returns true if chat is on top of a tab pile
834 if ( chat->isHidden() )
835 {
836 return false;
837 }
838 if (!option.useTabs)
839 {
840 return chat->isActiveWindow();
841 }
842 for (uint i = 0; i < d->tabs.count(); ++i)
843 {
844 if ( d->tabs.at(i)->isActiveWindow() )
845 {
846 if ( d->tabs.at(i)->chatOnTop( chat ) )
847 {
848 return true;
849 }
850 }
851 }
852 return false;
853}
854
855void PsiCon::dialogRegister(QWidget *w)
856{
857 item_dialog *i = new item_dialog;
858 i->widget = w;
859 i->className = w->className();
860 d->dialogList.append(i);
861}
862
863void PsiCon::dialogUnregister(QWidget *w)
864{
865 QPtrListIterator<item_dialog> it(d->dialogList);
866 for(item_dialog *i; (i = it.current()); ++it) {
867 if(i->widget == w) {
868 d->dialogList.removeRef(i);
869 return;
870 }
871 }
872}
873
874void PsiCon::deleteAllDialogs()
875{
876 QPtrListIterator<item_dialog> it(d->dialogList);
877 for(item_dialog *i; (i = it.current());)
878 delete i->widget;
879 d->dialogList.clear();
880}
881
882AccountsComboBox *PsiCon::accountsComboBox(QWidget *parent, bool online_only)
883{
884 AccountsComboBox *acb = new AccountsComboBox(this, parent, online_only);
885 return acb;
886}
887
888bool PsiCon::isValid(PsiAccount *pa)
889{
890 if(d->list.findRef(pa) == -1)
891 return false;
892 else
893 return true;
894}
895
896void PsiCon::createAccount(const QString &name, const Jid &j, const QString &pass, bool opt_host, const QString &host, int port, bool ssl, int proxy)
897{
898 UserAccount acc;
899 acc.name = name;
900
901 acc.jid = j.full();
902 if(!pass.isEmpty()) {
903 acc.opt_pass = true;
904 acc.pass = pass;
905 }
906
907 acc.opt_host = opt_host;
908 acc.host = host;
909 acc.port = port;
910
911 acc.opt_ssl = ssl;
912 acc.proxy_index = proxy;
913
914 PsiAccount *pa = loadAccount(acc);
915 saveAccounts();
916
917 // pop up the modify dialog so the user can customize the new account
918 pa->modify();
919}
920
921void PsiCon::modifyAccount(PsiAccount *pa)
922{
923 pa->modify();
924}
925
926void PsiCon::removeAccount(PsiAccount *pa)
927{
928 accountRemoved(pa);
929 pa->deleteQueueFile();
930 delete pa;
931 saveAccounts();
932}
933
934void PsiCon::enableAccount(PsiAccount *pa, bool e)
935{
936 if(e){
937 if(!d->listEnabled.containsRef(pa))
938 d->listEnabled.append(pa);
939 }else
940 d->listEnabled.remove(pa);
941}
942
943void PsiCon::statusMenuChanged(int x)
944{
945 if(x == STATUS_OFFLINE && !option.askOffline) {
946 setGlobalStatus(Status("","Logged out",0,false));
947 if(option.useDock == true)
948 d->mainwin->setTrayToolTip(Status("","",0,false));
949 }
950 else {
951 if(x == STATUS_ONLINE && !option.askOnline) {
952 setGlobalStatus(Status());
953 if(option.useDock == true)
954 d->mainwin->setTrayToolTip(Status());
955 }
956 else if(x == STATUS_INVISIBLE){
957 Status s("","",0,true);
958 s.setIsInvisible(true);
959 setGlobalStatus(s);
960 if(option.useDock == true)
961 d->mainwin->setTrayToolTip(s);
962 }
963 else {
964 // Create a dialog with the last status message
965 StatusSetDlg *w = new StatusSetDlg(this, makeStatus(x, d->lastStatusString));
966 connect(w, SIGNAL(set(const Status &)), SLOT(setStatusFromDialog(const Status &)));
967 connect(w, SIGNAL(cancelled()), SLOT(updateMainwinStatus()));
968 if(option.useDock == true)
969 connect(w, SIGNAL(set(const Status &)), d->mainwin, SLOT(setTrayToolTip(const Status &)));
970 w->show();
971 }
972 }
973}
974
975void PsiCon::setStatusFromDialog(const Status &s)
976{
977 d->lastStatusString = s.status();
978 setGlobalStatus(s);
979}
980
981void PsiCon::setGlobalStatus(const Status &s)
982{
983 // Check whether all accounts are logged off
984 bool allOffline = true;
985 PsiAccountListIt i(d->listEnabled);
986 PsiAccount *pa;
987 for( ; (pa = i.current()); ++i) {
988 if ( pa->isActive() ) {
989 allOffline = false;
990 break;
991 }
992 }
993
994 // globally set each account which is logged in
995 PsiAccountListIt it(d->listEnabled);
996 for( ; (pa = it.current()); ++it)
997 if (allOffline || pa->isActive())
998 pa->setStatus(s);
999}
1000
1001void PsiCon::pa_updatedActivity()
1002{
1003 PsiAccount *pa = (PsiAccount *)sender();
1004 accountUpdated(pa);
1005
1006 // update s5b server
1007 updateS5BServerAddresses();
1008
1009 updateMainwinStatus();
1010}
1011
1012void PsiCon::pa_updatedAccount()
1013{
1014 PsiAccount *pa = (PsiAccount *)sender();
1015 accountUpdated(pa);
1016
1017 saveAccounts();
1018}
1019
1020void PsiCon::saveAccounts()
1021{
1022 UserAccountList acc;
1023 PsiAccountListIt it(d->list);
1024 for(PsiAccount *pa; (pa = it.current()); ++it)
1025 acc += pa->userAccount();
1026
1027 d->pro.proxyList = d->proxy->itemList();
1028 //d->pro.acc = acc;
1029 //d->pro.toFile(pathToProfileConfig(activeProfile));
1030 d->saveProfile(acc);
1031}
1032
1033void PsiCon::updateMainwinStatus()
1034{
1035 bool active = false;
1036 bool loggedIn = false;
1037 int state = STATUS_ONLINE;
1038 PsiAccountListIt it(d->listEnabled);
1039 for(PsiAccount *pa; (pa = it.current()); ++it) {
1040 if(pa->isActive())
1041 active = true;
1042 if(pa->loggedIn()) {
1043 loggedIn = true;
1044 state = makeSTATUS(pa->status());
1045 }
1046 }
1047 if(loggedIn)
1048 d->mainwin->decorateButton(state);
1049 else {
1050 if(active)
1051 d->mainwin->decorateButton(-1);
1052 else
1053 d->mainwin->decorateButton(STATUS_OFFLINE);
1054 }
1055}
1056
1057void PsiCon::setToggles(bool tog_offline, bool tog_away, bool tog_agents, bool tog_hidden, bool tog_self)
1058{
1059 if(d->listEnabled.count() > 1)
1060 return;
1061
1062 d->mainwin->cvlist->setShowOffline(tog_offline);
1063 d->mainwin->cvlist->setShowAway(tog_away);
1064 d->mainwin->cvlist->setShowAgents(tog_agents);
1065 d->mainwin->cvlist->setShowHidden(tog_hidden);
1066 d->mainwin->cvlist->setShowSelf(tog_self);
1067}
1068
1069void PsiCon::getToggles(bool *tog_offline, bool *tog_away, bool *tog_agents, bool *tog_hidden, bool *tog_self)
1070{
1071 *tog_offline = d->mainwin->cvlist->isShowOffline();
1072 *tog_away = d->mainwin->cvlist->isShowAway();
1073 *tog_agents = d->mainwin->cvlist->isShowAgents();
1074 *tog_hidden = d->mainwin->cvlist->isShowHidden();
1075 *tog_self = d->mainwin->cvlist->isShowSelf();
1076}
1077
1078void PsiCon::doOptions()
1079{
1080 OptionsDlg *w = (OptionsDlg *)dialogFind("OptionsDlg");
1081 if(w)
1082 bringToFront(w);
1083 else {
1084 w = new OptionsDlg(this, option);
1085 connect(w, SIGNAL(applyOptions(const Options &)), SLOT(slotApplyOptions(const Options &)));
1086 w->show();
1087 }
1088}
1089
1090void PsiCon::doFileTransDlg()
1091{
1092 bringToFront(d->ftwin);
1093}
1094
1095QWidget *PsiCon::doToolbars()
1096{
1097 ToolbarDlg *w = (ToolbarDlg *)dialogFind("ToolbarDlg");
1098 if (w)
1099 bringToFront(w);
1100 else {
1101 w = new ToolbarDlg(this);
1102 w->show();
1103 }
1104
1105 return w;
1106}
1107
1108void PsiCon::slotApplyOptions(const Options &opt)
1109{
1110 QString oldpgp = option.pgp;
1111 Options oldOpt = option;
1112 bool notifyRestart = true;
1113
1114 option = opt;
1115
1116 if ( option.useTabs != oldOpt.useTabs || opt.chatLineEdit != oldOpt.chatLineEdit ) {
1117 QMessageBox::information(0, tr("Information"), tr("Some of the options you changed will only have full effect upon restart."));
1118 notifyRestart = false;
1119 }
1120
1121 // change icon set
1122 if ( option.systemIconset != oldOpt.systemIconset ||
1123 option.emoticons != oldOpt.emoticons ||
1124 option.defaultRosterIconset != oldOpt.defaultRosterIconset ||
1125 option.serviceRosterIconset != oldOpt.serviceRosterIconset ||
1126 option.customRosterIconset != oldOpt.customRosterIconset )
1127 {
1128 if ( notifyRestart && is->optionsChanged(&oldOpt) )
1129 QMessageBox::information(0, tr("Information"), tr("The complete iconset update will happen on next Psi start."));
1130
1131 // update icon selector
1132 d->updateIconSelect();
1133
1134 // flush the QPixmapCache
1135 QPixmapCache::clear();
1136 }
1137
1138 if ( oldOpt.alertStyle != option.alertStyle )
1139 alertIconUpdateAlertStyle();
1140
1141 mainWin()->buildToolbars();
1142
1143 /*// change pgp engine
1144 if(option.pgp != oldpgp) {
1145 if(d->pgp) {
1146 delete d->pgp;
1147 d->pgp = 0;
1148 pgpToggled(false);
1149 }
1150 pgp_init(option.pgp);
1151 }*/
1152
1153 // update s5b
1154 if(oldOpt.dtPort != option.dtPort)
1155 s5b_init();
1156 updateS5BServerAddresses();
1157
1158 // mainwin stuff
1159 d->mainwin->setWindowOpts(option.alwaysOnTop, (option.useDock && option.dockToolMW));
1160 d->mainwin->setUseDock(option.useDock);
1161
1162 // notify about options change
1163 emitOptionsUpdate();
1164
1165 // save just the options
1166 //d->pro.prefs = option;
1167 //d->pro.toFile(pathToProfileConfig(activeProfile));
1168 d->saveProfile();
1169}
1170
1171int PsiCon::getId()
1172{
1173 return d->eventId++;
1174}
1175
1176int PsiCon::queueCount()
1177{
1178 int total = 0;
1179 PsiAccountListIt it(d->listEnabled);
1180 for(PsiAccount *pa; (pa = it.current()); ++it)
1181 total += pa->eventQueue()->count();
1182 return total;
1183}
1184
1185PsiAccount *PsiCon::queueLowestEventId()
1186{
1187 PsiAccount *low = 0;
1188
1189 low = d->queueLowestEventId( false ); // first try to get event from non-dnd account
1190
1191 // if failed, then get the event from dnd account instead
1192 if ( !low )
1193 low = d->queueLowestEventId( true );
1194
1195 return low;
1196}
1197
1198void PsiCon::queueChanged()
1199{
1200 Icon *nextAnim = 0;
1201 int nextAmount = queueCount();
1202 PsiAccount *pa = queueLowestEventId();
1203 if(pa)
1204 nextAnim = is->event2icon(pa->eventQueue()->peekNext());
1205
1206#ifdef Q_WS_MAC
1207 {
1208 // The Mac Dock icon
1209
1210 // Update the event count
1211 if (nextAmount)
1212 MacDock::overlay(QString::number(nextAmount));
1213 else
1214 MacDock::overlay(QString::null);
1215
1216 // Check if bouncing is necessary
1217 bool doBounce = false;
1218 PsiAccountListIt it(d->listEnabled);
1219 for(PsiAccount *pa; (pa = it.current()); ++it) {
1220 if ( pa->eventQueue()->count() && pa->status().show() != "dnd" ) {
1221 doBounce = true;
1222 break;
1223 }
1224 }
1225
1226 // Bouncy bouncy
1227 if (doBounce) {
1228 if (option.bounceDock != Options::NoBounce) {
1229 MacDock::startBounce();
1230 if (option.bounceDock == Options::BounceOnce)
1231 MacDock::stopBounce();
1232 }
1233 }
1234 else
1235 MacDock::stopBounce();
1236 }
1237#endif
1238
1239 d->mainwin->updateReadNext(nextAnim, nextAmount);
1240}
1241
1242void PsiCon::recvNextEvent()
1243{
1244 /*printf("--- Queue Content: ---\n");
1245 PsiAccountListIt it(d->list);
1246 for(PsiAccount *pa; (pa = it.current()); ++it) {
1247 printf(" Account: [%s]\n", pa->name().latin1());
1248 pa->eventQueue()->printContent();
1249 }*/
1250 PsiAccount *pa = queueLowestEventId();
1251 if(pa)
1252 pa->openNextEvent();
1253}
1254
1255void PsiCon::playSound(const QString &str)
1256{
1257 if(str.isEmpty() || !useSound)
1258 return;
1259
1260 soundPlay(str);
1261}
1262
1263void PsiCon::raiseMainwin()
1264{
1265 d->mainwin->showNoFocus();
1266}
1267
1268const QStringList & PsiCon::recentGCList() const
1269{
1270 return d->recentGCList;
1271}
1272
1273void PsiCon::recentGCAdd(const QString &str)
1274{
1275 // remove it if we have it
1276 for(QStringList::Iterator it = d->recentGCList.begin(); it != d->recentGCList.end(); ++it) {
1277 if(*it == str) {
1278 d->recentGCList.remove(it);
1279 break;
1280 }
1281 }
1282
1283 // put it in the front
1284 d->recentGCList.prepend(str);
1285
1286 // trim the list if bigger than 10
1287 while(d->recentGCList.count() > 10)
1288 d->recentGCList.remove(d->recentGCList.fromLast());
1289}
1290
1291const QStringList & PsiCon::recentBrowseList() const
1292{
1293 return d->recentBrowseList;
1294}
1295
1296void PsiCon::recentBrowseAdd(const QString &str)
1297{
1298 // remove it if we have it
1299 for(QStringList::Iterator it = d->recentBrowseList.begin(); it != d->recentBrowseList.end(); ++it) {
1300 if(*it == str) {
1301 d->recentBrowseList.remove(it);
1302 break;
1303 }
1304 }
1305
1306 // put it in the front
1307 d->recentBrowseList.prepend(str);
1308
1309 // trim the list if bigger than 10
1310 while(d->recentBrowseList.count() > 10)
1311 d->recentBrowseList.remove(d->recentBrowseList.fromLast());
1312}
1313
1314const QStringList & PsiCon::recentNodeList() const
1315{
1316 return d->recentNodeList;
1317}
1318
1319void PsiCon::recentNodeAdd(const QString &str)
1320{
1321 // remove it if we have it
1322 for(QStringList::Iterator it = d->recentNodeList.begin(); it != d->recentNodeList.end(); ++it) {
1323 if(*it == str) {
1324 d->recentNodeList.remove(it);
1325 break;
1326 }
1327 }
1328
1329 // put it in the front
1330 d->recentNodeList.prepend(str);
1331
1332 // trim the list if bigger than 10
1333 while(d->recentNodeList.count() > 10)
1334 d->recentNodeList.remove(d->recentNodeList.fromLast());
1335}
1336
1337void PsiCon::pgp_init(const QString &id)
1338{
1339 if(id.isEmpty())
1340 return;
1341
1342 d->pgp = OpenPGP::createEngine(id);
1343 if(d->pgp) {
1344 connect(d->pgp, SIGNAL(initFinished(bool, const QString &)), SLOT(pgp_initFinished(bool, const QString &)));
1345 connect(d->pgp, SIGNAL(keysUpdated()), SLOT(pgp_keysUpdated()));
1346 d->pgpReady = false;
1347 d->pgp->init();
1348 }
1349}
1350
1351void PsiCon::pgp_initFinished(bool b, const QString &)
1352{
1353 if(b) {
1354 d->pgpReady = true;
1355 if(no_gpg_agent) {
1356 GnuPG *gpg = (GnuPG *)d->pgp;
1357 gpg->setTryAgent(false);
1358 }
1359 pgpToggled(true);
1360 }
1361}
1362
1363void PsiCon::pgp_keysUpdated()
1364{
1365 pgpKeysUpdated();
1366 //QMessageBox::information(0, CAP(tr("OpenPGP")), tr("Psi has detected that you have modified your keyring. That is all."));
1367}
1368
1369void PsiCon::proxy_settingsChanged()
1370{
1371 // properly index accounts
1372 PsiAccountListIt it(d->list);
1373 for(PsiAccount *pa; (pa = it.current()); ++it) {
1374 UserAccount acc = pa->userAccount();
1375 if(acc.proxy_index > 0) {
1376 int x = d->proxy->findOldIndex(acc.proxy_index-1);
1377 if(x == -1)
1378 acc.proxy_index = 0;
1379 else
1380 acc.proxy_index = x+1;
1381 pa->setUserAccount(acc);
1382 }
1383 }
1384
1385 saveAccounts();
1386}
1387
1388void PsiCon::accel_activated(int x)
1389{
1390 switch (x) {
1391 case 1:
1392 recvNextEvent();
1393 break;
1394 case 2:
1395 d->mainwin->toggleVisible();
1396 break;
1397 }
1398}
1399
1400MainWin *PsiCon::mainWin() const
1401{
1402 return d->mainwin;
1403}
1404
1405IconSelectPopup *PsiCon::iconSelectPopup() const
1406{
1407 return d->iconSelect;
1408}
1409
1410void PsiCon::processEvent(PsiEvent *e)
1411{
1412 if ( e->type() == PsiEvent::PGP ) {
1413 e->account()->eventQueue()->dequeue(e);
1414 e->account()->queueChanged();
1415 e->account()->promptPassphrase();
1416 return;
1417 }
1418
1419 if ( !e->account() )
1420 return;
1421
1422 UserListItem *u = e->account()->find(e->jid());
1423 if ( !u ) {
1424 qWarning("SYSTEM MESSAGE: Bug #1. Contact the developers and tell them what you did to make this message appear. Thank you.");
1425 e->account()->eventQueue()->dequeue(e);
1426 e->account()->queueChanged();
1427 return;
1428 }
1429
1430 if( e->type() == PsiEvent::File ) {
1431 FileEvent *fe = (FileEvent *)e;
1432 FileTransfer *ft = fe->takeFileTransfer();
1433 e->account()->eventQueue()->dequeue(e);
1434 e->account()->queueChanged();
1435 e->account()->cpUpdate(*u);
1436 if(ft) {
1437 FileRequestDlg *w = new FileRequestDlg(fe->timeStamp(), ft, e->account());
1438 bringToFront(w);
1439 }
1440 return;
1441 }
1442
1443 bool isChat = false;
1444 bool sentToChatWindow = false;
1445 if ( e->type() == PsiEvent::Message ) {
1446 MessageEvent *me = (MessageEvent *)e;
1447 const Message &m = me->message();
1448 if ( m.type() == "chat" ) {
1449 isChat = true;
1450 sentToChatWindow = me->sentToChatWindow();
1451 }
1452 }
1453
1454 if ( isChat ) {
1455 if ( option.alertOpenChats && sentToChatWindow ) {
1456 // Message already displayed, need only to pop up chat dialog, so that
1457 // it will be read (or marked as read)
1458 ChatDlg *c = (ChatDlg *)e->account()->dialogFind("ChatDlg", e->from());
1459 if(!c)
1460 c = (ChatDlg *)e->account()->dialogFind("ChatDlg", e->jid());
1461 if(!c)
1462 return; // should never happen
1463
1464 e->account()->processChats(e->from()); // this will delete all events, corresponding to that chat dialog
1465 //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.
1466 bringToFront((QWidget *)c);
1467 if ( option.useTabs)
1468 {
1469 TabDlg* tabSet = getManagingTabs(c);
1470 tabSet->selectTab(c);
1471 }
1472 }
1473 else
1474 e->account()->openChat(e->from());
1475 }
1476 else {
1477 // search for an already opened eventdlg
1478 EventDlg *w = (EventDlg *)e->account()->dialogFind("EventDlg", u->jid());
1479
1480 if ( !w ) {
1481 // create the eventdlg
1482 w = e->account()->ensureEventDlg(u->jid());
1483
1484 // load next message
1485 e->account()->processReadNext(*u);
1486 }
1487
1488 bringToFront(w);
1489 }
1490}
1491
1492void PsiCon::mainWinGeomChanged(int x, int y, int w, int h)
1493{
1494 d->mwgeom.setX(x);
1495 d->mwgeom.setY(y);
1496 d->mwgeom.setWidth(w);
1497 d->mwgeom.setHeight(h);
1498}
1499
1500void PsiCon::updateS5BServerAddresses()
1501{
1502 if(!d->s5bServer)
1503 return;
1504
1505 QValueList<QHostAddress> list;
1506
1507 // grab all IP addresses
1508 QPtrListIterator<PsiAccount> it(d->list);
1509 for(PsiAccount *pa; (pa = it.current()); ++it) {
1510 QHostAddress *a = pa->localAddress();
1511 if(!a)
1512 continue;
1513
1514 // don't take dups
1515 bool found = false;
1516 for(QValueList<QHostAddress>::ConstIterator hit = list.begin(); hit != list.end(); ++hit) {
1517 const QHostAddress &ha = *hit;
1518 if(ha == (*a)) {
1519 found = true;
1520 break;
1521 }
1522 }
1523 if(!found)
1524 list += (*a);
1525 }
1526
1527 // convert to stringlist
1528 QStringList slist;
1529 for(QValueList<QHostAddress>::ConstIterator hit = list.begin(); hit != list.end(); ++hit)
1530 slist += (*hit).toString();
1531
1532 // add external
1533 if(!option.dtExternal.isEmpty()) {
1534 bool found = false;
1535 for(QStringList::ConstIterator sit = slist.begin(); sit != slist.end(); ++sit) {
1536 const QString &s = *sit;
1537 if(s == option.dtExternal) {
1538 found = true;
1539 break;
1540 }
1541 }
1542 if(!found)
1543 slist += option.dtExternal;
1544 }
1545
1546 // set up the server
1547 d->s5bServer->setHostList(slist);
1548}
1549
1550void PsiCon::s5b_init()
1551{
1552 if(d->s5bServer->isActive())
1553 d->s5bServer->stop();
1554
1555 if (option.dtPort) {
1556 if(!d->s5bServer->start(option.dtPort)) {
1557 QMessageBox::information(0, tr("Error"), tr("Unable to bind to port %1 for Data Transfer").arg(option.dtPort));
1558 }
1559 }
1560}
1561
1562void PsiCon::doSleep()
1563{
1564 setGlobalStatus(Status("",tr("Computer went to sleep"),0,false));
1565}
1566
1567void PsiCon::doWakeup()
1568{
1569 // TODO: Restore the status from before the log out. Make it an (hidden) option for people with a bad wireless connection.
1570 //setGlobalStatus(Status());
1571}
1572
1573
1574QPtrList<PsiToolBar> *PsiCon::toolbarList() const
1575{
1576 QPtrList<PsiToolBar> *list = new QPtrList<PsiToolBar>();
1577
1578 QPtrListIterator<PsiToolBar> it ( mainWin()->toolbars );
1579 for ( ; it.current(); ++it )
1580 list->append( it.current() );
1581
1582 return list;
1583}
1584
1585PsiToolBar *PsiCon::findToolBar(QString group, int index)
1586{
1587 PsiToolBar *toolBar = 0;
1588
1589 if ( group == "mainWin" )
1590 toolBar = mainWin()->toolbars.at(index);
1591
1592 return toolBar;
1593}
1594
1595PsiActionList *PsiCon::actionList() const
1596{
1597 return d->actionList;
1598}
1599
1600#include "psicon.moc"
Note: See TracBrowser for help on using the repository browser.