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

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

Psi: Fixed "bring to front" functionality:

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