/* * mainwin.cpp - the main window. holds contactlist and buttons. * Copyright (C) 2001-2003 Justin Karneges, Michail Pishchagin * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include"mainwin.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include"im.h" #include"common.h" #include"showtextdlg.h" #include"psicon.h" #include"psiaccount.h" #include"psitoolbar.h" #include"ui_about.h" #include"ui_tip.h" #include"fancylabel.h" #include"psitoolbar.h" #include"psipopup.h" #include"mainwin_p.h" using namespace XMPP; // deletes submenus in a popupmenu void qpopupmenuclear(QPopupMenu *p) { while(p->count()) { QMenuItem *item = p->findItem(p->idAt(0)); QPopupMenu *popup = item->popup(); p->removeItemAt(0); if(popup) delete popup; } } //---------------------------------------------------------------------------- // MainWin::Private //---------------------------------------------------------------------------- class MainWin::Private { public: Private(PsiCon *, MainWin *); ~Private(); QVBoxLayout *vb_main; bool onTop, asTool; QPopupMenu *mainMenu, *statusMenu, *optionsMenu, *toolsMenu; int sbState; QString nickname; MTray *tray; QPopupMenu *trayMenu; QString statusTip; PopupAction *optionsButton, *statusButton; IconActionGroup *statusGroup; EventNotifierAction *eventNotifier; PsiCon *psi; MainWin *mainWin; QSignalMapper *statusMapper; Icon *nextAnim; int nextAmount; QMap statusActions; int lastStatus; QMenuBar *gm; QString infoString; void registerActions(); IconAction *getAction( QString name ); }; MainWin::Private::Private(PsiCon *_psi, MainWin *_mainWin) { psi = _psi; mainWin = _mainWin; statusGroup = (IconActionGroup *)getAction("status_all"); eventNotifier = (EventNotifierAction *)getAction("event_notifier"); optionsButton = (PopupAction *)getAction("button_options"); statusButton = (PopupAction *)getAction("button_status"); statusMapper = new QSignalMapper(mainWin, "statusMapper"); mainWin->connect(statusMapper, SIGNAL(mapped(int)), mainWin, SLOT(activatedStatusAction(int))); } MainWin::Private::~Private() { } void MainWin::Private::registerActions() { struct { const char *name; int id; } statuslist[] = { { "status_chat", STATUS_CHAT }, { "status_online", STATUS_ONLINE }, { "status_away", STATUS_AWAY }, { "status_xa", STATUS_XA }, { "status_dnd", STATUS_DND }, { "status_invisible", STATUS_INVISIBLE }, { "status_offline", STATUS_OFFLINE }, { "", 0 } }; int i; QString aName; for ( i = 0; !(aName = QString(statuslist[i].name)).isEmpty(); i++ ) { IconAction *action = getAction( aName ); connect (action, SIGNAL(activated()), statusMapper, SLOT(map())); statusMapper->setMapping(action, statuslist[i].id); statusActions[action] = statuslist[i].id; } // register all actions PsiActionList::ActionsType type = PsiActionList::ActionsType( PsiActionList::Actions_MainWin | PsiActionList::Actions_Common ); ActionList actions = psi->actionList()->suitableActions( type ); QStringList names = actions.actions(); QStringList::Iterator it = names.begin(); for ( ; it != names.end(); ++it ) { IconAction *action = actions.action( *it ); if ( action ) mainWin->registerAction( action ); } } IconAction *MainWin::Private::getAction( QString name ) { PsiActionList::ActionsType type = PsiActionList::ActionsType( PsiActionList::Actions_MainWin | PsiActionList::Actions_Common ); ActionList actions = psi->actionList()->suitableActions( type ); IconAction *action = actions.action( name ); if ( !action ) qWarning("MainWin::Private::getAction(): action %s not found!", name.latin1()); //else // mainWin->registerAction( action ); return action; } //---------------------------------------------------------------------------- // MainWin //---------------------------------------------------------------------------- //#ifdef Q_WS_X11 //#define TOOLW_FLAGS WStyle_Customize //#else #define TOOLW_FLAGS 0 //#endif MainWin::MainWin(bool _onTop, bool _asTool, PsiCon *psi, const char *name) :AdvancedWidget(0, name, 0 | (_onTop ? WStyle_StaysOnTop: 0) | (_asTool ? WStyle_Tool | TOOLW_FLAGS : 0)) { d = new Private(psi, this); setIcon(is->status(STATUS_OFFLINE)); d->onTop = _onTop; d->asTool = _asTool; // sbState: // -1 : connect // >= 0 : STATUS_* d->sbState = STATUS_OFFLINE; d->lastStatus = -2; d->nextAmount = 0; d->nextAnim = 0; d->tray = 0; d->trayMenu = 0; d->statusTip = ""; d->infoString = ""; d->nickname = ""; QWidget *center = new QWidget (this, "Central widget"); setCentralWidget ( center ); d->vb_main = new QVBoxLayout(center, 2); cvlist = new ContactView(center); d->vb_main->addWidget(cvlist, 1); #ifdef Q_WS_MAC // If the space isn't there, MacOS draws an empty vertical scrollbar :( d->vb_main->addSpacing(1); #endif d->statusMenu = new QPopupMenu(this); d->optionsMenu = new QPopupMenu(this); buildStatusMenu(); buildOptionsMenu(); connect(d->statusMenu, SIGNAL(aboutToShow()), SLOT(buildStatusMenu())); connect(d->optionsMenu, SIGNAL(aboutToShow()), SLOT(buildOptionsMenu())); d->optionsButton->setPopup( d->optionsMenu ); d->statusButton->setPopup( d->statusMenu ); X11WM_CLASS("main"); connect(d->psi, SIGNAL(accountCountChanged()), SLOT(numAccountsChanged())); numAccountsChanged(); updateCaption(); d->registerActions(); buildToolbars(); decorateButton(STATUS_OFFLINE); // show tip of the day if ( option.showTips ) actTipActivated(); #ifdef Q_WS_MAC // Create a global menubar d->gm = new QMenuBar(0); #else // Create a menu for the current window d->gm = new QMenuBar(this); #endif // Mac-only menus #ifdef Q_WS_MAC QPopupMenu *mainMenu = new QPopupMenu(this); d->gm->insertItem(tr("Menu"), mainMenu); mainMenu->insertItem(tr("Preferences"), this, SIGNAL(doOptions())); mainMenu->insertItem(tr("Quit"), this, SLOT(try2tryCloseProgram())); d->getAction("help_about")->addTo(mainMenu); d->getAction("help_about_qt")->addTo(mainMenu); d->mainMenu = new QPopupMenu(this); d->gm->insertItem(tr("General"), d->mainMenu); connect(d->mainMenu, SIGNAL(aboutToShow()), SLOT(buildMainMenu())); #else d->gm->insertItem(tr("General"), d->optionsMenu); #endif d->gm->insertItem(tr("Status"), d->statusMenu); QPopupMenu *viewMenu = new QPopupMenu(this); d->gm->insertItem(tr("View"), viewMenu); d->getAction("show_offline")->addTo(viewMenu); d->getAction("show_away")->addTo(viewMenu); d->getAction("show_hidden")->addTo(viewMenu); d->getAction("show_agents")->addTo(viewMenu); d->getAction("show_self")->addTo(viewMenu); // Mac-only menus #ifdef Q_WS_MAC d->toolsMenu = new QPopupMenu(this); d->gm->insertItem(tr("Tools"), d->toolsMenu); connect(d->toolsMenu, SIGNAL(aboutToShow()), SLOT(buildToolsMenu())); QPopupMenu *helpMenu = new QPopupMenu(this); d->gm->insertItem(tr("Help"), helpMenu); d->getAction("help_readme")->addTo (helpMenu); d->getAction("help_tip")->addTo (helpMenu); helpMenu->insertSeparator(); d->getAction("help_online_help")->addTo (helpMenu); d->getAction("help_online_wiki")->addTo (helpMenu); d->getAction("help_online_home")->addTo (helpMenu); d->getAction("help_report_bug")->addTo (helpMenu); d->gm->show(); #else if (option.hideMenubar) d->gm->hide(); else d->gm->show(); #endif #if QT_VERSION >= 0x030300 setWindowOpacity(double(option.rosterOpacity)/100); #endif connect(qApp, SIGNAL(dockActivated()), SLOT(dockActivated())); } MainWin::~MainWin() { PsiPopup::deleteAll(); if (d->gm) delete d->gm; if(d->tray) { delete d->tray; d->tray = 0; delete d->trayMenu; d->trayMenu = 0; } //saveToolbarsPositions(); // need to find some workaround to case, when you're logging off. in that case // toobars are all disabled, and when you start psi again you need to enable // your toolbars delete d; } void MainWin::registerAction( IconAction *action ) { char activated[] = SIGNAL( activated() ); char toggled[] = SIGNAL( toggled(bool) ); char setOn[] = SLOT( setOn(bool) ); struct { const char *name; const char *signal; QObject *receiver; const char *slot; } actionlist[] = { { "show_offline", toggled, cvlist, SLOT( setShowOffline(bool) ) }, { "show_away", toggled, cvlist, SLOT( setShowAway(bool) ) }, { "show_hidden", toggled, cvlist, SLOT( setShowHidden(bool) ) }, { "show_agents", toggled, cvlist, SLOT( setShowAgents(bool) ) }, { "show_self", toggled, cvlist, SLOT( setShowSelf(bool) ) }, { "button_options", activated, this, SIGNAL( doOptions() ) }, { "menu_disco", SIGNAL( activated(PsiAccount *, int) ), this, SLOT( activatedAccOption(PsiAccount*, int) ) }, { "menu_add_contact", SIGNAL( activated(PsiAccount *, int) ), this, SLOT( activatedAccOption(PsiAccount*, int) ) }, { "menu_xml_console", SIGNAL( activated(PsiAccount *, int) ), this, SLOT( activatedAccOption(PsiAccount*, int) ) }, { "menu_new_message", activated, this, SIGNAL( blankMessage() ) }, { "menu_join_groupchat", activated, this, SIGNAL( doGroupChat() ) }, { "menu_account_setup", activated, this, SIGNAL( doManageAccounts() ) }, { "menu_options", activated, this, SIGNAL( doOptions() ) }, { "menu_file_transfer", activated, this, SIGNAL( doFileTransDlg() ) }, { "menu_toolbars", activated, this, SIGNAL( doToolbars() ) }, { "menu_change_profile", activated, this, SIGNAL( changeProfile() ) }, { "menu_quit", activated, this, SLOT( try2tryCloseProgram() ) }, { "menu_play_sounds", toggled, this, SLOT( actPlaySoundsActivated(bool) ) }, { "event_notifier", SIGNAL( clicked(int) ), this, SLOT( statusClicked(int) ) }, { "event_notifier", activated, this, SLOT( doRecvNextEvent() ) }, { "help_readme", activated, this, SLOT( actReadmeActivated() ) }, { "help_tip", activated, this, SLOT( actTipActivated() ) }, { "help_online_help", activated, this, SLOT( actOnlineHelpActivated() ) }, { "help_online_wiki", activated, this, SLOT( actOnlineWikiActivated() ) }, { "help_online_home", activated, this, SLOT( actOnlineHomeActivated() ) }, { "help_report_bug", activated, this, SLOT( actBugReportActivated() ) }, { "help_about", activated, this, SLOT( actAboutActivated() ) }, { "help_about_qt", activated, this, SLOT( actAboutQtActivated() ) }, { "", 0, 0, 0 } }; int i; QString aName; for ( i = 0; !(aName = QString(actionlist[i].name)).isEmpty(); i++ ) { if ( aName == action->name() ) { disconnect( action, actionlist[i].signal, actionlist[i].receiver, actionlist[i].slot ); // for safety connect( action, actionlist[i].signal, actionlist[i].receiver, actionlist[i].slot ); // special cases if ( aName == "menu_play_sounds" ) action->setOn( useSound ); //else if ( aName == "foobar" ) // ; } } struct { const char *name; QObject *sender; const char *signal; const char *slot; } reverseactionlist[] = { { "show_away", cvlist, SIGNAL( showAway(bool) ), setOn }, { "show_hidden", cvlist, SIGNAL( showHidden(bool) ), setOn }, { "show_offline", cvlist, SIGNAL( showOffline(bool) ), setOn }, { "show_self", cvlist, SIGNAL( showSelf(bool) ), setOn }, { "show_agents", cvlist, SIGNAL( showAgents(bool) ), setOn }, { "", 0, 0, 0 } }; for ( i = 0; !(aName = QString(reverseactionlist[i].name)).isEmpty(); i++ ) { if ( aName == action->name() ) { disconnect( reverseactionlist[i].sender, reverseactionlist[i].signal, action, reverseactionlist[i].slot ); // for safety connect( reverseactionlist[i].sender, reverseactionlist[i].signal, action, reverseactionlist[i].slot ); action->setOn( true ); } } } PsiCon *MainWin::psiCon() const { return d->psi; } void MainWin::setWindowOpts(bool _onTop, bool _asTool) { if(_onTop == d->onTop && _asTool == d->asTool) return; d->onTop = _onTop; d->asTool = _asTool; WFlags flags = 0; if(d->onTop) flags |= WStyle_StaysOnTop; if(d->asTool) flags |= WStyle_Tool | TOOLW_FLAGS; QPoint p = pos(); reparent(parentWidget(), flags, p, FALSE); move(p); show(); } void MainWin::setUseDock(bool use) { #ifdef Q_WS_PM /// @todo (dmik) disable the docklet until the xCenter plugin is implemented // (this ifdef is necessary in order to share the same config between // different platforms where the Use Docklet option may be set to true. return; #else if(use == false || (d->tray && option.isWMDock != d->tray->isWMDock())) { if(d->tray) { delete d->tray; d->tray = 0; delete d->trayMenu; d->trayMenu = 0; } if (use == false) return; } if(d->tray) return; d->trayMenu = new QPopupMenu; connect(d->trayMenu, SIGNAL(aboutToShow()), SLOT(buildTrayMenu())); d->tray = new MTray("Psi", d->trayMenu); d->tray->setIcon( is->statusPtr( STATUS_OFFLINE )); d->tray->setToolTip(PROG_NAME); connect(d->tray, SIGNAL(clicked(const QPoint &, int)), SLOT(trayClicked(const QPoint &, int))); connect(d->tray, SIGNAL(doubleClicked(const QPoint &)), SLOT(trayDoubleClicked())); connect(d->tray, SIGNAL(closed()), SLOT(dockActivated())); connect(qApp, SIGNAL(trayOwnerDied()), SLOT(dockActivated())); updateReadNext(d->nextAnim, d->nextAmount); d->tray->show(); #endif } void MainWin::setInfo(const QString &str) { d->infoString = str; if(d->nextAmount == 0) d->eventNotifier->setText(d->infoString); } void MainWin::buildStatusMenu() { //statusMenu->clear(); qpopupmenuclear(d->statusMenu); d->statusGroup->addTo(d->statusMenu); } void MainWin::activatedStatusAction(int id) { QObjectList *l = d->statusGroup->queryList( "IconAction" ); QObjectListIt it( *l ); QObject *obj; for ( ; (obj = it.current()); ++it) { IconAction *action = (IconAction *)obj; action->setOn ( d->statusActions[action] == id ); } delete l; statusChanged(id); } void MainWin::buildToolbars() { bool dockBottom = false; while ( option.toolbars.count() < toolbars.count() && toolbars.count() ) { PsiToolBar *tb = toolbars.last(); toolbars.removeLast(); delete tb; } uint i; for (i = 0; i < option.toolbars["mainWin"].count(); i++) { PsiToolBar *tb = 0; if ( i < toolbars.count() ) tb = toolbars.at(i); Options::ToolbarPrefs &tbPref = option.toolbars["mainWin"][i]; if ( tb && !tbPref.dirty ) continue; if ( tb ) delete tb; tb = new PsiToolBar (tbPref.name, this, this); moveDockWindow ( tb, tbPref.dock, tbPref.nl, tbPref.index, tbPref. extraOffset ); tb->setGroup( "mainWin", i ); tb->setPsiCon( d->psi ); tb->setType( PsiActionList::Actions_MainWin ); //connect( tb, SIGNAL( registerAction( IconAction * ) ), SLOT( registerAction( IconAction * ) ) ); tb->initialize( tbPref, false ); // MacOS stuff dockBottom = dockBottom || (tbPref.dock == Qt::DockBottom && tbPref.on); if ( i < toolbars.count() ) toolbars.remove(i); toolbars.insert(i, tb); } #ifdef Q_WS_MAC if (dockBottom) { statusBar()->show(); } else { statusBar()->hide(); } #endif } void MainWin::saveToolbarsPositions() { for (uint i = 0; i < toolbars.count(); i++) { Options::ToolbarPrefs &tbPref = option.toolbars["mainWin"][i]; getLocation ( toolbars.at(i), tbPref.dock, tbPref.index, tbPref.nl, tbPref.extraOffset ); tbPref.on = toolbars.at(i)->isVisible(); } } bool MainWin::showDockMenu(const QPoint &) { return false; } void MainWin::buildOptionsMenu() { d->optionsMenu->clear(); // help menu QPopupMenu *helpMenu = new QPopupMenu(d->optionsMenu); QStringList actionNames; actionNames << "help_readme"; actionNames << "help_tip"; actionNames << "separator"; actionNames << "help_online_help"; actionNames << "help_online_wiki"; actionNames << "help_online_home"; actionNames << "help_report_bug"; actionNames << "separator"; actionNames << "help_about"; actionNames << "help_about_qt"; QStringList::Iterator it; IconAction *action; for ( it = actionNames.begin(); it != actionNames.end(); ++it ) if ( (action = d->getAction(*it)) ) action->addTo( helpMenu ); buildGeneralMenu( d->optionsMenu ); d->optionsMenu->insertSeparator(); d->optionsMenu->insertItem(IconsetFactory::icon("psi/help"), tr("&Help"), helpMenu); d->getAction("menu_quit")->addTo( d->optionsMenu ); } void MainWin::buildMainMenu() { d->mainMenu->clear(); QStringList actionNames; // options menu if(!option.lockdown.roster) actionNames << "menu_add_contact"; actionNames << "menu_new_message"; if(!option.lockdown.services) actionNames << "menu_disco"; actionNames << "menu_join_groupchat"; actionNames << ""; if(!option.lockdown.accounts) actionNames << "menu_account_setup"; if(!option.lockdown.profiles) actionNames << "menu_change_profile"; actionNames << "menu_toolbars"; actionNames << "menu_play_sounds"; QStringList::Iterator it; IconAction *action; for ( it = actionNames.begin(); it != actionNames.end(); ++it ) { if ((*it).isEmpty()) d->mainMenu->insertSeparator(); else if ( (action = d->getAction(*it)) ) action->addTo( d->mainMenu ); } } void MainWin::buildToolsMenu() { IconAction* action; d->toolsMenu->clear(); if ( (action = d->getAction("menu_file_transfer")) ) action->addTo(d->toolsMenu); d->toolsMenu->insertSeparator(); if ( (action = d->getAction("menu_xml_console")) ) action->addTo(d->toolsMenu); } void MainWin::buildGeneralMenu(QPopupMenu *menu) { menu->clear(); QStringList actionNames; // options menu if(!option.lockdown.roster) actionNames << "menu_add_contact"; actionNames << "menu_new_message"; if(!option.lockdown.services) actionNames << "menu_disco"; actionNames << "menu_join_groupchat"; if(!option.lockdown.accounts) actionNames << "menu_account_setup"; if(!option.lockdown.options) actionNames << "menu_options"; actionNames << "menu_file_transfer"; // TODO: probably we want to lock down filetransfer, right? if(!option.lockdown.profiles) actionNames << "menu_change_profile"; actionNames << "menu_toolbars"; actionNames << "menu_play_sounds"; QStringList::Iterator it; IconAction *action; for ( it = actionNames.begin(); it != actionNames.end(); ++it ) if ( (action = d->getAction(*it)) ) action->addTo( menu ); } // WTF?? void MainWin::testme() { d->optionsMenu->setItemEnabled(10, false); } void MainWin::actReadmeActivated () { #if defined(Q_WS_WIN) || defined(Q_OS_OS2) ShowTextDlg *w = new ShowTextDlg(g.pathBase + "/readme.txt"); #else ShowTextDlg *w = new ShowTextDlg(g.pathBase + "/README"); #endif w->setCaption(CAP(tr("ReadMe"))); w->show(); } void MainWin::actOnlineHelpActivated () { openURL("http://psi-im.org/wiki/User_Guide"); } void MainWin::actOnlineWikiActivated () { openURL("http://psi-im.org/wiki"); } void MainWin::actOnlineHomeActivated () { openURL("http://psi-im.org"); } void MainWin::actBugReportActivated () { openURL("http://psi-im.org/forum/forum/2"); } void MainWin::actAboutActivated () { AboutDlg *about = new AboutDlg (this, "AboutDlg", false, WDestructiveClose); about->show(); } void MainWin::actTipActivated () { TipUI *tip = new TipUI (this, "TipDlg", false, WDestructiveClose); tip->show(); } void MainWin::actAboutQtActivated () { QMessageBox::aboutQt(this); } void MainWin::actPlaySoundsActivated (bool state) { useSound = state; } void MainWin::activatedAccOption(PsiAccount *pa, int x) { if(x == 0) pa->openAddUserDlg(); else if(x == 2) pa->showXmlConsole(); else if(x == 3) pa->doDisco(); } void MainWin::buildTrayMenu() { if(!d->trayMenu) return; d->trayMenu->clear(); if(d->nextAmount > 0) { d->trayMenu->insertItem(tr("Receive next event"), this, SLOT(doRecvNextEvent())); d->trayMenu->insertSeparator(); } if(isHidden()) d->trayMenu->insertItem(tr("Un&hide"), this, SLOT(trayShow())); else d->trayMenu->insertItem(tr("&Hide"), this, SLOT(trayHide())); d->optionsButton->addTo(d->trayMenu); d->statusButton->addTo(d->trayMenu); d->trayMenu->insertSeparator(); // TODO! d->getAction("menu_quit")->addTo(d->trayMenu); } void MainWin::setTrayToolTip(int status) { if (!d->tray) return; d->tray->setToolTip(QString("Psi - " + status2txt(status))); } void MainWin::decorateButton(int status) { // update the 'change status' buttons QObjectList *l = d->statusGroup->queryList( "IconAction" ); QObjectListIt it( *l ); QObject *obj; for ( ; (obj = it.current()); ++it) { IconAction *action = (IconAction *)obj; action->setOn ( d->statusActions[action] == status ); } delete l; if(d->lastStatus == status) return; d->lastStatus = status; QIconSet icon; icon.setPixmap(is->status(status), QIconSet::Small); if(status == -1) { d->statusButton->setText(tr("Connecting")); if (option.alertStyle != 0) d->statusButton->setAlert(IconsetFactory::iconPtr("psi/connect")); else d->statusButton->setIcon(is->statusPtr(STATUS_OFFLINE)); setIcon(is->status(STATUS_OFFLINE)); } else { d->statusButton->setText(status2txt(status)); d->statusButton->setIcon(is->statusPtr(status)); setIcon(is->status(status)); } updateTray(); } bool MainWin::askQuit() { return TRUE; } void MainWin::try2tryCloseProgram() { QTimer::singleShot(0, this, SLOT(tryCloseProgram())); } void MainWin::tryCloseProgram() { if(askQuit()) closeProgram(); } void MainWin::closeEvent(QCloseEvent *e) { #ifdef Q_WS_MAC trayHide(); e->accept(); #else if(d->tray) { trayHide(); e->accept(); return; } if(!askQuit()) return; closeProgram(); e->accept(); #endif } void MainWin::keyPressEvent(QKeyEvent *e) { #ifdef Q_WS_MAC bool allowed = true; #else bool allowed = d->tray ? true: false; #endif bool closekey = false; if(e->key() == Key_Escape && e->state() == 0) closekey = true; #ifdef Q_WS_MAC else if(e->key() == Key_W && e->state() & ControlButton) closekey = true; #endif if(closekey) { #ifdef Q_WS_MAC if(allowed) { close(); e->accept(); return; } #else if(allowed) close(); else showMinimized(); e->accept(); return; #endif } QWidget::keyPressEvent(e); } void MainWin::updateCaption() { QString str = ""; if(d->nextAmount > 0) str += "* "; if(d->nickname.isEmpty()) str += PROG_NAME; else str += d->nickname; if(str == caption()) return; setCaption(str); } void MainWin::optionsUpdate() { int status = d->lastStatus; d->lastStatus = -2; decorateButton(status); if (option.hideMenubar) d->gm->hide(); else d->gm->show(); #if QT_VERSION >= 0x030300 setWindowOpacity(double(option.rosterOpacity)/100); #endif updateTray(); } void MainWin::toggleVisible() { if(!isHidden()) trayHide(); else trayShow(); } void MainWin::setTrayToolTip(const Status &status) { if (!d->tray) return; QString s = "Psi"; QString show = status.show(); if(!show.isEmpty()) { show[0] = show[0].upper(); s += " - "+show; } QString text = status.status(); if(!text.isEmpty()) s += ": "+text; d->tray->setToolTip(s); } void MainWin::trayClicked(const QPoint &, int button) { if(option.dockDCstyle) return; if(button == MidButton) { doRecvNextEvent(); return; } if(!isHidden()) trayHide(); else trayShow(); } void MainWin::trayDoubleClicked() { if(!option.dockDCstyle) return; if(d->nextAmount > 0) { doRecvNextEvent(); return; } if(!isHidden()) trayHide(); else trayShow(); } void MainWin::trayShow() { bringToFront(this); } void MainWin::trayHide() { emit geomChanged(x(), y(), width(), height()); hide(); } void MainWin::updateReadNext(Icon *anim, int amount) { d->nextAnim = anim; if(anim == 0) d->nextAmount = 0; else d->nextAmount = amount; if(d->nextAmount <= 0) { d->eventNotifier->hide(); d->eventNotifier->setText(""); } else { d->eventNotifier->setText(QString("") + numEventsString(d->nextAmount) + ""); d->eventNotifier->show(); // make sure it shows //qApp->processEvents(); } updateTray(); updateCaption(); } QString MainWin::numEventsString(int x) const { QString s; if(x <= 0) s = ""; else if(x == 1) s = tr("1 event received"); else s = tr("%1 events received").arg(x); return s; } void MainWin::updateTray() { if(!d->tray) return; if ( d->nextAmount > 0 ) d->tray->setAlert(d->nextAnim); else if ( d->lastStatus == -1 ) d->tray->setAlert(IconsetFactory::iconPtr("psi/connect")); else d->tray->setIcon(is->statusPtr(d->lastStatus)); } void MainWin::doRecvNextEvent() { recvNextEvent(); } void MainWin::statusClicked(int x) { if(x == MidButton) recvNextEvent(); } void MainWin::numAccountsChanged() { bool enabled = d->psi->accountList(TRUE).isEmpty() ? false : true; d->statusButton->setEnabled (enabled); } void MainWin::dockActivated() { if(isHidden()) show(); } #ifdef Q_WS_MAC void MainWin::setIcon(const QPixmap&) { } #else void MainWin::setIcon(const QPixmap& p) { QMainWindow::setIcon(p); } #endif /// @todo (r=dmik) I don't fully understand what is this code good for, but // at least it doesn't do what it should (for example, if the roster window is // minimized, it won't be shown). Instead we use bringToFront() just like on // any other platform (the *fixed* version of bringToFront() seems to work ok). #if 0 && defined(Q_WS_WIN) #include void MainWin::showNoFocus() { clearWState( WState_ForceHide ); if ( testWState(WState_Visible) ) { SetWindowPos(winId(),HWND_TOPMOST,0,0,0,0, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE); if(!d->onTop) SetWindowPos(winId(),HWND_NOTOPMOST,0,0,0,0, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE); return; // nothing to do } if ( isTopLevel() && !testWState( WState_Resized ) ) { // do this before sending the posted resize events. Otherwise // the layout would catch the resize event and may expand the // minimum size. QSize s = sizeHint(); QSizePolicy::ExpandData exp; #ifndef QT_NO_LAYOUT if ( layout() ) { if ( layout()->hasHeightForWidth() ) s.setHeight( layout()->totalHeightForWidth( s.width() ) ); exp = layout()->expanding(); } else #endif { if ( sizePolicy().hasHeightForWidth() ) s.setHeight( heightForWidth( s.width() ) ); exp = sizePolicy().expanding(); } if ( exp & QSizePolicy::Horizontally ) s.setWidth( QMAX( s.width(), 200 ) ); if ( exp & QSizePolicy::Vertically ) s.setHeight( QMAX( s.height(), 150 ) ); QRect screen = QApplication::desktop()->screenGeometry( QApplication::desktop()->screenNumber( pos() ) ); s.setWidth( QMIN( s.width(), screen.width()*2/3 ) ); s.setHeight( QMIN( s.height(), screen.height()*2/3 ) ); if ( !s.isEmpty() ) resize( s ); } QApplication::sendPostedEvents( this, QEvent::Move ); QApplication::sendPostedEvents( this, QEvent::Resize ); setWState( WState_Visible ); if ( testWFlags(WStyle_Tool) || isPopup() ) { raise(); } else if ( testWFlags(WType_TopLevel) ) { while ( QApplication::activePopupWidget() ) QApplication::activePopupWidget()->close(); } if ( !testWState(WState_Polished) ) polish(); if ( children() ) { QObjectListIt it(*children()); register QObject *object; QWidget *widget; while ( it ) { // show all widget children object = it.current(); // (except popups and other toplevels) ++it; if ( object->isWidgetType() ) { widget = (QWidget*)object; if ( !widget->isHidden() && !widget->isTopLevel() ) widget->show(); } } } #if defined(QT_ACCESSIBILITY_SUPPORT) QAccessible::updateAccessibility( this, 0, QAccessible::ObjectShow ); #endif SetWindowPos(winId(),HWND_TOP,0,0,0,0, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW); UpdateWindow(winId()); } #else void MainWin::showNoFocus() { #if defined(QT_ACCESSIBILITY_SUPPORT) QAccessible::updateAccessibility( this, 0, QAccessible::ObjectShow ); #endif bringToFront(this, false); } #endif