source: psi/trunk/src/mainwin.cpp@ 5

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

Imported original Psi 0.10 sources from Affinix

File size: 27.1 KB
Line 
1/*
2 * mainwin.cpp - the main window. holds contactlist and buttons.
3 * Copyright (C) 2001-2003 Justin Karneges, Michail Pishchagin
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 */
20
21#include"mainwin.h"
22
23#include<qmessagebox.h>
24#include<qiconset.h>
25#include<qtooltip.h>
26#include<qstyle.h>
27#include<qapplication.h>
28#include<qptrlist.h>
29#include<qtimer.h>
30#include<qobjectlist.h>
31#include<qpainter.h>
32#include<qsignalmapper.h>
33#include<qstatusbar.h>
34#include<qmenubar.h>
35#include"im.h"
36#include"common.h"
37#include"showtextdlg.h"
38#include"psicon.h"
39#include"psiaccount.h"
40#include"psitoolbar.h"
41#include"ui_about.h"
42#include"ui_tip.h"
43#include"fancylabel.h"
44#include"psitoolbar.h"
45#include"psipopup.h"
46
47#include"mainwin_p.h"
48
49using namespace XMPP;
50
51// deletes submenus in a popupmenu
52void qpopupmenuclear(QPopupMenu *p)
53{
54 while(p->count()) {
55 QMenuItem *item = p->findItem(p->idAt(0));
56 QPopupMenu *popup = item->popup();
57 p->removeItemAt(0);
58
59 if(popup)
60 delete popup;
61 }
62}
63
64//----------------------------------------------------------------------------
65// MainWin::Private
66//----------------------------------------------------------------------------
67
68class MainWin::Private
69{
70public:
71 Private(PsiCon *, MainWin *);
72 ~Private();
73
74 QVBoxLayout *vb_main;
75 bool onTop, asTool;
76 QPopupMenu *mainMenu, *statusMenu, *optionsMenu, *toolsMenu;
77 int sbState;
78 QString nickname;
79 MTray *tray;
80 QPopupMenu *trayMenu;
81 QString statusTip;
82
83 PopupAction *optionsButton, *statusButton;
84 IconActionGroup *statusGroup;
85 EventNotifierAction *eventNotifier;
86 PsiCon *psi;
87 MainWin *mainWin;
88
89 QSignalMapper *statusMapper;
90
91 Icon *nextAnim;
92 int nextAmount;
93
94 QMap<QAction *, int> statusActions;
95
96 int lastStatus;
97 QMenuBar *gm;
98
99 QString infoString;
100
101 void registerActions();
102 IconAction *getAction( QString name );
103};
104
105MainWin::Private::Private(PsiCon *_psi, MainWin *_mainWin)
106{
107 psi = _psi;
108 mainWin = _mainWin;
109
110 statusGroup = (IconActionGroup *)getAction("status_all");
111 eventNotifier = (EventNotifierAction *)getAction("event_notifier");
112
113 optionsButton = (PopupAction *)getAction("button_options");
114 statusButton = (PopupAction *)getAction("button_status");
115
116 statusMapper = new QSignalMapper(mainWin, "statusMapper");
117 mainWin->connect(statusMapper, SIGNAL(mapped(int)), mainWin, SLOT(activatedStatusAction(int)));
118}
119
120MainWin::Private::~Private()
121{
122}
123
124void MainWin::Private::registerActions()
125{
126 struct {
127 const char *name;
128 int id;
129 } statuslist[] = {
130 { "status_chat", STATUS_CHAT },
131 { "status_online", STATUS_ONLINE },
132 { "status_away", STATUS_AWAY },
133 { "status_xa", STATUS_XA },
134 { "status_dnd", STATUS_DND },
135 { "status_invisible", STATUS_INVISIBLE },
136 { "status_offline", STATUS_OFFLINE },
137 { "", 0 }
138 };
139
140 int i;
141 QString aName;
142 for ( i = 0; !(aName = QString(statuslist[i].name)).isEmpty(); i++ ) {
143 IconAction *action = getAction( aName );
144 connect (action, SIGNAL(activated()), statusMapper, SLOT(map()));
145
146 statusMapper->setMapping(action, statuslist[i].id);
147 statusActions[action] = statuslist[i].id;
148 }
149
150 // register all actions
151 PsiActionList::ActionsType type = PsiActionList::ActionsType( PsiActionList::Actions_MainWin | PsiActionList::Actions_Common );
152 ActionList actions = psi->actionList()->suitableActions( type );
153 QStringList names = actions.actions();
154 QStringList::Iterator it = names.begin();
155 for ( ; it != names.end(); ++it ) {
156 IconAction *action = actions.action( *it );
157 if ( action )
158 mainWin->registerAction( action );
159 }
160}
161
162IconAction *MainWin::Private::getAction( QString name )
163{
164 PsiActionList::ActionsType type = PsiActionList::ActionsType( PsiActionList::Actions_MainWin | PsiActionList::Actions_Common );
165 ActionList actions = psi->actionList()->suitableActions( type );
166 IconAction *action = actions.action( name );
167
168 if ( !action )
169 qWarning("MainWin::Private::getAction(): action %s not found!", name.latin1());
170 //else
171 // mainWin->registerAction( action );
172
173 return action;
174}
175
176//----------------------------------------------------------------------------
177// MainWin
178//----------------------------------------------------------------------------
179
180//#ifdef Q_WS_X11
181//#define TOOLW_FLAGS WStyle_Customize
182//#else
183#define TOOLW_FLAGS 0
184//#endif
185
186MainWin::MainWin(bool _onTop, bool _asTool, PsiCon *psi, const char *name)
187:AdvancedWidget<QMainWindow>(0, name, 0 | (_onTop ? WStyle_StaysOnTop: 0) | (_asTool ? WStyle_Tool | TOOLW_FLAGS : 0))
188{
189 d = new Private(psi, this);
190
191 setIcon(is->status(STATUS_OFFLINE));
192
193 d->onTop = _onTop;
194 d->asTool = _asTool;
195
196 // sbState:
197 // -1 : connect
198 // >= 0 : STATUS_*
199 d->sbState = STATUS_OFFLINE;
200 d->lastStatus = -2;
201
202 d->nextAmount = 0;
203 d->nextAnim = 0;
204 d->tray = 0;
205 d->trayMenu = 0;
206 d->statusTip = "";
207 d->infoString = "";
208 d->nickname = "";
209
210 QWidget *center = new QWidget (this, "Central widget");
211 setCentralWidget ( center );
212
213 d->vb_main = new QVBoxLayout(center, 2);
214 cvlist = new ContactView(center);
215 d->vb_main->addWidget(cvlist, 1);
216#ifdef Q_WS_MAC
217 // If the space isn't there, MacOS draws an empty vertical scrollbar :(
218 d->vb_main->addSpacing(1);
219#endif
220
221 d->statusMenu = new QPopupMenu(this);
222 d->optionsMenu = new QPopupMenu(this);
223
224 buildStatusMenu();
225 buildOptionsMenu();
226 connect(d->statusMenu, SIGNAL(aboutToShow()), SLOT(buildStatusMenu()));
227 connect(d->optionsMenu, SIGNAL(aboutToShow()), SLOT(buildOptionsMenu()));
228
229 d->optionsButton->setPopup( d->optionsMenu );
230 d->statusButton->setPopup( d->statusMenu );
231
232 X11WM_CLASS("main");
233
234 connect(d->psi, SIGNAL(accountCountChanged()), SLOT(numAccountsChanged()));
235 numAccountsChanged();
236
237 updateCaption();
238
239 d->registerActions();
240 buildToolbars();
241
242 decorateButton(STATUS_OFFLINE);
243
244 // show tip of the day
245 if ( option.showTips )
246 actTipActivated();
247
248#ifdef Q_WS_MAC
249 // Create a global menubar
250 d->gm = new QMenuBar(0);
251#else
252 // Create a menu for the current window
253 d->gm = new QMenuBar(this);
254#endif
255
256 // Mac-only menus
257#ifdef Q_WS_MAC
258 QPopupMenu *mainMenu = new QPopupMenu(this);
259 d->gm->insertItem(tr("Menu"), mainMenu);
260 mainMenu->insertItem(tr("Preferences"), this, SIGNAL(doOptions()));
261 mainMenu->insertItem(tr("Quit"), this, SLOT(try2tryCloseProgram()));
262 d->getAction("help_about")->addTo(mainMenu);
263 d->getAction("help_about_qt")->addTo(mainMenu);
264
265 d->mainMenu = new QPopupMenu(this);
266 d->gm->insertItem(tr("General"), d->mainMenu);
267 connect(d->mainMenu, SIGNAL(aboutToShow()), SLOT(buildMainMenu()));
268#else
269 d->gm->insertItem(tr("General"), d->optionsMenu);
270#endif
271
272 d->gm->insertItem(tr("Status"), d->statusMenu);
273
274 QPopupMenu *viewMenu = new QPopupMenu(this);
275 d->gm->insertItem(tr("View"), viewMenu);
276 d->getAction("show_offline")->addTo(viewMenu);
277 d->getAction("show_away")->addTo(viewMenu);
278 d->getAction("show_hidden")->addTo(viewMenu);
279 d->getAction("show_agents")->addTo(viewMenu);
280 d->getAction("show_self")->addTo(viewMenu);
281
282 // Mac-only menus
283#ifdef Q_WS_MAC
284 d->toolsMenu = new QPopupMenu(this);
285 d->gm->insertItem(tr("Tools"), d->toolsMenu);
286 connect(d->toolsMenu, SIGNAL(aboutToShow()), SLOT(buildToolsMenu()));
287
288 QPopupMenu *helpMenu = new QPopupMenu(this);
289 d->gm->insertItem(tr("Help"), helpMenu);
290 d->getAction("help_readme")->addTo (helpMenu);
291 d->getAction("help_tip")->addTo (helpMenu);
292 helpMenu->insertSeparator();
293 d->getAction("help_online_help")->addTo (helpMenu);
294 d->getAction("help_online_wiki")->addTo (helpMenu);
295 d->getAction("help_online_home")->addTo (helpMenu);
296 d->getAction("help_report_bug")->addTo (helpMenu);
297
298 d->gm->show();
299#else
300 if (option.hideMenubar)
301 d->gm->hide();
302 else
303 d->gm->show();
304#endif
305
306#if QT_VERSION >= 0x030300
307 setWindowOpacity(double(option.rosterOpacity)/100);
308#endif
309
310 connect(qApp, SIGNAL(dockActivated()), SLOT(dockActivated()));
311}
312
313
314MainWin::~MainWin()
315{
316 PsiPopup::deleteAll();
317
318 if (d->gm)
319 delete d->gm;
320
321 if(d->tray) {
322 delete d->tray;
323 d->tray = 0;
324 delete d->trayMenu;
325 d->trayMenu = 0;
326 }
327
328 //saveToolbarsPositions();
329 // need to find some workaround to case, when you're logging off. in that case
330 // toobars are all disabled, and when you start psi again you need to enable
331 // your toolbars
332
333 delete d;
334}
335
336void MainWin::registerAction( IconAction *action )
337{
338 char activated[] = SIGNAL( activated() );
339 char toggled[] = SIGNAL( toggled(bool) );
340 char setOn[] = SLOT( setOn(bool) );
341
342 struct {
343 const char *name;
344 const char *signal;
345 QObject *receiver;
346 const char *slot;
347 } actionlist[] = {
348 { "show_offline", toggled, cvlist, SLOT( setShowOffline(bool) ) },
349 { "show_away", toggled, cvlist, SLOT( setShowAway(bool) ) },
350 { "show_hidden", toggled, cvlist, SLOT( setShowHidden(bool) ) },
351 { "show_agents", toggled, cvlist, SLOT( setShowAgents(bool) ) },
352 { "show_self", toggled, cvlist, SLOT( setShowSelf(bool) ) },
353
354 { "button_options", activated, this, SIGNAL( doOptions() ) },
355
356 { "menu_disco", SIGNAL( activated(PsiAccount *, int) ), this, SLOT( activatedAccOption(PsiAccount*, int) ) },
357 { "menu_add_contact", SIGNAL( activated(PsiAccount *, int) ), this, SLOT( activatedAccOption(PsiAccount*, int) ) },
358 { "menu_xml_console", SIGNAL( activated(PsiAccount *, int) ), this, SLOT( activatedAccOption(PsiAccount*, int) ) },
359
360 { "menu_new_message", activated, this, SIGNAL( blankMessage() ) },
361 { "menu_join_groupchat", activated, this, SIGNAL( doGroupChat() ) },
362 { "menu_account_setup", activated, this, SIGNAL( doManageAccounts() ) },
363 { "menu_options", activated, this, SIGNAL( doOptions() ) },
364 { "menu_file_transfer", activated, this, SIGNAL( doFileTransDlg() ) },
365 { "menu_toolbars", activated, this, SIGNAL( doToolbars() ) },
366 { "menu_change_profile", activated, this, SIGNAL( changeProfile() ) },
367 { "menu_quit", activated, this, SLOT( try2tryCloseProgram() ) },
368 { "menu_play_sounds", toggled, this, SLOT( actPlaySoundsActivated(bool) ) },
369
370 { "event_notifier", SIGNAL( clicked(int) ), this, SLOT( statusClicked(int) ) },
371 { "event_notifier", activated, this, SLOT( doRecvNextEvent() ) },
372
373 { "help_readme", activated, this, SLOT( actReadmeActivated() ) },
374 { "help_tip", activated, this, SLOT( actTipActivated() ) },
375 { "help_online_help", activated, this, SLOT( actOnlineHelpActivated() ) },
376 { "help_online_wiki", activated, this, SLOT( actOnlineWikiActivated() ) },
377 { "help_online_home", activated, this, SLOT( actOnlineHomeActivated() ) },
378 { "help_report_bug", activated, this, SLOT( actBugReportActivated() ) },
379 { "help_about", activated, this, SLOT( actAboutActivated() ) },
380 { "help_about_qt", activated, this, SLOT( actAboutQtActivated() ) },
381
382 { "", 0, 0, 0 }
383 };
384
385 int i;
386 QString aName;
387 for ( i = 0; !(aName = QString(actionlist[i].name)).isEmpty(); i++ ) {
388 if ( aName == action->name() ) {
389 disconnect( action, actionlist[i].signal, actionlist[i].receiver, actionlist[i].slot ); // for safety
390 connect( action, actionlist[i].signal, actionlist[i].receiver, actionlist[i].slot );
391
392 // special cases
393 if ( aName == "menu_play_sounds" )
394 action->setOn( useSound );
395 //else if ( aName == "foobar" )
396 // ;
397 }
398 }
399
400 struct {
401 const char *name;
402 QObject *sender;
403 const char *signal;
404 const char *slot;
405 } reverseactionlist[] = {
406 { "show_away", cvlist, SIGNAL( showAway(bool) ), setOn },
407 { "show_hidden", cvlist, SIGNAL( showHidden(bool) ), setOn },
408 { "show_offline", cvlist, SIGNAL( showOffline(bool) ), setOn },
409 { "show_self", cvlist, SIGNAL( showSelf(bool) ), setOn },
410 { "show_agents", cvlist, SIGNAL( showAgents(bool) ), setOn },
411 { "", 0, 0, 0 }
412 };
413
414 for ( i = 0; !(aName = QString(reverseactionlist[i].name)).isEmpty(); i++ ) {
415 if ( aName == action->name() ) {
416 disconnect( reverseactionlist[i].sender, reverseactionlist[i].signal, action, reverseactionlist[i].slot ); // for safety
417 connect( reverseactionlist[i].sender, reverseactionlist[i].signal, action, reverseactionlist[i].slot );
418
419 action->setOn( true );
420 }
421 }
422}
423
424PsiCon *MainWin::psiCon() const
425{
426 return d->psi;
427}
428
429void MainWin::setWindowOpts(bool _onTop, bool _asTool)
430{
431 if(_onTop == d->onTop && _asTool == d->asTool)
432 return;
433
434 d->onTop = _onTop;
435 d->asTool = _asTool;
436
437 WFlags flags = 0;
438 if(d->onTop)
439 flags |= WStyle_StaysOnTop;
440 if(d->asTool)
441 flags |= WStyle_Tool | TOOLW_FLAGS;
442
443 QPoint p = pos();
444 reparent(parentWidget(), flags, p, FALSE);
445 move(p);
446 show();
447}
448
449void MainWin::setUseDock(bool use)
450{
451 if(use == false || (d->tray && option.isWMDock != d->tray->isWMDock())) {
452 if(d->tray) {
453 delete d->tray;
454 d->tray = 0;
455 delete d->trayMenu;
456 d->trayMenu = 0;
457 }
458
459 if (use == false)
460 return;
461 }
462
463 if(d->tray)
464 return;
465
466 d->trayMenu = new QPopupMenu;
467 connect(d->trayMenu, SIGNAL(aboutToShow()), SLOT(buildTrayMenu()));
468
469 d->tray = new MTray("Psi", d->trayMenu);
470 d->tray->setIcon( is->statusPtr( STATUS_OFFLINE ));
471 d->tray->setToolTip(PROG_NAME);
472 connect(d->tray, SIGNAL(clicked(const QPoint &, int)), SLOT(trayClicked(const QPoint &, int)));
473 connect(d->tray, SIGNAL(doubleClicked(const QPoint &)), SLOT(trayDoubleClicked()));
474 connect(d->tray, SIGNAL(closed()), SLOT(dockActivated()));
475 connect(qApp, SIGNAL(trayOwnerDied()), SLOT(dockActivated()));
476
477 updateReadNext(d->nextAnim, d->nextAmount);
478
479 d->tray->show();
480}
481
482void MainWin::setInfo(const QString &str)
483{
484 d->infoString = str;
485
486 if(d->nextAmount == 0)
487 d->eventNotifier->setText(d->infoString);
488}
489
490void MainWin::buildStatusMenu()
491{
492 //statusMenu->clear();
493 qpopupmenuclear(d->statusMenu);
494
495 d->statusGroup->addTo(d->statusMenu);
496}
497
498void MainWin::activatedStatusAction(int id)
499{
500 QObjectList *l = d->statusGroup->queryList( "IconAction" );
501 QObjectListIt it( *l );
502 QObject *obj;
503 for ( ; (obj = it.current()); ++it) {
504 IconAction *action = (IconAction *)obj;
505 action->setOn ( d->statusActions[action] == id );
506 }
507 delete l;
508
509 statusChanged(id);
510}
511
512void MainWin::buildToolbars()
513{
514 bool dockBottom = false;
515
516 while ( option.toolbars.count() < toolbars.count() && toolbars.count() ) {
517 PsiToolBar *tb = toolbars.last();
518 toolbars.removeLast();
519 delete tb;
520 }
521
522 uint i;
523 for (i = 0; i < option.toolbars["mainWin"].count(); i++) {
524 PsiToolBar *tb = 0;
525 if ( i < toolbars.count() )
526 tb = toolbars.at(i);
527
528 Options::ToolbarPrefs &tbPref = option.toolbars["mainWin"][i];
529 if ( tb && !tbPref.dirty )
530 continue;
531
532 if ( tb )
533 delete tb;
534
535 tb = new PsiToolBar (tbPref.name, this, this);
536 moveDockWindow ( tb, tbPref.dock, tbPref.nl, tbPref.index, tbPref. extraOffset );
537
538 tb->setGroup( "mainWin", i );
539 tb->setPsiCon( d->psi );
540 tb->setType( PsiActionList::Actions_MainWin );
541 //connect( tb, SIGNAL( registerAction( IconAction * ) ), SLOT( registerAction( IconAction * ) ) );
542 tb->initialize( tbPref, false );
543
544 // MacOS stuff
545 dockBottom = dockBottom || (tbPref.dock == Qt::DockBottom && tbPref.on);
546
547 if ( i < toolbars.count() )
548 toolbars.remove(i);
549 toolbars.insert(i, tb);
550 }
551
552#ifdef Q_WS_MAC
553 if (dockBottom) {
554 statusBar()->show();
555 }
556 else {
557 statusBar()->hide();
558 }
559#endif
560}
561
562void MainWin::saveToolbarsPositions()
563{
564 for (uint i = 0; i < toolbars.count(); i++) {
565 Options::ToolbarPrefs &tbPref = option.toolbars["mainWin"][i];
566 getLocation ( toolbars.at(i), tbPref.dock, tbPref.index, tbPref.nl, tbPref.extraOffset );
567 tbPref.on = toolbars.at(i)->isVisible();
568 }
569}
570
571bool MainWin::showDockMenu(const QPoint &)
572{
573 return false;
574}
575
576void MainWin::buildOptionsMenu()
577{
578 d->optionsMenu->clear();
579
580 // help menu
581 QPopupMenu *helpMenu = new QPopupMenu(d->optionsMenu);
582
583 QStringList actionNames;
584 actionNames << "help_readme";
585 actionNames << "help_tip";
586 actionNames << "separator";
587 actionNames << "help_online_help";
588 actionNames << "help_online_wiki";
589 actionNames << "help_online_home";
590 actionNames << "help_report_bug";
591 actionNames << "separator";
592 actionNames << "help_about";
593 actionNames << "help_about_qt";
594
595 QStringList::Iterator it;
596 IconAction *action;
597 for ( it = actionNames.begin(); it != actionNames.end(); ++it )
598 if ( (action = d->getAction(*it)) )
599 action->addTo( helpMenu );
600
601 buildGeneralMenu( d->optionsMenu );
602
603 d->optionsMenu->insertSeparator();
604 d->optionsMenu->insertItem(IconsetFactory::icon("psi/help"), tr("&Help"), helpMenu);
605 d->getAction("menu_quit")->addTo( d->optionsMenu );
606
607}
608
609void MainWin::buildMainMenu()
610{
611 d->mainMenu->clear();
612
613 QStringList actionNames;
614
615 // options menu
616 if(!option.lockdown.roster)
617 actionNames << "menu_add_contact";
618 actionNames << "menu_new_message";
619 if(!option.lockdown.services)
620 actionNames << "menu_disco";
621 actionNames << "menu_join_groupchat";
622 actionNames << "";
623 if(!option.lockdown.accounts)
624 actionNames << "menu_account_setup";
625 if(!option.lockdown.profiles)
626 actionNames << "menu_change_profile";
627 actionNames << "menu_toolbars";
628 actionNames << "menu_play_sounds";
629
630 QStringList::Iterator it;
631 IconAction *action;
632 for ( it = actionNames.begin(); it != actionNames.end(); ++it ) {
633 if ((*it).isEmpty())
634 d->mainMenu->insertSeparator();
635 else if ( (action = d->getAction(*it)) )
636 action->addTo( d->mainMenu );
637 }
638}
639
640void MainWin::buildToolsMenu()
641{
642 IconAction* action;
643
644 d->toolsMenu->clear();
645 if ( (action = d->getAction("menu_file_transfer")) )
646 action->addTo(d->toolsMenu);
647 d->toolsMenu->insertSeparator();
648 if ( (action = d->getAction("menu_xml_console")) )
649 action->addTo(d->toolsMenu);
650}
651
652void MainWin::buildGeneralMenu(QPopupMenu *menu)
653{
654 menu->clear();
655
656 QStringList actionNames;
657
658 // options menu
659 if(!option.lockdown.roster)
660 actionNames << "menu_add_contact";
661 actionNames << "menu_new_message";
662 if(!option.lockdown.services)
663 actionNames << "menu_disco";
664 actionNames << "menu_join_groupchat";
665 if(!option.lockdown.accounts)
666 actionNames << "menu_account_setup";
667 if(!option.lockdown.options)
668 actionNames << "menu_options";
669 actionNames << "menu_file_transfer"; // TODO: probably we want to lock down filetransfer, right?
670 if(!option.lockdown.profiles)
671 actionNames << "menu_change_profile";
672 actionNames << "menu_toolbars";
673 actionNames << "menu_play_sounds";
674
675 QStringList::Iterator it;
676 IconAction *action;
677 for ( it = actionNames.begin(); it != actionNames.end(); ++it )
678 if ( (action = d->getAction(*it)) )
679 action->addTo( menu );
680}
681
682// WTF??
683void MainWin::testme()
684{
685 d->optionsMenu->setItemEnabled(10, false);
686}
687
688void MainWin::actReadmeActivated ()
689{
690#ifdef Q_WS_WIN
691 ShowTextDlg *w = new ShowTextDlg(g.pathBase + "/readme.txt");
692#else
693 ShowTextDlg *w = new ShowTextDlg(g.pathBase + "/README");
694#endif
695 w->setCaption(CAP(tr("ReadMe")));
696 w->show();
697}
698
699void MainWin::actOnlineHelpActivated ()
700{
701 openURL("http://psi-im.org/wiki/User_Guide");
702}
703
704void MainWin::actOnlineWikiActivated ()
705{
706 openURL("http://psi-im.org/wiki");
707}
708
709void MainWin::actOnlineHomeActivated ()
710{
711 openURL("http://psi-im.org");
712}
713
714void MainWin::actBugReportActivated ()
715{
716 openURL("http://psi-im.org/forum/forum/2");
717}
718
719void MainWin::actAboutActivated ()
720{
721 AboutDlg *about = new AboutDlg (this, "AboutDlg", false, WDestructiveClose);
722 about->show();
723}
724
725void MainWin::actTipActivated ()
726{
727 TipUI *tip = new TipUI (this, "TipDlg", false, WDestructiveClose);
728 tip->show();
729}
730
731void MainWin::actAboutQtActivated ()
732{
733 QMessageBox::aboutQt(this);
734}
735
736void MainWin::actPlaySoundsActivated (bool state)
737{
738 useSound = state;
739}
740
741void MainWin::activatedAccOption(PsiAccount *pa, int x)
742{
743 if(x == 0)
744 pa->openAddUserDlg();
745 else if(x == 2)
746 pa->showXmlConsole();
747 else if(x == 3)
748 pa->doDisco();
749}
750
751void MainWin::buildTrayMenu()
752{
753 if(!d->trayMenu)
754 return;
755 d->trayMenu->clear();
756
757 if(d->nextAmount > 0) {
758 d->trayMenu->insertItem(tr("Receive next event"), this, SLOT(doRecvNextEvent()));
759 d->trayMenu->insertSeparator();
760 }
761
762 if(isHidden())
763 d->trayMenu->insertItem(tr("Un&hide"), this, SLOT(trayShow()));
764 else
765 d->trayMenu->insertItem(tr("&Hide"), this, SLOT(trayHide()));
766 d->optionsButton->addTo(d->trayMenu);
767 d->statusButton->addTo(d->trayMenu);
768 d->trayMenu->insertSeparator();
769 // TODO!
770 d->getAction("menu_quit")->addTo(d->trayMenu);
771}
772
773void MainWin::setTrayToolTip(int status)
774{
775 if (!d->tray)
776 return;
777 d->tray->setToolTip(QString("Psi - " + status2txt(status)));
778}
779
780void MainWin::decorateButton(int status)
781{
782 // update the 'change status' buttons
783 QObjectList *l = d->statusGroup->queryList( "IconAction" );
784 QObjectListIt it( *l );
785 QObject *obj;
786 for ( ; (obj = it.current()); ++it) {
787 IconAction *action = (IconAction *)obj;
788 action->setOn ( d->statusActions[action] == status );
789 }
790 delete l;
791
792 if(d->lastStatus == status)
793 return;
794 d->lastStatus = status;
795
796 QIconSet icon;
797 icon.setPixmap(is->status(status), QIconSet::Small);
798
799 if(status == -1) {
800 d->statusButton->setText(tr("Connecting"));
801 if (option.alertStyle != 0)
802 d->statusButton->setAlert(IconsetFactory::iconPtr("psi/connect"));
803 else
804 d->statusButton->setIcon(is->statusPtr(STATUS_OFFLINE));
805
806 setIcon(is->status(STATUS_OFFLINE));
807 }
808 else {
809 d->statusButton->setText(status2txt(status));
810 d->statusButton->setIcon(is->statusPtr(status));
811
812 setIcon(is->status(status));
813 }
814
815 updateTray();
816}
817
818bool MainWin::askQuit()
819{
820 return TRUE;
821}
822
823void MainWin::try2tryCloseProgram()
824{
825 QTimer::singleShot(0, this, SLOT(tryCloseProgram()));
826}
827
828void MainWin::tryCloseProgram()
829{
830 if(askQuit())
831 closeProgram();
832}
833
834void MainWin::closeEvent(QCloseEvent *e)
835{
836#ifdef Q_WS_MAC
837 trayHide();
838 e->accept();
839#else
840 if(d->tray) {
841 trayHide();
842 e->accept();
843 return;
844 }
845
846 if(!askQuit())
847 return;
848
849 closeProgram();
850 e->accept();
851#endif
852}
853
854void MainWin::keyPressEvent(QKeyEvent *e)
855{
856#ifdef Q_WS_MAC
857 bool allowed = true;
858#else
859 bool allowed = d->tray ? true: false;
860#endif
861
862 bool closekey = false;
863 if(e->key() == Key_Escape)
864 closekey = true;
865#ifdef Q_WS_MAC
866 else if(e->key() == Key_W && e->state() & ControlButton)
867 closekey = true;
868#endif
869
870 if(allowed && closekey) {
871 close();
872 e->accept();
873 return;
874 }
875
876 QWidget::keyPressEvent(e);
877}
878
879void MainWin::updateCaption()
880{
881 QString str = "";
882
883 if(d->nextAmount > 0)
884 str += "* ";
885
886 if(d->nickname.isEmpty())
887 str += PROG_NAME;
888 else
889 str += d->nickname;
890
891 if(str == caption())
892 return;
893
894 setCaption(str);
895}
896
897void MainWin::optionsUpdate()
898{
899 int status = d->lastStatus;
900 d->lastStatus = -2;
901 decorateButton(status);
902
903 if (option.hideMenubar)
904 d->gm->hide();
905 else
906 d->gm->show();
907
908#if QT_VERSION >= 0x030300
909 setWindowOpacity(double(option.rosterOpacity)/100);
910#endif
911
912 updateTray();
913}
914
915void MainWin::toggleVisible()
916{
917 if(!isHidden())
918 trayHide();
919 else
920 trayShow();
921}
922
923void MainWin::setTrayToolTip(const Status &status)
924{
925 if (!d->tray)
926 return;
927 QString s = "Psi";
928
929 QString show = status.show();
930 if(!show.isEmpty()) {
931 show[0] = show[0].upper();
932 s += " - "+show;
933 }
934
935 QString text = status.status();
936 if(!text.isEmpty())
937 s += ": "+text;
938
939 d->tray->setToolTip(s);
940}
941
942void MainWin::trayClicked(const QPoint &, int button)
943{
944 if(option.dockDCstyle)
945 return;
946
947 if(button == MidButton) {
948 doRecvNextEvent();
949 return;
950 }
951
952 if(!isHidden())
953 trayHide();
954 else
955 trayShow();
956}
957
958void MainWin::trayDoubleClicked()
959{
960 if(!option.dockDCstyle)
961 return;
962
963 if(d->nextAmount > 0) {
964 doRecvNextEvent();
965 return;
966 }
967
968
969 if(!isHidden())
970 trayHide();
971 else
972 trayShow();
973}
974
975void MainWin::trayShow()
976{
977 bringToFront(this);
978}
979
980void MainWin::trayHide()
981{
982 emit geomChanged(x(), y(), width(), height());
983 hide();
984}
985
986void MainWin::updateReadNext(Icon *anim, int amount)
987{
988 d->nextAnim = anim;
989 if(anim == 0)
990 d->nextAmount = 0;
991 else
992 d->nextAmount = amount;
993
994 if(d->nextAmount <= 0) {
995 d->eventNotifier->hide();
996 d->eventNotifier->setText("");
997 }
998 else {
999 d->eventNotifier->setText(QString("<b>") + numEventsString(d->nextAmount) + "</b>");
1000 d->eventNotifier->show();
1001 // make sure it shows
1002 //qApp->processEvents();
1003 }
1004
1005 updateTray();
1006 updateCaption();
1007}
1008
1009QString MainWin::numEventsString(int x) const
1010{
1011 QString s;
1012 if(x <= 0)
1013 s = "";
1014 else if(x == 1)
1015 s = tr("1 event received");
1016 else
1017 s = tr("%1 events received").arg(x);
1018
1019 return s;
1020}
1021
1022void MainWin::updateTray()
1023{
1024 if(!d->tray)
1025 return;
1026
1027 if ( d->nextAmount > 0 )
1028 d->tray->setAlert(d->nextAnim);
1029 else if ( d->lastStatus == -1 )
1030 d->tray->setAlert(IconsetFactory::iconPtr("psi/connect"));
1031 else
1032 d->tray->setIcon(is->statusPtr(d->lastStatus));
1033}
1034
1035void MainWin::doRecvNextEvent()
1036{
1037 recvNextEvent();
1038}
1039
1040void MainWin::statusClicked(int x)
1041{
1042 if(x == MidButton)
1043 recvNextEvent();
1044}
1045
1046void MainWin::numAccountsChanged()
1047{
1048 bool enabled = d->psi->accountList(TRUE).isEmpty() ? false : true;
1049 d->statusButton->setEnabled (enabled);
1050}
1051
1052void MainWin::dockActivated()
1053{
1054 if(isHidden())
1055 show();
1056}
1057
1058
1059#ifdef Q_WS_MAC
1060void MainWin::setIcon(const QPixmap&)
1061{
1062}
1063#else
1064void MainWin::setIcon(const QPixmap& p)
1065{
1066 QMainWindow::setIcon(p);
1067}
1068#endif
1069
1070#if defined(Q_WS_WIN)
1071#include<windows.h>
1072void MainWin::showNoFocus()
1073{
1074 clearWState( WState_ForceHide );
1075
1076 if ( testWState(WState_Visible) ) {
1077 SetWindowPos(winId(),HWND_TOPMOST,0,0,0,0, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE);
1078 if(!d->onTop)
1079 SetWindowPos(winId(),HWND_NOTOPMOST,0,0,0,0, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE);
1080 return; // nothing to do
1081 }
1082
1083 if ( isTopLevel() && !testWState( WState_Resized ) ) {
1084 // do this before sending the posted resize events. Otherwise
1085 // the layout would catch the resize event and may expand the
1086 // minimum size.
1087 QSize s = sizeHint();
1088 QSizePolicy::ExpandData exp;
1089#ifndef QT_NO_LAYOUT
1090 if ( layout() ) {
1091 if ( layout()->hasHeightForWidth() )
1092 s.setHeight( layout()->totalHeightForWidth( s.width() ) );
1093 exp = layout()->expanding();
1094 } else
1095#endif
1096 {
1097 if ( sizePolicy().hasHeightForWidth() )
1098 s.setHeight( heightForWidth( s.width() ) );
1099 exp = sizePolicy().expanding();
1100 }
1101 if ( exp & QSizePolicy::Horizontally )
1102 s.setWidth( QMAX( s.width(), 200 ) );
1103 if ( exp & QSizePolicy::Vertically )
1104 s.setHeight( QMAX( s.height(), 150 ) );
1105 QRect screen = QApplication::desktop()->screenGeometry( QApplication::desktop()->screenNumber( pos() ) );
1106 s.setWidth( QMIN( s.width(), screen.width()*2/3 ) );
1107 s.setHeight( QMIN( s.height(), screen.height()*2/3 ) );
1108 if ( !s.isEmpty() )
1109 resize( s );
1110 }
1111
1112 QApplication::sendPostedEvents( this, QEvent::Move );
1113 QApplication::sendPostedEvents( this, QEvent::Resize );
1114
1115 setWState( WState_Visible );
1116
1117 if ( testWFlags(WStyle_Tool) || isPopup() ) {
1118 raise();
1119 } else if ( testWFlags(WType_TopLevel) ) {
1120 while ( QApplication::activePopupWidget() )
1121 QApplication::activePopupWidget()->close();
1122 }
1123
1124 if ( !testWState(WState_Polished) )
1125 polish();
1126
1127 if ( children() ) {
1128 QObjectListIt it(*children());
1129 register QObject *object;
1130 QWidget *widget;
1131 while ( it ) { // show all widget children
1132 object = it.current(); // (except popups and other toplevels)
1133 ++it;
1134 if ( object->isWidgetType() ) {
1135 widget = (QWidget*)object;
1136 if ( !widget->isHidden() && !widget->isTopLevel() )
1137 widget->show();
1138 }
1139 }
1140 }
1141
1142#if defined(QT_ACCESSIBILITY_SUPPORT)
1143 QAccessible::updateAccessibility( this, 0, QAccessible::ObjectShow );
1144#endif
1145
1146 SetWindowPos(winId(),HWND_TOP,0,0,0,0, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW);
1147 UpdateWindow(winId());
1148}
1149
1150#else
1151
1152void MainWin::showNoFocus()
1153{
1154 bringToFront(this);
1155}
1156
1157#endif
Note: See TracBrowser for help on using the repository browser.