00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifdef HAVE_CONFIG_H
00020 #include <config.h>
00021 #endif
00022
00023 #include "kmsystemtray.h"
00024 #include "kmfoldertree.h"
00025 #include "kmfoldermgr.h"
00026 #include "kmfolderimap.h"
00027 #include "kmmainwidget.h"
00028
00029 #include <kapplication.h>
00030 #include <kglobalsettings.h>
00031 #include <kiconloader.h>
00032 #include <kiconeffect.h>
00033 #include <kwin.h>
00034 #include <kdebug.h>
00035
00036 #include <qpainter.h>
00037 #include <qbitmap.h>
00038 #include <qtooltip.h>
00039 #include <qwidgetlist.h>
00040 #include <qobjectlist.h>
00041
00042 #include <math.h>
00043 #include <assert.h>
00044
00056 KMSystemTray::KMSystemTray(QWidget *parent, const char *name)
00057 : KSystemTray( parent, name ),
00058 mParentVisible( true ),
00059 mPosOfMainWin( 0, 0 ),
00060 mDesktopOfMainWin( 0 ),
00061 mMode( OnNewMail ),
00062 mCount( 0 ),
00063 mNewMessagePopupId(-1),
00064 mPopupMenu(0)
00065 {
00066 setAlignment( AlignCenter );
00067 kdDebug(5006) << "Initting systray" << endl;
00068
00069 #if KDE_IS_VERSION( 3, 1,92 )
00070 mDefaultIcon = loadIcon( "kmail" );
00071 mLightIconImage = loadIcon( "kmaillight" ).convertToImage();
00072 #else
00073 mDefaultIcon = SmallIcon( "kmail" );
00074 mLightIconImage = SmallIcon( "kmaillight" ).convertToImage();
00075 #endif
00076
00077 setPixmap(mDefaultIcon);
00078
00079 KMMainWidget * mainWidget = getKMMainWidget();
00080 if ( mainWidget ) {
00081 QWidget * mainWin = mainWidget->topLevelWidget();
00082 if ( mainWin ) {
00083 mDesktopOfMainWin = KWin::windowInfo( mainWin->winId(),
00084 NET::WMDesktop ).desktop();
00085 mPosOfMainWin = mainWin->pos();
00086 }
00087 }
00088
00089
00090 kmkernel->registerSystemTrayApplet( this );
00091
00093 foldersChanged();
00094
00095 connect( kmkernel->folderMgr(), SIGNAL(changed()), SLOT(foldersChanged()));
00096 connect( kmkernel->imapFolderMgr(), SIGNAL(changed()), SLOT(foldersChanged()));
00097 connect( kmkernel->dimapFolderMgr(), SIGNAL(changed()), SLOT(foldersChanged()));
00098 connect( kmkernel->searchFolderMgr(), SIGNAL(changed()), SLOT(foldersChanged()));
00099 }
00100
00101 void KMSystemTray::buildPopupMenu()
00102 {
00103
00104 delete mPopupMenu;
00105 mPopupMenu = 0;
00106
00107 mPopupMenu = new KPopupMenu();
00108 KMMainWidget * mainWidget = getKMMainWidget();
00109 if ( !mainWidget )
00110 return;
00111
00112 mPopupMenu->insertTitle(*(this->pixmap()), "KMail");
00113 KAction * action;
00114 if ( ( action = mainWidget->action("check_mail") ) )
00115 action->plug( mPopupMenu );
00116 if ( ( action = mainWidget->action("check_mail_in") ) )
00117 action->plug( mPopupMenu );
00118 mPopupMenu->insertSeparator();
00119 if ( ( action = mainWidget->action("new_message") ) )
00120 action->plug( mPopupMenu );
00121 if ( ( action = mainWidget->action("kmail_configure_kmail") ) )
00122 action->plug( mPopupMenu );
00123 mPopupMenu->insertSeparator();
00124 if ( ( action = mainWidget->action("file_quit") ) )
00125 action->plug( mPopupMenu );
00126 }
00127
00128 KMSystemTray::~KMSystemTray()
00129 {
00130
00131 kmkernel->unregisterSystemTrayApplet( this );
00132
00133 delete mPopupMenu;
00134 mPopupMenu = 0;
00135 }
00136
00137 void KMSystemTray::setMode(int newMode)
00138 {
00139 if(newMode == mMode) return;
00140
00141 kdDebug(5006) << "Setting systray mMode to " << newMode << endl;
00142 mMode = newMode;
00143
00144 if(mMode == AlwaysOn)
00145 {
00146 kdDebug(5006) << "Initting alwayson mMode" << endl;
00147
00148 if(isHidden()) show();
00149 } else
00150 {
00151 if(mCount == 0)
00152 {
00153 hide();
00154 }
00155 }
00156 }
00157
00163 void KMSystemTray::updateCount()
00164 {
00165 if(mCount != 0)
00166 {
00167 int oldPixmapWidth = pixmap()->size().width();
00168 int oldPixmapHeight = pixmap()->size().height();
00169
00170 QString countString = QString::number( mCount );
00171 QFont countFont = KGlobalSettings::generalFont();
00172 countFont.setBold(true);
00173
00174
00175
00176 float countFontSize = countFont.pointSizeFloat();
00177 QFontMetrics qfm( countFont );
00178 int width = qfm.width( countString );
00179 if( width > oldPixmapWidth )
00180 {
00181 countFontSize *= float( oldPixmapWidth ) / float( width );
00182 countFont.setPointSizeFloat( countFontSize );
00183 }
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202 QPixmap numberPixmap( oldPixmapWidth, oldPixmapHeight );
00203 numberPixmap.fill( Qt::white );
00204 QPainter p( &numberPixmap );
00205 p.setFont( countFont );
00206 p.setPen( Qt::blue );
00207 p.drawText( numberPixmap.rect(), Qt::AlignCenter, countString );
00208 numberPixmap.setMask( numberPixmap.createHeuristicMask() );
00209 QImage numberImage = numberPixmap.convertToImage();
00210
00211
00212 QImage iconWithNumberImage = mLightIconImage.copy();
00213 KIconEffect::overlay( iconWithNumberImage, numberImage );
00214
00215 QPixmap iconWithNumber;
00216 iconWithNumber.convertFromImage( iconWithNumberImage );
00217 setPixmap( iconWithNumber );
00218 } else
00219 {
00220 setPixmap( mDefaultIcon );
00221 }
00222 }
00223
00228 void KMSystemTray::foldersChanged()
00229 {
00234 mFoldersWithUnread.clear();
00235 mCount = 0;
00236
00237 if(mMode == OnNewMail)
00238 {
00239 hide();
00240 }
00241
00243 disconnect(this, SLOT(updateNewMessageNotification(KMFolder *)));
00244
00245 QStringList folderNames;
00246 QValueList<QGuardedPtr<KMFolder> > folderList;
00247 kmkernel->folderMgr()->createFolderList(&folderNames, &folderList);
00248 kmkernel->imapFolderMgr()->createFolderList(&folderNames, &folderList);
00249 kmkernel->dimapFolderMgr()->createFolderList(&folderNames, &folderList);
00250 kmkernel->searchFolderMgr()->createFolderList(&folderNames, &folderList);
00251
00252 QStringList::iterator strIt = folderNames.begin();
00253
00254 for(QValueList<QGuardedPtr<KMFolder> >::iterator it = folderList.begin();
00255 it != folderList.end() && strIt != folderNames.end(); ++it, ++strIt)
00256 {
00257 KMFolder * currentFolder = *it;
00258 QString currentName = *strIt;
00259
00260 if((!currentFolder->isSystemFolder() || (currentFolder->name().lower() == "inbox")) ||
00261 (currentFolder->folderType() == KMFolderTypeImap))
00262 {
00264 connect(currentFolder, SIGNAL(numUnreadMsgsChanged(KMFolder *)),
00265 this, SLOT(updateNewMessageNotification(KMFolder *)));
00266
00268 updateNewMessageNotification(currentFolder);
00269 }
00270 }
00271 }
00272
00277 void KMSystemTray::mousePressEvent(QMouseEvent *e)
00278 {
00279
00280 if( e->button() == LeftButton )
00281 {
00282 if( mParentVisible && mainWindowIsOnCurrentDesktop() )
00283 hideKMail();
00284 else
00285 showKMail();
00286 }
00287
00288
00289 if( e->button() == RightButton )
00290 {
00291 mPopupFolders.clear();
00292 mPopupFolders.resize(mFoldersWithUnread.count());
00293
00294
00295
00296 buildPopupMenu();
00297
00298 if(mNewMessagePopupId != -1)
00299 {
00300 mPopupMenu->removeItem(mNewMessagePopupId);
00301 }
00302
00303 if(mFoldersWithUnread.count() > 0)
00304 {
00305 KPopupMenu *newMessagesPopup = new KPopupMenu();
00306
00307 QMap<QGuardedPtr<KMFolder>, int>::Iterator it = mFoldersWithUnread.begin();
00308 for(uint i=0; it != mFoldersWithUnread.end(); ++i)
00309 {
00310 kdDebug(5006) << "Adding folder" << endl;
00311 if(i > mPopupFolders.size()) mPopupFolders.resize(i * 2);
00312 mPopupFolders.insert(i, it.key());
00313 QString item = prettyName(it.key()) + "(" + QString::number(it.data()) + ")";
00314 newMessagesPopup->insertItem(item, this, SLOT(selectedAccount(int)), 0, i);
00315 ++it;
00316 }
00317
00318 mNewMessagePopupId = mPopupMenu->insertItem(i18n("New Messages In..."),
00319 newMessagesPopup, mNewMessagePopupId, 3);
00320
00321 kdDebug(5006) << "Folders added" << endl;
00322 }
00323
00324 mPopupMenu->popup(e->globalPos());
00325 }
00326
00327 }
00328
00333 QString KMSystemTray::prettyName(KMFolder * fldr)
00334 {
00335 QString rvalue = fldr->label();
00336 if(fldr->folderType() == KMFolderTypeImap)
00337 {
00338 KMFolderImap * imap = dynamic_cast<KMFolderImap*> (fldr);
00339 assert(imap);
00340
00341 if((imap->account() != 0) &&
00342 (imap->account()->name() != 0) )
00343 {
00344 kdDebug(5006) << "IMAP folder, prepend label with type" << endl;
00345 rvalue = imap->account()->name() + "->" + rvalue;
00346 }
00347 }
00348
00349 kdDebug(5006) << "Got label " << rvalue << endl;
00350
00351 return rvalue;
00352 }
00353
00354
00355 bool KMSystemTray::mainWindowIsOnCurrentDesktop()
00356 {
00357 KMMainWidget * mainWidget = getKMMainWidget();
00358 if ( !mainWidget )
00359 return false;
00360
00361 QWidget *mainWin = getKMMainWidget()->topLevelWidget();
00362 if ( !mainWin )
00363 return false;
00364
00365 return KWin::windowInfo( mainWin->winId(),
00366 NET::WMDesktop ).isOnCurrentDesktop();
00367 }
00368
00373 void KMSystemTray::showKMail()
00374 {
00375 if (!getKMMainWidget())
00376 return;
00377 QWidget *mainWin = getKMMainWidget()->topLevelWidget();
00378 assert(mainWin);
00379 if(mainWin)
00380 {
00381
00382 if ( mDesktopOfMainWin != NET::OnAllDesktops )
00383 KWin::setCurrentDesktop( mDesktopOfMainWin );
00384 if ( !mParentVisible ) {
00385 if ( mDesktopOfMainWin == NET::OnAllDesktops )
00386 KWin::setOnAllDesktops( mainWin->winId(), true );
00387 mainWin->move( mPosOfMainWin );
00388 mainWin->show();
00389 }
00390 KWin::activateWindow( mainWin->winId() );
00391 mParentVisible = true;
00392 }
00393 }
00394
00395 void KMSystemTray::hideKMail()
00396 {
00397 if (!getKMMainWidget())
00398 return;
00399 QWidget *mainWin = getKMMainWidget()->topLevelWidget();
00400 assert(mainWin);
00401 if(mainWin)
00402 {
00403 mDesktopOfMainWin = KWin::windowInfo( mainWin->winId(),
00404 NET::WMDesktop ).desktop();
00405 mPosOfMainWin = mainWin->pos();
00406
00407 KWin::iconifyWindow( mainWin->winId() );
00408 mainWin->hide();
00409 mParentVisible = false;
00410 }
00411 }
00412
00416 KMMainWidget * KMSystemTray::getKMMainWidget()
00417 {
00418 QWidgetList *l = kapp->topLevelWidgets();
00419 QWidgetListIt it( *l );
00420 QWidget *wid;
00421
00422 while ( (wid = it.current()) != 0 ) {
00423 ++it;
00424 QObjectList *l2 = wid->topLevelWidget()->queryList("KMMainWidget");
00425 if (l2 && l2->first())
00426 {
00427 KMMainWidget* kmmw = dynamic_cast<KMMainWidget *>(l2->first());
00428 assert (kmmw);
00429 delete l2;
00430 delete l;
00431 return kmmw;
00432 }
00433 delete l2;
00434 }
00435 delete l;
00436 return 0;
00437 }
00438
00445 void KMSystemTray::updateNewMessageNotification(KMFolder * fldr)
00446 {
00447
00448
00449 if( !fldr ||
00450 fldr->folderType() == KMFolderTypeSearch )
00451 {
00452 kdDebug(5006) << "Null or a search folder, can't mess with that" << endl;
00453 return;
00454 }
00455
00457 int unread = fldr->countUnread();
00458
00459 QMap<QGuardedPtr<KMFolder>, int>::Iterator it =
00460 mFoldersWithUnread.find(fldr);
00461 bool unmapped = (it == mFoldersWithUnread.end());
00462
00465 if(unmapped) mCount += unread;
00466
00467
00468 else
00469 {
00470 int diff = unread - it.data();
00471 mCount += diff;
00472 }
00473
00474 if(unread > 0)
00475 {
00477 mFoldersWithUnread.insert(fldr, unread);
00478 kdDebug(5006) << "There are now " << mFoldersWithUnread.count() << " folders with unread" << endl;
00479 }
00480
00486 if(unmapped)
00487 {
00489 if(unread == 0) return;
00490
00492 if(mMode == OnNewMail)
00493 {
00494 if(isHidden()) show();
00495 }
00496
00497 } else
00498 {
00499
00500 if(unread == 0)
00501 {
00502 kdDebug(5006) << "Removing folder from internal store " << fldr->name() << endl;
00503
00505 mFoldersWithUnread.remove(fldr);
00506
00508 if(mFoldersWithUnread.count() == 0)
00509 {
00510 mPopupFolders.clear();
00511 disconnect(this, SLOT(selectedAccount(int)));
00512
00513 mCount = 0;
00514
00515 if(mMode == OnNewMail)
00516 hide();
00517 }
00518 }
00519 }
00520
00521 updateCount();
00522
00524 QToolTip::remove(this);
00525 QToolTip::add(this, i18n("There is 1 unread message.",
00526 "There are %n unread messages.",
00527 mCount));
00528 }
00529
00535 void KMSystemTray::selectedAccount(int id)
00536 {
00537 showKMail();
00538
00539 KMMainWidget * mainWidget = getKMMainWidget();
00540 if (!mainWidget)
00541 {
00542 kmkernel->openReader();
00543 mainWidget = getKMMainWidget();
00544 }
00545
00546 assert(mainWidget);
00547
00549 KMFolder * fldr = mPopupFolders.at(id);
00550 if(!fldr) return;
00551 KMFolderTree * ft = mainWidget->folderTree();
00552 if(!ft) return;
00553 QListViewItem * fldrIdx = ft->indexOfFolder(fldr);
00554 if(!fldrIdx) return;
00555
00556 ft->setCurrentItem(fldrIdx);
00557 ft->selectCurrentFolder();
00558 }
00559
00560
00561 #include "kmsystemtray.moc"