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 "kmfoldertree.h"
00023
#include "kmfoldermgr.h"
00024
#include "kmfolderimap.h"
00025
#include "kmmainwidget.h"
00026
#include "kmacctmgr.h"
00027
#include "globalsettings.h"
00028
00029
#include <kapplication.h>
00030
#include <kmainwindow.h>
00031
#include <kglobalsettings.h>
00032
#include <kiconloader.h>
00033
#include <kiconeffect.h>
00034
#include <kwin.h>
00035
#include <kdebug.h>
00036
00037
#include <qpainter.h>
00038
#include <qbitmap.h>
00039
#include <qtooltip.h>
00040
#include <qwidgetlist.h>
00041
#include <qobjectlist.h>
00042
00043
#include <math.h>
00044
#include <assert.h>
00045
00057 KMSystemTray::KMSystemTray(
QWidget *parent,
const char *name)
00058 : KSystemTray( parent, name ),
00059 mParentVisible( true ),
00060 mPosOfMainWin( 0, 0 ),
00061 mDesktopOfMainWin( 0 ),
00062 mMode( GlobalSettings::EnumSystemTrayPolicy::ShowOnUnread ),
00063 mCount( 0 ),
00064 mNewMessagePopupId(-1),
00065 mPopupMenu(0)
00066 {
00067 setAlignment( AlignCenter );
00068 kdDebug(5006) <<
"Initting systray" << endl;
00069
00070 mLastUpdate = time( 0 );
00071 mUpdateTimer =
new QTimer(
this,
"systraytimer" );
00072 connect( mUpdateTimer, SIGNAL( timeout() ), SLOT( updateNewMessages() ) );
00073
00074 mDefaultIcon = loadIcon(
"kmail" );
00075 mLightIconImage = loadIcon(
"kmaillight" ).convertToImage();
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 connect( kmkernel->acctMgr(), SIGNAL( checkedMail(
bool,
bool,
const QMap<QString, int> & ) ),
00101 SLOT( updateNewMessages() ) );
00102 }
00103
00104
void KMSystemTray::buildPopupMenu()
00105 {
00106
00107
delete mPopupMenu;
00108 mPopupMenu = 0;
00109
00110 mPopupMenu =
new KPopupMenu();
00111 KMMainWidget * mainWidget =
getKMMainWidget();
00112
if ( !mainWidget )
00113
return;
00114
00115 mPopupMenu->insertTitle(*(this->pixmap()),
"KMail");
00116 KAction * action;
00117
if ( ( action = mainWidget->action(
"check_mail") ) )
00118 action->plug( mPopupMenu );
00119
if ( ( action = mainWidget->action(
"check_mail_in") ) )
00120 action->plug( mPopupMenu );
00121 mPopupMenu->insertSeparator();
00122
if ( ( action = mainWidget->action(
"new_message") ) )
00123 action->plug( mPopupMenu );
00124
if ( ( action = mainWidget->action(
"kmail_configure_kmail") ) )
00125 action->plug( mPopupMenu );
00126 mPopupMenu->insertSeparator();
00127
00128 KMainWindow *mainWin = ::qt_cast<KMainWindow*>(
getKMMainWidget()->topLevelWidget());
00129
if(mainWin)
00130
if ( ( action=mainWin->actionCollection()->action(
"file_quit") ) )
00131 action->plug( mPopupMenu );
00132 }
00133
00134 KMSystemTray::~KMSystemTray()
00135 {
00136
00137 kmkernel->unregisterSystemTrayApplet(
this );
00138
00139
delete mPopupMenu;
00140 mPopupMenu = 0;
00141 }
00142
00143
void KMSystemTray::setMode(
int newMode)
00144 {
00145
if(newMode == mMode)
return;
00146
00147 kdDebug(5006) <<
"Setting systray mMode to " << newMode << endl;
00148 mMode = newMode;
00149
00150
switch ( mMode ) {
00151
case GlobalSettings::EnumSystemTrayPolicy::ShowAlways:
00152
if ( isHidden() )
00153 show();
00154
break;
00155
case GlobalSettings::EnumSystemTrayPolicy::ShowOnUnread:
00156
if ( mCount == 0 && !isHidden() )
00157 hide();
00158
else if ( mCount > 0 && isHidden() )
00159 show();
00160
default:
00161 kdDebug(5006) << k_funcinfo <<
" Unknown systray mode " << mMode << endl;
00162 }
00163 }
00164
00165
int KMSystemTray::mode()
const
00166
{
00167
return mMode;
00168 }
00169
00175 void KMSystemTray::updateCount()
00176 {
00177
if(mCount != 0)
00178 {
00179
int oldPixmapWidth = pixmap()->size().width();
00180
int oldPixmapHeight = pixmap()->size().height();
00181
00182
QString countString = QString::number( mCount );
00183
QFont countFont = KGlobalSettings::generalFont();
00184 countFont.setBold(
true);
00185
00186
00187
00188
float countFontSize = countFont.pointSizeFloat();
00189
QFontMetrics qfm( countFont );
00190
int width = qfm.width( countString );
00191
if( width > oldPixmapWidth )
00192 {
00193 countFontSize *= float( oldPixmapWidth ) / float( width );
00194 countFont.setPointSizeFloat( countFontSize );
00195 }
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
QPixmap numberPixmap( oldPixmapWidth, oldPixmapHeight );
00215 numberPixmap.fill( Qt::white );
00216
QPainter p( &numberPixmap );
00217 p.setFont( countFont );
00218 p.setPen( Qt::blue );
00219 p.drawText( numberPixmap.rect(), Qt::AlignCenter, countString );
00220 numberPixmap.setMask( numberPixmap.createHeuristicMask() );
00221
QImage numberImage = numberPixmap.convertToImage();
00222
00223
00224
QImage iconWithNumberImage = mLightIconImage.copy();
00225 KIconEffect::overlay( iconWithNumberImage, numberImage );
00226
00227
QPixmap iconWithNumber;
00228 iconWithNumber.convertFromImage( iconWithNumberImage );
00229 setPixmap( iconWithNumber );
00230 }
else
00231 {
00232 setPixmap( mDefaultIcon );
00233 }
00234 }
00235
00240
void KMSystemTray::foldersChanged()
00241 {
00246 mFoldersWithUnread.clear();
00247 mCount = 0;
00248
00249
if ( mMode == GlobalSettings::EnumSystemTrayPolicy::ShowOnUnread ) {
00250 hide();
00251 }
00252
00254 disconnect(
this, SLOT(updateNewMessageNotification(
KMFolder *)));
00255
00256
QStringList folderNames;
00257
QValueList<QGuardedPtr<KMFolder> > folderList;
00258 kmkernel->folderMgr()->createFolderList(&folderNames, &folderList);
00259 kmkernel->imapFolderMgr()->createFolderList(&folderNames, &folderList);
00260 kmkernel->dimapFolderMgr()->createFolderList(&folderNames, &folderList);
00261 kmkernel->searchFolderMgr()->createFolderList(&folderNames, &folderList);
00262
00263 QStringList::iterator strIt = folderNames.begin();
00264
00265
for(
QValueList<QGuardedPtr<KMFolder> >::iterator it = folderList.begin();
00266 it != folderList.end() && strIt != folderNames.end(); ++it, ++strIt)
00267 {
00268
KMFolder * currentFolder = *it;
00269
QString currentName = *strIt;
00270
00271
if ( ((!currentFolder->
isSystemFolder() || (currentFolder->name().lower() ==
"inbox")) ||
00272 (currentFolder->
folderType() == KMFolderTypeImap)) &&
00273 !currentFolder->
ignoreNewMail() )
00274 {
00276 connect(currentFolder, SIGNAL(numUnreadMsgsChanged(
KMFolder *)),
00277
this, SLOT(updateNewMessageNotification(
KMFolder *)));
00278
00280 updateNewMessageNotification(currentFolder);
00281 }
00282 }
00283 }
00284
00289 void KMSystemTray::mousePressEvent(
QMouseEvent *e)
00290 {
00291
00292
if( e->button() == LeftButton )
00293 {
00294
if( mParentVisible && mainWindowIsOnCurrentDesktop() )
00295 hideKMail();
00296
else
00297
showKMail();
00298 }
00299
00300
00301
if( e->button() == RightButton )
00302 {
00303 mPopupFolders.clear();
00304 mPopupFolders.resize(mFoldersWithUnread.count());
00305
00306
00307
00308 buildPopupMenu();
00309
00310
if(mNewMessagePopupId != -1)
00311 {
00312 mPopupMenu->removeItem(mNewMessagePopupId);
00313 }
00314
00315
if(mFoldersWithUnread.count() > 0)
00316 {
00317 KPopupMenu *newMessagesPopup =
new KPopupMenu();
00318
00319
QMap<QGuardedPtr<KMFolder>,
int>::Iterator it = mFoldersWithUnread.begin();
00320
for(uint i=0; it != mFoldersWithUnread.end(); ++i)
00321 {
00322 kdDebug(5006) <<
"Adding folder" << endl;
00323
if(i > mPopupFolders.size()) mPopupFolders.resize(i * 2);
00324 mPopupFolders.insert(i, it.key());
00325
QString item =
prettyName(it.key()) +
"(" + QString::number(it.data()) +
")";
00326 newMessagesPopup->insertItem(item,
this, SLOT(selectedAccount(
int)), 0, i);
00327 ++it;
00328 }
00329
00330 mNewMessagePopupId = mPopupMenu->insertItem(i18n(
"New Messages In"),
00331 newMessagesPopup, mNewMessagePopupId, 3);
00332
00333 kdDebug(5006) <<
"Folders added" << endl;
00334 }
00335
00336 mPopupMenu->popup(e->globalPos());
00337 }
00338
00339 }
00340
00345 QString KMSystemTray::prettyName(
KMFolder * fldr)
00346 {
00347
QString rvalue = fldr->
label();
00348
if(fldr->
folderType() == KMFolderTypeImap)
00349 {
00350 KMFolderImap * imap = dynamic_cast<KMFolderImap*> (fldr->
storage());
00351 assert(imap);
00352
00353
if((imap->account() != 0) &&
00354 (imap->account()->name() != 0) )
00355 {
00356 kdDebug(5006) <<
"IMAP folder, prepend label with type" << endl;
00357 rvalue = imap->account()->name() +
"->" + rvalue;
00358 }
00359 }
00360
00361 kdDebug(5006) <<
"Got label " << rvalue << endl;
00362
00363
return rvalue;
00364 }
00365
00366
00367
bool KMSystemTray::mainWindowIsOnCurrentDesktop()
00368 {
00369 KMMainWidget * mainWidget =
getKMMainWidget();
00370
if ( !mainWidget )
00371
return false;
00372
00373
QWidget *mainWin =
getKMMainWidget()->topLevelWidget();
00374
if ( !mainWin )
00375
return false;
00376
00377
return KWin::windowInfo( mainWin->winId(),
00378 NET::WMDesktop ).isOnCurrentDesktop();
00379 }
00380
00385 void KMSystemTray::showKMail()
00386 {
00387
if (!
getKMMainWidget())
00388
return;
00389
QWidget *mainWin =
getKMMainWidget()->topLevelWidget();
00390 assert(mainWin);
00391
if(mainWin)
00392 {
00393
00394
if ( mDesktopOfMainWin != NET::OnAllDesktops )
00395 KWin::setCurrentDesktop( mDesktopOfMainWin );
00396
if ( !mParentVisible ) {
00397
if ( mDesktopOfMainWin == NET::OnAllDesktops )
00398 KWin::setOnAllDesktops( mainWin->winId(),
true );
00399 mainWin->move( mPosOfMainWin );
00400 mainWin->show();
00401 }
00402 KWin::activateWindow( mainWin->winId() );
00403 mParentVisible =
true;
00404 }
00405
00406
00407 foldersChanged();
00408 }
00409
00410
void KMSystemTray::hideKMail()
00411 {
00412
if (!
getKMMainWidget())
00413
return;
00414
QWidget *mainWin =
getKMMainWidget()->topLevelWidget();
00415 assert(mainWin);
00416
if(mainWin)
00417 {
00418 mDesktopOfMainWin = KWin::windowInfo( mainWin->winId(),
00419 NET::WMDesktop ).desktop();
00420 mPosOfMainWin = mainWin->pos();
00421
00422 KWin::iconifyWindow( mainWin->winId() );
00423 mainWin->hide();
00424 mParentVisible =
false;
00425 }
00426 }
00427
00431 KMMainWidget *
KMSystemTray::getKMMainWidget()
00432 {
00433 QWidgetList *l = kapp->topLevelWidgets();
00434 QWidgetListIt it( *l );
00435
QWidget *wid;
00436
00437
while ( (wid = it.current()) != 0 ) {
00438 ++it;
00439
QObjectList *l2 = wid->topLevelWidget()->queryList(
"KMMainWidget");
00440
if (l2 && l2->first())
00441 {
00442 KMMainWidget* kmmw = dynamic_cast<KMMainWidget *>(l2->first());
00443 assert (kmmw);
00444
delete l2;
00445
delete l;
00446
return kmmw;
00447 }
00448
delete l2;
00449 }
00450
delete l;
00451
return 0;
00452 }
00453
00460
void KMSystemTray::updateNewMessageNotification(
KMFolder * fldr)
00461 {
00462
00463
00464
if( !fldr ||
00465 fldr->
folderType() == KMFolderTypeSearch )
00466 {
00467
00468
return;
00469 }
00470
00471 mPendingUpdates[ fldr ] =
true;
00472
if ( time( 0 ) - mLastUpdate > 2 ) {
00473 mUpdateTimer->stop();
00474 updateNewMessages();
00475 }
00476
else {
00477 mUpdateTimer->start(150,
true);
00478 }
00479 }
00480
00481
void KMSystemTray::updateNewMessages()
00482 {
00483
for (
QMap<KMFolder*, bool>::Iterator it = mPendingUpdates.begin();
00484 it != mPendingUpdates.end(); ++it)
00485 {
00486
KMFolder *fldr = it.key();
00487
00489
int unread = fldr->
countUnread();
00490
00491
QMap<QGuardedPtr<KMFolder>,
int>::Iterator it =
00492 mFoldersWithUnread.find(fldr);
00493
bool unmapped = (it == mFoldersWithUnread.end());
00494
00497
if(unmapped) mCount += unread;
00498
00499
00500
else
00501 {
00502
int diff = unread - it.data();
00503 mCount += diff;
00504 }
00505
00506
if(unread > 0)
00507 {
00509 mFoldersWithUnread.insert(fldr, unread);
00510
00511 }
00512
00518
if(unmapped)
00519 {
00521
if(unread == 0)
continue;
00522
00524
if ( ( mMode == GlobalSettings::EnumSystemTrayPolicy::ShowOnUnread )
00525 && isHidden() ) {
00526 show();
00527 }
00528
00529 }
else
00530 {
00531
00532
if(unread == 0)
00533 {
00534 kdDebug(5006) <<
"Removing folder from internal store " << fldr->name() << endl;
00535
00537 mFoldersWithUnread.remove(fldr);
00538
00540
if(mFoldersWithUnread.count() == 0)
00541 {
00542 mPopupFolders.clear();
00543 disconnect(
this, SLOT(selectedAccount(
int)));
00544
00545 mCount = 0;
00546
00547
if ( mMode == GlobalSettings::EnumSystemTrayPolicy::ShowOnUnread ) {
00548 hide();
00549 }
00550 }
00551 }
00552 }
00553
00554 }
00555 mPendingUpdates.clear();
00556
updateCount();
00557
00559 QToolTip::remove(
this);
00560 QToolTip::add(
this, i18n(
"There is 1 unread message.",
00561
"There are %n unread messages.",
00562 mCount));
00563
00564 mLastUpdate = time( 0 );
00565 }
00566
00572
void KMSystemTray::selectedAccount(
int id)
00573 {
00574
showKMail();
00575
00576 KMMainWidget * mainWidget =
getKMMainWidget();
00577
if (!mainWidget)
00578 {
00579 kmkernel->openReader();
00580 mainWidget =
getKMMainWidget();
00581 }
00582
00583 assert(mainWidget);
00584
00586
KMFolder * fldr = mPopupFolders.at(
id);
00587
if(!fldr)
return;
00588 KMFolderTree * ft = mainWidget->folderTree();
00589
if(!ft)
return;
00590
QListViewItem * fldrIdx = ft->indexOfFolder(fldr);
00591
if(!fldrIdx)
return;
00592
00593 ft->setCurrentItem(fldrIdx);
00594 ft->selectCurrentFolder();
00595 }
00596
00597
#include "kmsystemtray.moc"