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 <tdeapplication.h>
00032 #include <tdemainwindow.h>
00033 #include <tdeglobalsettings.h>
00034 #include <kiconloader.h>
00035 #include <kiconeffect.h>
00036 #include <twin.h>
00037 #include <kdebug.h>
00038 #include <tdepopupmenu.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 TDEPopupMenu();
00115 KMMainWidget * mainWidget = kmkernel->getKMMainWidget();
00116 if ( !mainWidget )
00117 return;
00118
00119 mPopupMenu->insertTitle(*(this->pixmap()), "KMail");
00120 TDEAction * 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 mPopupMenu->insertItem( SmallIcon("system-log-out"), i18n("&Quit"), this, TQT_SLOT(maybeQuit()) );
00137 }
00138
00139 void KMSystemTray::tray_quit()
00140 {
00141
00142 kapp->quit();
00143 }
00144
00145 KMSystemTray::~KMSystemTray()
00146 {
00147
00148 kmkernel->unregisterSystemTrayApplet( this );
00149
00150 delete mPopupMenu;
00151 mPopupMenu = 0;
00152 }
00153
00154 void KMSystemTray::setMode(int newMode)
00155 {
00156 if(newMode == mMode) return;
00157
00158 kdDebug(5006) << "Setting systray mMode to " << newMode << endl;
00159 mMode = newMode;
00160
00161 switch ( mMode ) {
00162 case GlobalSettings::EnumSystemTrayPolicy::ShowAlways:
00163 if ( isHidden() )
00164 show();
00165 break;
00166 case GlobalSettings::EnumSystemTrayPolicy::ShowOnUnread:
00167 if ( mCount == 0 && !isHidden() )
00168 hide();
00169 else if ( mCount > 0 && isHidden() )
00170 show();
00171 break;
00172 default:
00173 kdDebug(5006) << k_funcinfo << " Unknown systray mode " << mMode << endl;
00174 }
00175 }
00176
00177 int KMSystemTray::mode() const
00178 {
00179 return mMode;
00180 }
00181
00182 void KMSystemTray::resizeEvent(TQResizeEvent *)
00183 {
00184 updateCount();
00185 }
00186
00192 void KMSystemTray::updateCount()
00193 {
00194 if(mCount != 0)
00195 {
00196 int oldPixmapWidth = pixmap()->size().width();
00197 int oldPixmapHeight = pixmap()->size().height();
00198
00199 TQString countString = TQString::number( mCount );
00200 TQFont countFont = TDEGlobalSettings::generalFont();
00201 countFont.setBold(true);
00202
00203
00204
00205
00206 int realIconHeight = height();
00207 if (realIconHeight < 22) {
00208 countFont.setPointSizeFloat( countFont.pointSizeFloat() * 2.0 );
00209 }
00210
00211
00212
00213 float countFontSize = countFont.pointSizeFloat();
00214 TQFontMetrics qfm( countFont );
00215 int width = qfm.width( countString );
00216 if( width > oldPixmapWidth )
00217 {
00218 countFontSize *= float( oldPixmapWidth ) / float( width );
00219 countFont.setPointSizeFloat( countFontSize );
00220 }
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239 TQPixmap numberPixmap( oldPixmapWidth, oldPixmapHeight );
00240 numberPixmap.fill( TQt::white );
00241 TQPainter p( &numberPixmap );
00242 p.setFont( countFont );
00243 p.setPen( TQt::blue );
00244 p.drawText( numberPixmap.rect(), TQt::AlignCenter, countString );
00245 numberPixmap.setMask( numberPixmap.createHeuristicMask() );
00246 TQImage numberImage = numberPixmap.convertToImage();
00247
00248
00249 TQImage iconWithNumberImage = mLightIconImage.copy();
00250 TDEIconEffect::overlay( iconWithNumberImage, numberImage );
00251
00252 TQPixmap iconWithNumber;
00253 iconWithNumber.convertFromImage( iconWithNumberImage );
00254 setPixmap( iconWithNumber );
00255 } else
00256 {
00257 setPixmap( mDefaultIcon );
00258 }
00259 }
00260
00265 void KMSystemTray::foldersChanged()
00266 {
00271 mFoldersWithUnread.clear();
00272 mCount = 0;
00273
00274 if ( mMode == GlobalSettings::EnumSystemTrayPolicy::ShowOnUnread ) {
00275 hide();
00276 }
00277
00279 disconnect(this, TQT_SLOT(updateNewMessageNotification(KMFolder *)));
00280
00281 TQStringList folderNames;
00282 TQValueList<TQGuardedPtr<KMFolder> > folderList;
00283 kmkernel->folderMgr()->createFolderList(&folderNames, &folderList);
00284 kmkernel->imapFolderMgr()->createFolderList(&folderNames, &folderList);
00285 kmkernel->dimapFolderMgr()->createFolderList(&folderNames, &folderList);
00286 kmkernel->searchFolderMgr()->createFolderList(&folderNames, &folderList);
00287
00288 TQStringList::iterator strIt = folderNames.begin();
00289
00290 for(TQValueList<TQGuardedPtr<KMFolder> >::iterator it = folderList.begin();
00291 it != folderList.end() && strIt != folderNames.end(); ++it, ++strIt)
00292 {
00293 KMFolder * currentFolder = *it;
00294 TQString currentName = *strIt;
00295
00296 if ( ((!currentFolder->isSystemFolder() || (currentFolder->name().lower() == "inbox")) ||
00297 (currentFolder->folderType() == KMFolderTypeImap)) &&
00298 !currentFolder->ignoreNewMail() )
00299 {
00301 connect(currentFolder, TQT_SIGNAL(numUnreadMsgsChanged(KMFolder *)),
00302 this, TQT_SLOT(updateNewMessageNotification(KMFolder *)));
00303
00305 updateNewMessageNotification(currentFolder);
00306 }
00307 else {
00308 disconnect(currentFolder, TQT_SIGNAL(numUnreadMsgsChanged(KMFolder *)), this, TQT_SLOT(updateNewMessageNotification(KMFolder *)) );
00309 }
00310 }
00311 }
00312
00317 void KMSystemTray::mousePressEvent(TQMouseEvent *e)
00318 {
00319
00320 if( e->button() == Qt::LeftButton )
00321 {
00322 if( mParentVisible && mainWindowIsOnCurrentDesktop() )
00323 hideKMail();
00324 else
00325 showKMail();
00326 }
00327
00328
00329 if( e->button() == Qt::RightButton )
00330 {
00331 mPopupFolders.clear();
00332 mPopupFolders.reserve( mFoldersWithUnread.count() );
00333
00334
00335
00336 buildPopupMenu();
00337
00338 if(mNewMessagePopupId != -1)
00339 {
00340 mPopupMenu->removeItem(mNewMessagePopupId);
00341 }
00342
00343 if(mFoldersWithUnread.count() > 0)
00344 {
00345 TDEPopupMenu *newMessagesPopup = new TDEPopupMenu();
00346
00347 TQMap<TQGuardedPtr<KMFolder>, int>::Iterator it = mFoldersWithUnread.begin();
00348 for(uint i=0; it != mFoldersWithUnread.end(); ++i)
00349 {
00350 kdDebug(5006) << "Adding folder" << endl;
00351 mPopupFolders.append( it.key() );
00352 TQString item = prettyName(it.key()) + " (" + TQString::number(it.data()) + ")";
00353 newMessagesPopup->insertItem(item, this, TQT_SLOT(selectedAccount(int)), 0, i);
00354 ++it;
00355 }
00356
00357 mNewMessagePopupId = mPopupMenu->insertItem(i18n("New Messages In"),
00358 newMessagesPopup, mNewMessagePopupId, 3);
00359
00360 kdDebug(5006) << "Folders added" << endl;
00361 }
00362
00363 mPopupMenu->popup(e->globalPos());
00364 }
00365
00366 }
00367
00372 TQString KMSystemTray::prettyName(KMFolder * fldr)
00373 {
00374 TQString rvalue = fldr->label();
00375 if(fldr->folderType() == KMFolderTypeImap)
00376 {
00377 KMFolderImap * imap = dynamic_cast<KMFolderImap*> (fldr->storage());
00378 assert(imap);
00379
00380 if((imap->account() != 0) &&
00381 (imap->account()->name() != 0) )
00382 {
00383 kdDebug(5006) << "IMAP folder, prepend label with type" << endl;
00384 rvalue = imap->account()->name() + "->" + rvalue;
00385 }
00386 }
00387
00388 kdDebug(5006) << "Got label " << rvalue << endl;
00389
00390 return rvalue;
00391 }
00392
00393
00394 bool KMSystemTray::mainWindowIsOnCurrentDesktop()
00395 {
00396 KMMainWidget * mainWidget = kmkernel->getKMMainWidget();
00397 if ( !mainWidget )
00398 return false;
00399
00400 TQWidget *mainWin = kmkernel->getKMMainWidget()->topLevelWidget();
00401 if ( !mainWin )
00402 return false;
00403
00404 return KWin::windowInfo( mainWin->winId(),
00405 NET::WMDesktop ).isOnCurrentDesktop();
00406 }
00407
00412 void KMSystemTray::showKMail()
00413 {
00414 if (!kmkernel->getKMMainWidget())
00415 return;
00416 TQWidget *mainWin = kmkernel->getKMMainWidget()->topLevelWidget();
00417 assert(mainWin);
00418 if(mainWin)
00419 {
00420 KWin::WindowInfo cur = KWin::windowInfo( mainWin->winId(), NET::WMDesktop );
00421 if ( cur.valid() ) mDesktopOfMainWin = cur.desktop();
00422
00423 if ( mDesktopOfMainWin != NET::OnAllDesktops )
00424 KWin::setCurrentDesktop( mDesktopOfMainWin );
00425 if ( !mParentVisible ) {
00426 if ( mDesktopOfMainWin == NET::OnAllDesktops )
00427 KWin::setOnAllDesktops( mainWin->winId(), true );
00428 mainWin->move( mPosOfMainWin );
00429 mainWin->show();
00430 }
00431 KWin::activateWindow( mainWin->winId() );
00432 mParentVisible = true;
00433 }
00434 kmkernel->raise();
00435
00436
00437 foldersChanged();
00438 }
00439
00440 void KMSystemTray::hideKMail()
00441 {
00442 if (!kmkernel->getKMMainWidget())
00443 return;
00444 TQWidget *mainWin = kmkernel->getKMMainWidget()->topLevelWidget();
00445 assert(mainWin);
00446 if(mainWin)
00447 {
00448 mDesktopOfMainWin = KWin::windowInfo( mainWin->winId(),
00449 NET::WMDesktop ).desktop();
00450 mPosOfMainWin = mainWin->pos();
00451
00452 KWin::iconifyWindow( mainWin->winId() );
00453 mainWin->hide();
00454 mParentVisible = false;
00455 }
00456 }
00457
00464 void KMSystemTray::updateNewMessageNotification(KMFolder * fldr)
00465 {
00466
00467
00468 if( !fldr ||
00469 fldr->folderType() == KMFolderTypeSearch )
00470 {
00471
00472 return;
00473 }
00474
00475 mPendingUpdates[ fldr ] = true;
00476 if ( time( 0 ) - mLastUpdate > 2 ) {
00477 mUpdateTimer->stop();
00478 updateNewMessages();
00479 }
00480 else {
00481 mUpdateTimer->start(150, true);
00482 }
00483 }
00484
00485 void KMSystemTray::updateNewMessages()
00486 {
00487 for ( TQMap<TQGuardedPtr<KMFolder>, bool>::Iterator it = mPendingUpdates.begin();
00488 it != mPendingUpdates.end(); ++it)
00489 {
00490 KMFolder *fldr = it.key();
00491 if ( !fldr )
00492 continue;
00493
00495 int unread = fldr->countUnread();
00496
00497 TQMap<TQGuardedPtr<KMFolder>, int>::Iterator unread_it =
00498 mFoldersWithUnread.find(fldr);
00499 bool unmapped = (unread_it == mFoldersWithUnread.end());
00500
00503 if(unmapped) mCount += unread;
00504
00505
00506 else
00507 {
00508 int diff = unread - unread_it.data();
00509 mCount += diff;
00510 }
00511
00512 if(unread > 0)
00513 {
00515 mFoldersWithUnread.insert(fldr, unread);
00516
00517 }
00518
00524 if(unmapped)
00525 {
00527 if(unread == 0) continue;
00528
00530 if ( ( mMode == GlobalSettings::EnumSystemTrayPolicy::ShowOnUnread )
00531 && isHidden() ) {
00532 show();
00533 }
00534
00535 } else
00536 {
00537
00538 if(unread == 0)
00539 {
00540 kdDebug(5006) << "Removing folder from internal store " << fldr->name() << endl;
00541
00543 mFoldersWithUnread.remove(fldr);
00544
00546 if(mFoldersWithUnread.count() == 0)
00547 {
00548 mPopupFolders.clear();
00549 disconnect(this, TQT_SLOT(selectedAccount(int)));
00550
00551 mCount = 0;
00552
00553 if ( mMode == GlobalSettings::EnumSystemTrayPolicy::ShowOnUnread ) {
00554 hide();
00555 }
00556 }
00557 }
00558 }
00559
00560 }
00561 mPendingUpdates.clear();
00562 updateCount();
00563
00565 TQToolTip::remove(this);
00566 TQToolTip::add(this, mCount == 0 ?
00567 i18n("There are no unread messages")
00568 : i18n("There is 1 unread message.",
00569 "There are %n unread messages.",
00570 mCount));
00571
00572 mLastUpdate = time( 0 );
00573 }
00574
00580 void KMSystemTray::selectedAccount(int id)
00581 {
00582 showKMail();
00583
00584 KMMainWidget * mainWidget = kmkernel->getKMMainWidget();
00585 if (!mainWidget)
00586 {
00587 kmkernel->openReader();
00588 mainWidget = kmkernel->getKMMainWidget();
00589 }
00590
00591 assert(mainWidget);
00592
00594 KMFolder * fldr = mPopupFolders.at(id);
00595 if(!fldr) return;
00596 KMFolderTree * ft = mainWidget->folderTree();
00597 if(!ft) return;
00598 TQListViewItem * fldrIdx = ft->indexOfFolder(fldr);
00599 if(!fldrIdx) return;
00600
00601 ft->setCurrentItem(fldrIdx);
00602 ft->selectCurrentFolder();
00603 }
00604
00605 bool KMSystemTray::hasUnreadMail() const
00606 {
00607 return ( mCount != 0 );
00608 }
00609
00610 #include "kmsystemtray.moc"