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

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

UI: Misc changes:

  • Added OS/2-related definitions.
  • On all platforms but Mac, the main (roster) window will be minimized (instead of closing) when Esc is pressed, but the doclet window is disabled.
File size: 27.5 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#ifdef Q_WS_PM
452 /// @todo (dmik) disable the docklet until the xCenter plugin is implemented
453 // (this ifdef is necessary in order to share the same config between
454 // different platforms where the Use Docklet option may be set to true.
455 return;
456#else
457 if(use == false || (d->tray && option.isWMDock != d->tray->isWMDock())) {
458 if(d->tray) {
459 delete d->tray;
460 d->tray = 0;
461 delete d->trayMenu;
462 d->trayMenu = 0;
463 }
464
465 if (use == false)
466 return;
467 }
468
469 if(d->tray)
470 return;
471
472 d->trayMenu = new QPopupMenu;
473 connect(d->trayMenu, SIGNAL(aboutToShow()), SLOT(buildTrayMenu()));
474
475 d->tray = new MTray("Psi", d->trayMenu);
476 d->tray->setIcon( is->statusPtr( STATUS_OFFLINE ));
477 d->tray->setToolTip(PROG_NAME);
478 connect(d->tray, SIGNAL(clicked(const QPoint &, int)), SLOT(trayClicked(const QPoint &, int)));
479 connect(d->tray, SIGNAL(doubleClicked(const QPoint &)), SLOT(trayDoubleClicked()));
480 connect(d->tray, SIGNAL(closed()), SLOT(dockActivated()));
481 connect(qApp, SIGNAL(trayOwnerDied()), SLOT(dockActivated()));
482
483 updateReadNext(d->nextAnim, d->nextAmount);
484
485 d->tray->show();
486#endif
487}
488
489void MainWin::setInfo(const QString &str)
490{
491 d->infoString = str;
492
493 if(d->nextAmount == 0)
494 d->eventNotifier->setText(d->infoString);
495}
496
497void MainWin::buildStatusMenu()
498{
499 //statusMenu->clear();
500 qpopupmenuclear(d->statusMenu);
501
502 d->statusGroup->addTo(d->statusMenu);
503}
504
505void MainWin::activatedStatusAction(int id)
506{
507 QObjectList *l = d->statusGroup->queryList( "IconAction" );
508 QObjectListIt it( *l );
509 QObject *obj;
510 for ( ; (obj = it.current()); ++it) {
511 IconAction *action = (IconAction *)obj;
512 action->setOn ( d->statusActions[action] == id );
513 }
514 delete l;
515
516 statusChanged(id);
517}
518
519void MainWin::buildToolbars()
520{
521 bool dockBottom = false;
522
523 while ( option.toolbars.count() < toolbars.count() && toolbars.count() ) {
524 PsiToolBar *tb = toolbars.last();
525 toolbars.removeLast();
526 delete tb;
527 }
528
529 uint i;
530 for (i = 0; i < option.toolbars["mainWin"].count(); i++) {
531 PsiToolBar *tb = 0;
532 if ( i < toolbars.count() )
533 tb = toolbars.at(i);
534
535 Options::ToolbarPrefs &tbPref = option.toolbars["mainWin"][i];
536 if ( tb && !tbPref.dirty )
537 continue;
538
539 if ( tb )
540 delete tb;
541
542 tb = new PsiToolBar (tbPref.name, this, this);
543 moveDockWindow ( tb, tbPref.dock, tbPref.nl, tbPref.index, tbPref. extraOffset );
544
545 tb->setGroup( "mainWin", i );
546 tb->setPsiCon( d->psi );
547 tb->setType( PsiActionList::Actions_MainWin );
548 //connect( tb, SIGNAL( registerAction( IconAction * ) ), SLOT( registerAction( IconAction * ) ) );
549 tb->initialize( tbPref, false );
550
551 // MacOS stuff
552 dockBottom = dockBottom || (tbPref.dock == Qt::DockBottom && tbPref.on);
553
554 if ( i < toolbars.count() )
555 toolbars.remove(i);
556 toolbars.insert(i, tb);
557 }
558
559#ifdef Q_WS_MAC
560 if (dockBottom) {
561 statusBar()->show();
562 }
563 else {
564 statusBar()->hide();
565 }
566#endif
567}
568
569void MainWin::saveToolbarsPositions()
570{
571 for (uint i = 0; i < toolbars.count(); i++) {
572 Options::ToolbarPrefs &tbPref = option.toolbars["mainWin"][i];
573 getLocation ( toolbars.at(i), tbPref.dock, tbPref.index, tbPref.nl, tbPref.extraOffset );
574 tbPref.on = toolbars.at(i)->isVisible();
575 }
576}
577
578bool MainWin::showDockMenu(const QPoint &)
579{
580 return false;
581}
582
583void MainWin::buildOptionsMenu()
584{
585 d->optionsMenu->clear();
586
587 // help menu
588 QPopupMenu *helpMenu = new QPopupMenu(d->optionsMenu);
589
590 QStringList actionNames;
591 actionNames << "help_readme";
592 actionNames << "help_tip";
593 actionNames << "separator";
594 actionNames << "help_online_help";
595 actionNames << "help_online_wiki";
596 actionNames << "help_online_home";
597 actionNames << "help_report_bug";
598 actionNames << "separator";
599 actionNames << "help_about";
600 actionNames << "help_about_qt";
601
602 QStringList::Iterator it;
603 IconAction *action;
604 for ( it = actionNames.begin(); it != actionNames.end(); ++it )
605 if ( (action = d->getAction(*it)) )
606 action->addTo( helpMenu );
607
608 buildGeneralMenu( d->optionsMenu );
609
610 d->optionsMenu->insertSeparator();
611 d->optionsMenu->insertItem(IconsetFactory::icon("psi/help"), tr("&Help"), helpMenu);
612 d->getAction("menu_quit")->addTo( d->optionsMenu );
613
614}
615
616void MainWin::buildMainMenu()
617{
618 d->mainMenu->clear();
619
620 QStringList actionNames;
621
622 // options menu
623 if(!option.lockdown.roster)
624 actionNames << "menu_add_contact";
625 actionNames << "menu_new_message";
626 if(!option.lockdown.services)
627 actionNames << "menu_disco";
628 actionNames << "menu_join_groupchat";
629 actionNames << "";
630 if(!option.lockdown.accounts)
631 actionNames << "menu_account_setup";
632 if(!option.lockdown.profiles)
633 actionNames << "menu_change_profile";
634 actionNames << "menu_toolbars";
635 actionNames << "menu_play_sounds";
636
637 QStringList::Iterator it;
638 IconAction *action;
639 for ( it = actionNames.begin(); it != actionNames.end(); ++it ) {
640 if ((*it).isEmpty())
641 d->mainMenu->insertSeparator();
642 else if ( (action = d->getAction(*it)) )
643 action->addTo( d->mainMenu );
644 }
645}
646
647void MainWin::buildToolsMenu()
648{
649 IconAction* action;
650
651 d->toolsMenu->clear();
652 if ( (action = d->getAction("menu_file_transfer")) )
653 action->addTo(d->toolsMenu);
654 d->toolsMenu->insertSeparator();
655 if ( (action = d->getAction("menu_xml_console")) )
656 action->addTo(d->toolsMenu);
657}
658
659void MainWin::buildGeneralMenu(QPopupMenu *menu)
660{
661 menu->clear();
662
663 QStringList actionNames;
664
665 // options menu
666 if(!option.lockdown.roster)
667 actionNames << "menu_add_contact";
668 actionNames << "menu_new_message";
669 if(!option.lockdown.services)
670 actionNames << "menu_disco";
671 actionNames << "menu_join_groupchat";
672 if(!option.lockdown.accounts)
673 actionNames << "menu_account_setup";
674 if(!option.lockdown.options)
675 actionNames << "menu_options";
676 actionNames << "menu_file_transfer"; // TODO: probably we want to lock down filetransfer, right?
677 if(!option.lockdown.profiles)
678 actionNames << "menu_change_profile";
679 actionNames << "menu_toolbars";
680 actionNames << "menu_play_sounds";
681
682 QStringList::Iterator it;
683 IconAction *action;
684 for ( it = actionNames.begin(); it != actionNames.end(); ++it )
685 if ( (action = d->getAction(*it)) )
686 action->addTo( menu );
687}
688
689// WTF??
690void MainWin::testme()
691{
692 d->optionsMenu->setItemEnabled(10, false);
693}
694
695void MainWin::actReadmeActivated ()
696{
697#if defined(Q_WS_WIN) || defined(Q_OS_OS2)
698 ShowTextDlg *w = new ShowTextDlg(g.pathBase + "/readme.txt");
699#else
700 ShowTextDlg *w = new ShowTextDlg(g.pathBase + "/README");
701#endif
702 w->setCaption(CAP(tr("ReadMe")));
703 w->show();
704}
705
706void MainWin::actOnlineHelpActivated ()
707{
708 openURL("http://psi-im.org/wiki/User_Guide");
709}
710
711void MainWin::actOnlineWikiActivated ()
712{
713 openURL("http://psi-im.org/wiki");
714}
715
716void MainWin::actOnlineHomeActivated ()
717{
718 openURL("http://psi-im.org");
719}
720
721void MainWin::actBugReportActivated ()
722{
723 openURL("http://psi-im.org/forum/forum/2");
724}
725
726void MainWin::actAboutActivated ()
727{
728 AboutDlg *about = new AboutDlg (this, "AboutDlg", false, WDestructiveClose);
729 about->show();
730}
731
732void MainWin::actTipActivated ()
733{
734 TipUI *tip = new TipUI (this, "TipDlg", false, WDestructiveClose);
735 tip->show();
736}
737
738void MainWin::actAboutQtActivated ()
739{
740 QMessageBox::aboutQt(this);
741}
742
743void MainWin::actPlaySoundsActivated (bool state)
744{
745 useSound = state;
746}
747
748void MainWin::activatedAccOption(PsiAccount *pa, int x)
749{
750 if(x == 0)
751 pa->openAddUserDlg();
752 else if(x == 2)
753 pa->showXmlConsole();
754 else if(x == 3)
755 pa->doDisco();
756}
757
758void MainWin::buildTrayMenu()
759{
760 if(!d->trayMenu)
761 return;
762 d->trayMenu->clear();
763
764 if(d->nextAmount > 0) {
765 d->trayMenu->insertItem(tr("Receive next event"), this, SLOT(doRecvNextEvent()));
766 d->trayMenu->insertSeparator();
767 }
768
769 if(isHidden())
770 d->trayMenu->insertItem(tr("Un&hide"), this, SLOT(trayShow()));
771 else
772 d->trayMenu->insertItem(tr("&Hide"), this, SLOT(trayHide()));
773 d->optionsButton->addTo(d->trayMenu);
774 d->statusButton->addTo(d->trayMenu);
775 d->trayMenu->insertSeparator();
776 // TODO!
777 d->getAction("menu_quit")->addTo(d->trayMenu);
778}
779
780void MainWin::setTrayToolTip(int status)
781{
782 if (!d->tray)
783 return;
784 d->tray->setToolTip(QString("Psi - " + status2txt(status)));
785}
786
787void MainWin::decorateButton(int status)
788{
789 // update the 'change status' buttons
790 QObjectList *l = d->statusGroup->queryList( "IconAction" );
791 QObjectListIt it( *l );
792 QObject *obj;
793 for ( ; (obj = it.current()); ++it) {
794 IconAction *action = (IconAction *)obj;
795 action->setOn ( d->statusActions[action] == status );
796 }
797 delete l;
798
799 if(d->lastStatus == status)
800 return;
801 d->lastStatus = status;
802
803 QIconSet icon;
804 icon.setPixmap(is->status(status), QIconSet::Small);
805
806 if(status == -1) {
807 d->statusButton->setText(tr("Connecting"));
808 if (option.alertStyle != 0)
809 d->statusButton->setAlert(IconsetFactory::iconPtr("psi/connect"));
810 else
811 d->statusButton->setIcon(is->statusPtr(STATUS_OFFLINE));
812
813 setIcon(is->status(STATUS_OFFLINE));
814 }
815 else {
816 d->statusButton->setText(status2txt(status));
817 d->statusButton->setIcon(is->statusPtr(status));
818
819 setIcon(is->status(status));
820 }
821
822 updateTray();
823}
824
825bool MainWin::askQuit()
826{
827 return TRUE;
828}
829
830void MainWin::try2tryCloseProgram()
831{
832 QTimer::singleShot(0, this, SLOT(tryCloseProgram()));
833}
834
835void MainWin::tryCloseProgram()
836{
837 if(askQuit())
838 closeProgram();
839}
840
841void MainWin::closeEvent(QCloseEvent *e)
842{
843#ifdef Q_WS_MAC
844 trayHide();
845 e->accept();
846#else
847 if(d->tray) {
848 trayHide();
849 e->accept();
850 return;
851 }
852
853 if(!askQuit())
854 return;
855
856 closeProgram();
857 e->accept();
858#endif
859}
860
861void MainWin::keyPressEvent(QKeyEvent *e)
862{
863#ifdef Q_WS_MAC
864 bool allowed = true;
865#else
866 bool allowed = d->tray ? true: false;
867#endif
868
869 bool closekey = false;
870 if(e->key() == Key_Escape)
871 closekey = true;
872#ifdef Q_WS_MAC
873 else if(e->key() == Key_W && e->state() & ControlButton)
874 closekey = true;
875#endif
876
877 if(closekey) {
878#ifdef Q_WS_MAC
879 if(allowed) {
880 close();
881 e->accept();
882 return;
883 }
884#else
885 if(allowed)
886 close();
887 else
888 showMinimized();
889 e->accept();
890 return;
891#endif
892 }
893
894 QWidget::keyPressEvent(e);
895}
896
897void MainWin::updateCaption()
898{
899 QString str = "";
900
901 if(d->nextAmount > 0)
902 str += "* ";
903
904 if(d->nickname.isEmpty())
905 str += PROG_NAME;
906 else
907 str += d->nickname;
908
909 if(str == caption())
910 return;
911
912 setCaption(str);
913}
914
915void MainWin::optionsUpdate()
916{
917 int status = d->lastStatus;
918 d->lastStatus = -2;
919 decorateButton(status);
920
921 if (option.hideMenubar)
922 d->gm->hide();
923 else
924 d->gm->show();
925
926#if QT_VERSION >= 0x030300
927 setWindowOpacity(double(option.rosterOpacity)/100);
928#endif
929
930 updateTray();
931}
932
933void MainWin::toggleVisible()
934{
935 if(!isHidden())
936 trayHide();
937 else
938 trayShow();
939}
940
941void MainWin::setTrayToolTip(const Status &status)
942{
943 if (!d->tray)
944 return;
945 QString s = "Psi";
946
947 QString show = status.show();
948 if(!show.isEmpty()) {
949 show[0] = show[0].upper();
950 s += " - "+show;
951 }
952
953 QString text = status.status();
954 if(!text.isEmpty())
955 s += ": "+text;
956
957 d->tray->setToolTip(s);
958}
959
960void MainWin::trayClicked(const QPoint &, int button)
961{
962 if(option.dockDCstyle)
963 return;
964
965 if(button == MidButton) {
966 doRecvNextEvent();
967 return;
968 }
969
970 if(!isHidden())
971 trayHide();
972 else
973 trayShow();
974}
975
976void MainWin::trayDoubleClicked()
977{
978 if(!option.dockDCstyle)
979 return;
980
981 if(d->nextAmount > 0) {
982 doRecvNextEvent();
983 return;
984 }
985
986
987 if(!isHidden())
988 trayHide();
989 else
990 trayShow();
991}
992
993void MainWin::trayShow()
994{
995 bringToFront(this);
996}
997
998void MainWin::trayHide()
999{
1000 emit geomChanged(x(), y(), width(), height());
1001 hide();
1002}
1003
1004void MainWin::updateReadNext(Icon *anim, int amount)
1005{
1006 d->nextAnim = anim;
1007 if(anim == 0)
1008 d->nextAmount = 0;
1009 else
1010 d->nextAmount = amount;
1011
1012 if(d->nextAmount <= 0) {
1013 d->eventNotifier->hide();
1014 d->eventNotifier->setText("");
1015 }
1016 else {
1017 d->eventNotifier->setText(QString("<b>") + numEventsString(d->nextAmount) + "</b>");
1018 d->eventNotifier->show();
1019 // make sure it shows
1020 //qApp->processEvents();
1021 }
1022
1023 updateTray();
1024 updateCaption();
1025}
1026
1027QString MainWin::numEventsString(int x) const
1028{
1029 QString s;
1030 if(x <= 0)
1031 s = "";
1032 else if(x == 1)
1033 s = tr("1 event received");
1034 else
1035 s = tr("%1 events received").arg(x);
1036
1037 return s;
1038}
1039
1040void MainWin::updateTray()
1041{
1042 if(!d->tray)
1043 return;
1044
1045 if ( d->nextAmount > 0 )
1046 d->tray->setAlert(d->nextAnim);
1047 else if ( d->lastStatus == -1 )
1048 d->tray->setAlert(IconsetFactory::iconPtr("psi/connect"));
1049 else
1050 d->tray->setIcon(is->statusPtr(d->lastStatus));
1051}
1052
1053void MainWin::doRecvNextEvent()
1054{
1055 recvNextEvent();
1056}
1057
1058void MainWin::statusClicked(int x)
1059{
1060 if(x == MidButton)
1061 recvNextEvent();
1062}
1063
1064void MainWin::numAccountsChanged()
1065{
1066 bool enabled = d->psi->accountList(TRUE).isEmpty() ? false : true;
1067 d->statusButton->setEnabled (enabled);
1068}
1069
1070void MainWin::dockActivated()
1071{
1072 if(isHidden())
1073 show();
1074}
1075
1076
1077#ifdef Q_WS_MAC
1078void MainWin::setIcon(const QPixmap&)
1079{
1080}
1081#else
1082void MainWin::setIcon(const QPixmap& p)
1083{
1084 QMainWindow::setIcon(p);
1085}
1086#endif
1087
1088#if defined(Q_WS_WIN)
1089#include<windows.h>
1090void MainWin::showNoFocus()
1091{
1092 clearWState( WState_ForceHide );
1093
1094 if ( testWState(WState_Visible) ) {
1095 SetWindowPos(winId(),HWND_TOPMOST,0,0,0,0, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE);
1096 if(!d->onTop)
1097 SetWindowPos(winId(),HWND_NOTOPMOST,0,0,0,0, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE);
1098 return; // nothing to do
1099 }
1100
1101 if ( isTopLevel() && !testWState( WState_Resized ) ) {
1102 // do this before sending the posted resize events. Otherwise
1103 // the layout would catch the resize event and may expand the
1104 // minimum size.
1105 QSize s = sizeHint();
1106 QSizePolicy::ExpandData exp;
1107#ifndef QT_NO_LAYOUT
1108 if ( layout() ) {
1109 if ( layout()->hasHeightForWidth() )
1110 s.setHeight( layout()->totalHeightForWidth( s.width() ) );
1111 exp = layout()->expanding();
1112 } else
1113#endif
1114 {
1115 if ( sizePolicy().hasHeightForWidth() )
1116 s.setHeight( heightForWidth( s.width() ) );
1117 exp = sizePolicy().expanding();
1118 }
1119 if ( exp & QSizePolicy::Horizontally )
1120 s.setWidth( QMAX( s.width(), 200 ) );
1121 if ( exp & QSizePolicy::Vertically )
1122 s.setHeight( QMAX( s.height(), 150 ) );
1123 QRect screen = QApplication::desktop()->screenGeometry( QApplication::desktop()->screenNumber( pos() ) );
1124 s.setWidth( QMIN( s.width(), screen.width()*2/3 ) );
1125 s.setHeight( QMIN( s.height(), screen.height()*2/3 ) );
1126 if ( !s.isEmpty() )
1127 resize( s );
1128 }
1129
1130 QApplication::sendPostedEvents( this, QEvent::Move );
1131 QApplication::sendPostedEvents( this, QEvent::Resize );
1132
1133 setWState( WState_Visible );
1134
1135 if ( testWFlags(WStyle_Tool) || isPopup() ) {
1136 raise();
1137 } else if ( testWFlags(WType_TopLevel) ) {
1138 while ( QApplication::activePopupWidget() )
1139 QApplication::activePopupWidget()->close();
1140 }
1141
1142 if ( !testWState(WState_Polished) )
1143 polish();
1144
1145 if ( children() ) {
1146 QObjectListIt it(*children());
1147 register QObject *object;
1148 QWidget *widget;
1149 while ( it ) { // show all widget children
1150 object = it.current(); // (except popups and other toplevels)
1151 ++it;
1152 if ( object->isWidgetType() ) {
1153 widget = (QWidget*)object;
1154 if ( !widget->isHidden() && !widget->isTopLevel() )
1155 widget->show();
1156 }
1157 }
1158 }
1159
1160#if defined(QT_ACCESSIBILITY_SUPPORT)
1161 QAccessible::updateAccessibility( this, 0, QAccessible::ObjectShow );
1162#endif
1163
1164 SetWindowPos(winId(),HWND_TOP,0,0,0,0, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW);
1165 UpdateWindow(winId());
1166}
1167
1168#else
1169
1170void MainWin::showNoFocus()
1171{
1172 bringToFront(this);
1173}
1174
1175#endif
Note: See TracBrowser for help on using the repository browser.