00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <config.h>
00020
00021 #include "kmsystemtray.h"
00022 #include "kmfolder.h"
00023 #include "kmfoldertree.h"
00024 #include "kmfoldermgr.h"
00025 #include "kmfolderimap.h"
00026 #include "kmmainwidget.h"
00027 #include "accountmanager.h"
00028 using KMail::AccountManager;
00029 #include "globalsettings.h"
00030
00031 #include <kapplication.h>
00032 #include <kmainwindow.h>
00033 #include <kglobalsettings.h>
00034 #include <kiconloader.h>
00035 #include <kiconeffect.h>
00036 #include <kwin.h>
00037 #include <kdebug.h>
00038 #include <kpopupmenu.h>
00039
00040 #include <tqpainter.h>
00041 #include <tqbitmap.h>
00042 #include <tqtooltip.h>
00043 #include <tqwidgetlist.h>
00044 #include <tqobjectlist.h>
00045
00046 #include <math.h>
00047 #include <assert.h>
00048
00060 KMSystemTray::KMSystemTray(TQWidget *parent, const char *name)
00061 : KSystemTray( parent, name ),
00062 mParentVisible( true ),
00063 mPosOfMainWin( 0, 0 ),
00064 mDesktopOfMainWin( 0 ),
00065 mMode( GlobalSettings::EnumSystemTrayPolicy::ShowOnUnread ),
00066 mCount( 0 ),
00067 mNewMessagePopupId(-1),
00068 mPopupMenu(0)
00069 {
00070 setAlignment( AlignCenter );
00071 kdDebug(5006) << "Initting systray" << endl;
00072
00073 mLastUpdate = time( 0 );
00074 mUpdateTimer = new TQTimer( this, "systraytimer" );
00075 connect( mUpdateTimer, TQT_SIGNAL( timeout() ), TQT_SLOT( updateNewMessages() ) );
00076
00077 mDefaultIcon = loadIcon( "kmail" );
00078 mLightIconImage = loadIcon( "kmaillight" ).convertToImage();
00079
00080 setPixmap(mDefaultIcon);
00081
00082 KMMainWidget * mainWidget = kmkernel->getKMMainWidget();
00083 if ( mainWidget ) {
00084 TQWidget * mainWin = mainWidget->topLevelWidget();
00085 if ( mainWin ) {
00086 mDesktopOfMainWin = KWin::windowInfo( mainWin->winId(),
00087 NET::WMDesktop ).desktop();
00088 mPosOfMainWin = mainWin->pos();
00089 }
00090 }
00091
00092
00093 kmkernel->registerSystemTrayApplet( this );
00094
00096 foldersChanged();
00097
00098 connect( kmkernel->folderMgr(), TQT_SIGNAL(changed()), TQT_SLOT(foldersChanged()));
00099 connect( kmkernel->imapFolderMgr(), TQT_SIGNAL(changed()), TQT_SLOT(foldersChanged()));
00100 connect( kmkernel->dimapFolderMgr(), TQT_SIGNAL(changed()), TQT_SLOT(foldersChanged()));
00101 connect( kmkernel->searchFolderMgr(), TQT_SIGNAL(changed()), TQT_SLOT(foldersChanged()));
00102
00103 connect( kmkernel->acctMgr(), TQT_SIGNAL( checkedMail( bool, bool, const TQMap<TQString, int> & ) ),
00104 TQT_SLOT( updateNewMessages() ) );
00105
00106 connect( this, TQT_SIGNAL( quitSelected() ), TQT_SLOT( tray_quit() ) );
00107 }
00108
00109 void KMSystemTray::buildPopupMenu()
00110 {
00111
00112 delete mPopupMenu;
00113
00114 mPopupMenu = new KPopupMenu();
00115 KMMainWidget * mainWidget = kmkernel->getKMMainWidget();
00116 if ( !mainWidget )
00117 return;
00118
00119 mPopupMenu->insertTitle(*(this->pixmap()), "KMail");
00120 KAction * action;
00121 if ( ( action = mainWidget->action("check_mail") ) )
00122 action->plug( mPopupMenu );
00123 if ( ( action = mainWidget->action("check_mail_in") ) )
00124 action->plug( mPopupMenu );
00125 if ( ( action = mainWidget->action("send_queued") ) )
00126 action->plug( mPopupMenu );
00127 if ( ( action = mainWidget->action("send_queued_via") ) )
00128 action->plug( mPopupMenu );
00129 mPopupMenu->insertSeparator();
00130 if ( ( action = mainWidget->action("new_message") ) )
00131 action->plug( mPopupMenu );
00132 if ( ( action = mainWidget->action("kmail_configure_kmail") ) )
00133 action->plug( mPopupMenu );
00134 mPopupMenu->insertSeparator();
00135
00136 KMainWindow *mainWin = ::tqqt_cast<KMainWindow*>(kmkernel->getKMMainWidget()->topLevelWidget());
00137 mPopupMenu->insertItem( SmallIcon("exit"), i18n("&Quit"), this, TQT_SLOT(maybeQuit()) );
00138 }
00139
00140 void KMSystemTray::tray_quit()
00141 {
00142
00143 kapp->quit();
00144 }
00145
00146 KMSystemTray::~KMSystemTray()
00147 {
00148
00149 kmkernel->unregisterSystemTrayApplet( this );
00150
00151 delete mPopupMenu;
00152 mPopupMenu = 0;
00153 }
00154
00155 void KMSystemTray::setMode(int newMode)
00156 {
00157 if(newMode == mMode) return;
00158
00159 kdDebug(5006) << "Setting systray mMode to " << newMode << endl;
00160 mMode = newMode;
00161
00162 switch ( mMode ) {
00163 case GlobalSettings::EnumSystemTrayPolicy::ShowAlways:
00164 if ( isHidden() )
00165 show();
00166 break;
00167 case GlobalSettings::EnumSystemTrayPolicy::ShowOnUnread:
00168 if ( mCount == 0 && !isHidden() )
00169 hide();
00170 else if ( mCount > 0 && isHidden() )
00171 show();
00172 break;
00173 default:
00174 kdDebug(5006) << k_funcinfo << " Unknown systray mode " << mMode << endl;
00175 }
00176 }
00177
00178 int KMSystemTray::mode() const
00179 {
00180 return mMode;
00181 }
00182
00188 void KMSystemTray::updateCount()
00189 {
00190 if(mCount != 0)
00191 {
00192 int oldPixmapWidth = pixmap()->size().width();
00193 int oldPixmapHeight = pixmap()->size().height();
00194
00195 TQString countString = TQString::number( mCount );
00196 TQFont countFont = KGlobalSettings::generalFont();
00197 countFont.setBold(true);
00198
00199
00200
00201 float countFontSize = countFont.pointSizeFloat();
00202 TQFontMetrics qfm( countFont );
00203 int width = qfm.width( countString );
00204 if( width > oldPixmapWidth )
00205 {
00206 countFontSize *= float( oldPixmapWidth ) / float( width );
00207 countFont.setPointSizeFloat( countFontSize );
00208 }
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 TQPixmap numberPixmap( oldPixmapWidth, oldPixmapHeight );
00228 numberPixmap.fill( TQt::white );
00229 TQPainter p( &numberPixmap );
00230 p.setFont( countFont );
00231 p.setPen( TQt::blue );
00232 p.drawText( numberPixmap.rect(), TQt::AlignCenter, countString );
00233 numberPixmap.setMask( numberPixmap.createHeuristicMask() );
00234 TQImage numberImage = numberPixmap.convertToImage();
00235
00236
00237 TQImage iconWithNumberImage = mLightIconImage.copy();
00238 KIconEffect::overlay( iconWithNumberImage, numberImage );
00239
00240 TQPixmap iconWithNumber;
00241 iconWithNumber.convertFromImage( iconWithNumberImage );
00242 setPixmap( iconWithNumber );
00243 } else
00244 {
00245 setPixmap( mDefaultIcon );
00246 }
00247 }
00248
00253 void KMSystemTray::foldersChanged()
00254 {
00259 mFoldersWithUnread.clear();
00260 mCount = 0;
00261
00262 if ( mMode == GlobalSettings::EnumSystemTrayPolicy::ShowOnUnread ) {
00263 hide();
00264 }
00265
00267 disconnect(this, TQT_SLOT(updateNewMessageNotification(KMFolder *)));
00268
00269 TQStringList folderNames;
00270 TQValueList<TQGuardedPtr<KMFolder> > folderList;
00271 kmkernel->folderMgr()->createFolderList(&folderNames, &folderList);
00272 kmkernel->imapFolderMgr()->createFolderList(&folderNames, &folderList);
00273 kmkernel->dimapFolderMgr()->createFolderList(&folderNames, &folderList);
00274 kmkernel->searchFolderMgr()->createFolderList(&folderNames, &folderList);
00275
00276 TQStringList::iterator strIt = folderNames.begin();
00277
00278 for(TQValueList<TQGuardedPtr<KMFolder> >::iterator it = folderList.begin();
00279 it != folderList.end() && strIt != folderNames.end(); ++it, ++strIt)
00280 {
00281 KMFolder * currentFolder = *it;
00282 TQString currentName = *strIt;
00283
00284 if ( ((!currentFolder->isSystemFolder() || (currentFolder->name().lower() == "inbox")) ||
00285 (currentFolder->folderType() == KMFolderTypeImap)) &&
00286 !currentFolder->ignoreNewMail() )
00287 {
00289 connect(currentFolder, TQT_SIGNAL(numUnreadMsgsChanged(KMFolder *)),
00290 this, TQT_SLOT(updateNewMessageNotification(KMFolder *)));
00291
00293 updateNewMessageNotification(currentFolder);
00294 }
00295 else {
00296 disconnect(currentFolder, TQT_SIGNAL(numUnreadMsgsChanged(KMFolder *)), this, TQT_SLOT(updateNewMessageNotification(KMFolder *)) );
00297 }
00298 }
00299 }
00300
00305 void KMSystemTray::mousePressEvent(TQMouseEvent *e)
00306 {
00307
00308 if( e->button() == Qt::LeftButton )
00309 {
00310 if( mParentVisible && mainWindowIsOnCurrentDesktop() )
00311 hideKMail();
00312 else
00313 showKMail();
00314 }
00315
00316
00317 if( e->button() == Qt::RightButton )
00318 {
00319 mPopupFolders.clear();
00320 mPopupFolders.reserve( mFoldersWithUnread.count() );
00321
00322
00323
00324 buildPopupMenu();
00325
00326 if(mNewMessagePopupId != -1)
00327 {
00328 mPopupMenu->removeItem(mNewMessagePopupId);
00329 }
00330
00331 if(mFoldersWithUnread.count() > 0)
00332 {
00333 KPopupMenu *newMessagesPopup = new KPopupMenu();
00334
00335 TQMap<TQGuardedPtr<KMFolder>, int>::Iterator it = mFoldersWithUnread.begin();
00336 for(uint i=0; it != mFoldersWithUnread.end(); ++i)
00337 {
00338 kdDebug(5006) << "Adding folder" << endl;
00339 mPopupFolders.append( it.key() );
00340 TQString item = prettyName(it.key()) + " (" + TQString::number(it.data()) + ")";
00341 newMessagesPopup->insertItem(item, this, TQT_SLOT(selectedAccount(int)), 0, i);
00342 ++it;
00343 }
00344
00345 mNewMessagePopupId = mPopupMenu->insertItem(i18n("New Messages In"),
00346 newMessagesPopup, mNewMessagePopupId, 3);
00347
00348 kdDebug(5006) << "Folders added" << endl;
00349 }
00350
00351 mPopupMenu->popup(e->globalPos());
00352 }
00353
00354 }
00355
00360 TQString KMSystemTray::prettyName(KMFolder * fldr)
00361 {
00362 TQString rvalue = fldr->label();
00363 if(fldr->folderType() == KMFolderTypeImap)
00364 {
00365 KMFolderImap * imap = dynamic_cast<KMFolderImap*> (fldr->storage());
00366 assert(imap);
00367
00368 if((imap->account() != 0) &&
00369 (imap->account()->name() != 0) )
00370 {
00371 kdDebug(5006) << "IMAP folder, prepend label with type" << endl;
00372 rvalue = imap->account()->name() + "->" + rvalue;
00373 }
00374 }
00375
00376 kdDebug(5006) << "Got label " << rvalue << endl;
00377
00378 return rvalue;
00379 }
00380
00381
00382 bool KMSystemTray::mainWindowIsOnCurrentDesktop()
00383 {
00384 KMMainWidget * mainWidget = kmkernel->getKMMainWidget();
00385 if ( !mainWidget )
00386 return false;
00387
00388 TQWidget *mainWin = kmkernel->getKMMainWidget()->topLevelWidget();
00389 if ( !mainWin )
00390 return false;
00391
00392 return KWin::windowInfo( mainWin->winId(),
00393 NET::WMDesktop ).isOnCurrentDesktop();
00394 }
00395
00400 void KMSystemTray::showKMail()
00401 {
00402 if (!kmkernel->getKMMainWidget())
00403 return;
00404 TQWidget *mainWin = kmkernel->getKMMainWidget()->topLevelWidget();
00405 assert(mainWin);
00406 if(mainWin)
00407 {
00408 KWin::WindowInfo cur = KWin::windowInfo( mainWin->winId(), NET::WMDesktop );
00409 if ( cur.valid() ) mDesktopOfMainWin = cur.desktop();
00410
00411 if ( mDesktopOfMainWin != NET::OnAllDesktops )
00412 KWin::setCurrentDesktop( mDesktopOfMainWin );
00413 if ( !mParentVisible ) {
00414 if ( mDesktopOfMainWin == NET::OnAllDesktops )
00415 KWin::setOnAllDesktops( mainWin->winId(), true );
00416 mainWin->move( mPosOfMainWin );
00417 mainWin->show();
00418 }
00419 KWin::activateWindow( mainWin->winId() );
00420 mParentVisible = true;
00421 }
00422 kmkernel->raise();
00423
00424
00425 foldersChanged();
00426 }
00427
00428 void KMSystemTray::hideKMail()
00429 {
00430 if (!kmkernel->getKMMainWidget())
00431 return;
00432 TQWidget *mainWin = kmkernel->getKMMainWidget()->topLevelWidget();
00433 assert(mainWin);
00434 if(mainWin)
00435 {
00436 mDesktopOfMainWin = KWin::windowInfo( mainWin->winId(),
00437 NET::WMDesktop ).desktop();
00438 mPosOfMainWin = mainWin->pos();
00439
00440 KWin::iconifyWindow( mainWin->winId() );
00441 mainWin->hide();
00442 mParentVisible = false;
00443 }
00444 }
00445
00452 void KMSystemTray::updateNewMessageNotification(KMFolder * fldr)
00453 {
00454
00455
00456 if( !fldr ||
00457 fldr->folderType() == KMFolderTypeSearch )
00458 {
00459
00460 return;
00461 }
00462
00463 mPendingUpdates[ fldr ] = true;
00464 if ( time( 0 ) - mLastUpdate > 2 ) {
00465 mUpdateTimer->stop();
00466 updateNewMessages();
00467 }
00468 else {
00469 mUpdateTimer->start(150, true);
00470 }
00471 }
00472
00473 void KMSystemTray::updateNewMessages()
00474 {
00475 for ( TQMap<TQGuardedPtr<KMFolder>, bool>::Iterator it = mPendingUpdates.begin();
00476 it != mPendingUpdates.end(); ++it)
00477 {
00478 KMFolder *fldr = it.key();
00479 if ( !fldr )
00480 continue;
00481
00483 int unread = fldr->countUnread();
00484
00485 TQMap<TQGuardedPtr<KMFolder>, int>::Iterator unread_it =
00486 mFoldersWithUnread.find(fldr);
00487 bool unmapped = (unread_it == mFoldersWithUnread.end());
00488
00491 if(unmapped) mCount += unread;
00492
00493
00494 else
00495 {
00496 int diff = unread - unread_it.data();
00497 mCount += diff;
00498 }
00499
00500 if(unread > 0)
00501 {
00503 mFoldersWithUnread.insert(fldr, unread);
00504
00505 }
00506
00512 if(unmapped)
00513 {
00515 if(unread == 0) continue;
00516
00518 if ( ( mMode == GlobalSettings::EnumSystemTrayPolicy::ShowOnUnread )
00519 && isHidden() ) {
00520 show();
00521 }
00522
00523 } else
00524 {
00525
00526 if(unread == 0)
00527 {
00528 kdDebug(5006) << "Removing folder from internal store " << fldr->name() << endl;
00529
00531 mFoldersWithUnread.remove(fldr);
00532
00534 if(mFoldersWithUnread.count() == 0)
00535 {
00536 mPopupFolders.clear();
00537 disconnect(this, TQT_SLOT(selectedAccount(int)));
00538
00539 mCount = 0;
00540
00541 if ( mMode == GlobalSettings::EnumSystemTrayPolicy::ShowOnUnread ) {
00542 hide();
00543 }
00544 }
00545 }
00546 }
00547
00548 }
00549 mPendingUpdates.clear();
00550 updateCount();
00551
00553 TQToolTip::remove(this);
00554 TQToolTip::add(this, mCount == 0 ?
00555 i18n("There are no unread messages")
00556 : i18n("There is 1 unread message.",
00557 "There are %n unread messages.",
00558 mCount));
00559
00560 mLastUpdate = time( 0 );
00561 }
00562
00568 void KMSystemTray::selectedAccount(int id)
00569 {
00570 showKMail();
00571
00572 KMMainWidget * mainWidget = kmkernel->getKMMainWidget();
00573 if (!mainWidget)
00574 {
00575 kmkernel->openReader();
00576 mainWidget = kmkernel->getKMMainWidget();
00577 }
00578
00579 assert(mainWidget);
00580
00582 KMFolder * fldr = mPopupFolders.at(id);
00583 if(!fldr) return;
00584 KMFolderTree * ft = mainWidget->folderTree();
00585 if(!ft) return;
00586 TQListViewItem * fldrIdx = ft->indexOfFolder(fldr);
00587 if(!fldrIdx) return;
00588
00589 ft->setCurrentItem(fldrIdx);
00590 ft->selectCurrentFolder();
00591 }
00592
00593 bool KMSystemTray::hasUnreadMail() const
00594 {
00595 return ( mCount != 0 );
00596 }
00597
00598 #include "kmsystemtray.moc"