• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepim API Reference
  • KDE Home
  • Contact Us
 

kmail

  • sources
  • kde-4.12
  • kdepim
  • kmail
kmsystemtray.cpp
Go to the documentation of this file.
1 // -*- mode: C++; c-file-style: "gnu" -*-
2 /***************************************************************************
3  kmsystemtray.cpp - description
4  ------------------
5  begin : Fri Aug 31 22:38:44 EDT 2001
6  copyright : (C) 2001 by Ryan Breen
7  email : ryan@porivo.com
8 
9  Copyright (c) 2010, 2011, 2012, 2013 Montel Laurent <montel@kde.org>
10  ***************************************************************************/
11 
12 /***************************************************************************
13  * *
14  * This program is free software; you can redistribute it and/or modify *
15  * it under the terms of the GNU General Public License as published by *
16  * the Free Software Foundation; either version 2 of the License, or *
17  * (at your option) any later version. *
18  * *
19  ***************************************************************************/
20 
21 
22 #include "kmsystemtray.h"
23 #include "kmmainwidget.h"
24 #include "settings/globalsettings.h"
25 #include "util/mailutil.h"
26 #include "mailcommon/kernel/mailkernel.h"
27 #include "mailcommon/folder/foldertreeview.h"
28 #include "mailcommon/collectionpage/newmailnotifierattribute.h"
29 
30 #include <kiconloader.h>
31 #include <kcolorscheme.h>
32 #include <kwindowsystem.h>
33 #include <kdebug.h>
34 #include <KMenu>
35 #include <KLocale>
36 #include <KAction>
37 #include <KActionMenu>
38 #include <KActionCollection>
39 
40 #include <QPainter>
41 
42 #include <Akonadi/ChangeRecorder>
43 #include <Akonadi/EntityTreeModel>
44 #include <Akonadi/CollectionModel>
45 
46 using namespace MailCommon;
47 
59 namespace KMail {
60 KMSystemTray::KMSystemTray(QObject *parent)
61  : KStatusNotifierItem( parent),
62  mDesktopOfMainWin( 0 ),
63  mMode( GlobalSettings::EnumSystemTrayPolicy::ShowOnUnread ),
64  mCount( 0 ),
65  mShowUnreadMailCount( true ),
66  mIconNotificationsEnabled( true ),
67  mNewMessagesPopup( 0 ),
68  mSendQueued( 0 )
69 {
70  kDebug() << "Initting systray";
71  setToolTipTitle( i18n("KMail") );
72  setToolTipIconByName( QLatin1String("kmail") );
73  setIconByName( QLatin1String("kmail") );
74  mIcon = KIcon( QLatin1String("mail-unread-new") );
75 
76  KMMainWidget * mainWidget = kmkernel->getKMMainWidget();
77  if ( mainWidget ) {
78  QWidget * mainWin = mainWidget->window();
79  if ( mainWin ) {
80  mDesktopOfMainWin = KWindowSystem::windowInfo( mainWin->winId(),
81  NET::WMDesktop ).desktop();
82  }
83  }
84 
85 
86  connect( this, SIGNAL(activateRequested(bool,QPoint)),
87  this, SLOT(slotActivated()) );
88  connect( contextMenu(), SIGNAL(aboutToShow()),
89  this, SLOT(slotContextMenuAboutToShow()) );
90 
91  connect( kmkernel->folderCollectionMonitor(), SIGNAL(collectionStatisticsChanged(Akonadi::Collection::Id,Akonadi::CollectionStatistics)), SLOT(slotCollectionStatisticsChanged(Akonadi::Collection::Id,Akonadi::CollectionStatistics)) );
92 
93  connect( kmkernel->folderCollectionMonitor(), SIGNAL(collectionAdded(Akonadi::Collection,Akonadi::Collection)), this, SLOT(initListOfCollection()) );
94  connect( kmkernel->folderCollectionMonitor(), SIGNAL(collectionRemoved(Akonadi::Collection)), this, SLOT(initListOfCollection()) );
95  connect( kmkernel->folderCollectionMonitor(), SIGNAL(collectionSubscribed(Akonadi::Collection,Akonadi::Collection)),SLOT(initListOfCollection()) );
96  connect( kmkernel->folderCollectionMonitor(), SIGNAL(collectionUnsubscribed(Akonadi::Collection)),SLOT(initListOfCollection()) );
97 
98  initListOfCollection();
99 
100 }
101 
102 bool KMSystemTray::buildPopupMenu()
103 {
104  KMMainWidget * mainWidget = kmkernel->getKMMainWidget();
105  if ( !mainWidget ) {
106  return false;
107  }
108 
109  if ( !contextMenu() ) {
110  setContextMenu( new KMenu() );
111  }
112 
113  contextMenu()->clear();
114 
115  contextMenu()->addTitle(qApp->windowIcon(), i18n("KMail"));
116  QAction * action;
117  if ( ( action = mainWidget->action(QLatin1String("check_mail")) ) )
118  contextMenu()->addAction( action );
119  if ( ( action = mainWidget->action(QLatin1String("check_mail_in")) ) )
120  contextMenu()->addAction( action );
121 
122  mSendQueued = mainWidget->sendQueuedAction();
123  contextMenu()->addAction( mSendQueued );
124  contextMenu()->addAction( mainWidget->sendQueueViaMenu() );
125 
126  contextMenu()->addSeparator();
127  if ( ( action = mainWidget->action(QLatin1String("new_message")) ) )
128  contextMenu()->addAction( action );
129  if ( ( action = mainWidget->action(QLatin1String("kmail_configure_kmail")) ) )
130  contextMenu()->addAction( action );
131  contextMenu()->addSeparator();
132  if ( (action = mainWidget->action(QLatin1String("akonadi_work_offline")) ) )
133  contextMenu()->addAction( action );
134  contextMenu()->addSeparator();
135 
136  if ( ( action = actionCollection()->action(QLatin1String("file_quit")) ) )
137  contextMenu()->addAction( action );
138 
139  return true;
140 }
141 
142 KMSystemTray::~KMSystemTray()
143 {
144 }
145 
146 void KMSystemTray::setShowUnreadCount(bool showUnreadCount)
147 {
148  if (mShowUnreadMailCount == showUnreadCount)
149  return;
150  mShowUnreadMailCount = showUnreadCount;
151  updateSystemTray();
152 }
153 
154 void KMSystemTray::setMode(int newMode)
155 {
156  if (newMode == mMode)
157  return;
158 
159  kDebug() << "Setting systray mMode to" << newMode;
160  mMode = newMode;
161 
162  switch ( mMode ) {
163  case GlobalSettings::EnumSystemTrayPolicy::ShowAlways:
164  setStatus( KStatusNotifierItem::Active );
165  break;
166  case GlobalSettings::EnumSystemTrayPolicy::ShowOnUnread:
167  setStatus( mCount > 0 ? KStatusNotifierItem::Active : KStatusNotifierItem::Passive );
168  break;
169  default:
170  kDebug() << "Unknown systray mode" << mMode;
171  }
172 }
173 
174 int KMSystemTray::mode() const
175 {
176  return mMode;
177 }
178 
184 void KMSystemTray::updateCount()
185 {
186  if (mCount == 0 || !mIconNotificationsEnabled) {
187  setIconByName( QLatin1String("kmail") );
188  return;
189  }
190  if (mShowUnreadMailCount) {
191  const int overlaySize = KIconLoader::SizeSmallMedium;
192 
193  const QString countString = QString::number( mCount );
194  QFont countFont = KGlobalSettings::generalFont();
195  countFont.setBold(true);
196 
197  // decrease the size of the font for the number of unread messages if the
198  // number doesn't fit into the available space
199  float countFontSize = countFont.pointSizeF();
200  QFontMetrics qfm( countFont );
201  const int width = qfm.width( countString );
202  if ( width > (overlaySize - 2) ) {
203  countFontSize *= float( overlaySize - 2 ) / float( width );
204  countFont.setPointSizeF( countFontSize );
205  }
206 
207  // Paint the number in a pixmap
208  QPixmap overlayPixmap( overlaySize, overlaySize );
209  overlayPixmap.fill( Qt::transparent );
210 
211  QPainter p( &overlayPixmap );
212  p.setFont( countFont );
213  KColorScheme scheme( QPalette::Active, KColorScheme::View );
214 
215  p.setBrush( Qt::NoBrush );
216  p.setPen( scheme.foreground( KColorScheme::LinkText ).color() );
217  p.setOpacity( 1.0 );
218  p.drawText( overlayPixmap.rect(),Qt::AlignCenter, countString );
219  p.end();
220 
221  QPixmap iconPixmap = mIcon.pixmap(overlaySize, overlaySize);
222 
223  QPainter pp(&iconPixmap);
224  pp.drawPixmap(0, 0, overlayPixmap);
225  pp.end();
226 
227  setIconByPixmap( iconPixmap );
228  } else {
229  setIconByPixmap( mIcon );
230  }
231 }
232 
233 void KMSystemTray::setSystrayIconNotificationsEnabled( bool enabled )
234 {
235  if ( enabled != mIconNotificationsEnabled ) {
236  mIconNotificationsEnabled = enabled;
237  updateSystemTray();
238  }
239 }
240 
245 void KMSystemTray::slotActivated()
246 {
247  KMMainWidget * mainWidget = kmkernel->getKMMainWidget();
248  if ( !mainWidget )
249  return ;
250 
251  QWidget *mainWin = mainWidget->window();
252  if ( !mainWin )
253  return ;
254 
255  KWindowInfo cur = KWindowSystem::windowInfo( mainWin->winId(), NET::WMDesktop );
256 
257  const int currentDesktop = KWindowSystem::currentDesktop();
258  const bool wasMinimized = cur.isMinimized();
259 
260  if ( cur.valid() )
261  mDesktopOfMainWin = cur.desktop();
262 
263  if (wasMinimized && (currentDesktop != mDesktopOfMainWin) && ( mDesktopOfMainWin == NET::OnAllDesktops ))
264  KWindowSystem::setOnDesktop(mainWin->winId(), currentDesktop);
265 
266  if ( mDesktopOfMainWin == NET::OnAllDesktops )
267  KWindowSystem::setOnAllDesktops( mainWin->winId(), true );
268 
269  KWindowSystem::activateWindow( mainWin->winId() );
270 
271  if (wasMinimized )
272  kmkernel->raise();
273 }
274 
275 void KMSystemTray::slotContextMenuAboutToShow()
276 {
277  // Rebuild popup menu before show to minimize race condition if
278  // the base KMainWidget is closed.
279  if ( !buildPopupMenu() ) {
280  return;
281  }
282 
283  if ( mNewMessagesPopup != 0 ) {
284  contextMenu()->removeAction( mNewMessagesPopup->menuAction() );
285  delete mNewMessagesPopup;
286  mNewMessagesPopup = 0;
287  }
288  mNewMessagesPopup = new KMenu();
289  fillFoldersMenu( mNewMessagesPopup, kmkernel->treeviewModelSelection() );
290 
291  connect( mNewMessagesPopup, SIGNAL(triggered(QAction*)), this,
292  SLOT(slotSelectCollection(QAction*)) );
293 
294 
295  if ( mCount > 0 ) {
296  mNewMessagesPopup->setTitle( i18n("New Messages In") );
297  contextMenu()->insertAction( mSendQueued, mNewMessagesPopup->menuAction() );
298  }
299 }
300 
301 void KMSystemTray::fillFoldersMenu( QMenu *menu, const QAbstractItemModel *model, const QString &parentName, const QModelIndex &parentIndex )
302 {
303  const int rowCount = model->rowCount( parentIndex );
304  for ( int row = 0; row < rowCount; ++row ) {
305  const QModelIndex index = model->index( row, 0, parentIndex );
306  const Akonadi::Collection collection = model->data( index, Akonadi::CollectionModel::CollectionRole ).value<Akonadi::Collection>();
307  qint64 count = 0;
308  if ( !excludeFolder( collection ) ) {
309  Akonadi::CollectionStatistics statistics = collection.statistics();
310  count = qMax( 0LL, statistics.unreadCount() );
311  if ( count > 0 ) {
312  if (ignoreNewMailInFolder(collection)) {
313  count = 0;
314  } else {
315  mCount += count;
316  }
317  }
318  }
319  QString label = parentName.isEmpty() ? QString() : QString(parentName + QLatin1String("->"));
320  label += model->data( index ).toString();
321  label.replace( QLatin1Char( '&' ), QLatin1String( "&&" ) );
322  if ( count > 0 ) {
323  // insert an item
324  QAction* action = menu->addAction( label );
325  action->setData( collection.id() );
326  }
327  if ( model->rowCount( index ) > 0 ) {
328  fillFoldersMenu( menu, model, label, index );
329  }
330  }
331 }
332 
333 void KMSystemTray::hideKMail()
334 {
335  KMMainWidget * mainWidget = kmkernel->getKMMainWidget();
336  if (!mainWidget)
337  return;
338  QWidget *mainWin = mainWidget->window();
339  Q_ASSERT(mainWin);
340  if (mainWin) {
341  mDesktopOfMainWin = KWindowSystem::windowInfo( mainWin->winId(),
342  NET::WMDesktop ).desktop();
343  // iconifying is unnecessary, but it looks cooler
344  KWindowSystem::minimizeWindow( mainWin->winId() );
345  mainWin->hide();
346  }
347 }
348 
349 void KMSystemTray::initListOfCollection()
350 {
351  mCount = 0;
352  const QAbstractItemModel *model = kmkernel->entityTreeModel();
353  if (model->rowCount() == 0) {
354  QTimer::singleShot(1000,this,SLOT(initListOfCollection()));
355  return;
356  }
357  unreadMail( model );
358 
359  if ( mMode == GlobalSettings::EnumSystemTrayPolicy::ShowOnUnread ) {
360  if (status() == KStatusNotifierItem::Passive && (mCount > 0)) {
361  setStatus( KStatusNotifierItem::Active );
362  } else if ( status() == KStatusNotifierItem::Active && (mCount == 0) ) {
363  setStatus( KStatusNotifierItem::Passive );
364  }
365  }
366 
367  //kDebug()<<" mCount :"<<mCount;
368  updateCount();
369 }
370 
371 void KMSystemTray::unreadMail( const QAbstractItemModel *model, const QModelIndex& parentIndex )
372 {
373  const int rowCount = model->rowCount( parentIndex );
374  for ( int row = 0; row < rowCount; ++row ) {
375  const QModelIndex index = model->index( row, 0, parentIndex );
376  const Akonadi::Collection collection = model->data( index, Akonadi::CollectionModel::CollectionRole ).value<Akonadi::Collection>();
377 
378  if ( !excludeFolder( collection ) ) {
379 
380  const Akonadi::CollectionStatistics statistics = collection.statistics();
381  const qint64 count = qMax( 0LL, statistics.unreadCount() );
382 
383  if ( count > 0 ) {
384  if (!ignoreNewMailInFolder(collection)) {
385  mCount += count;
386  }
387  }
388  }
389  if ( model->rowCount( index ) > 0 ) {
390  unreadMail( model, index );
391  }
392  }
393  // Update tooltip to reflect count of unread messages
394  setToolTipSubTitle( mCount == 0 ? i18n("There are no unread messages")
395  : i18np("1 unread message",
396  "%1 unread messages",
397  mCount));
398 }
399 
400 bool KMSystemTray::hasUnreadMail() const
401 {
402  return ( mCount != 0 );
403 }
404 
405 void KMSystemTray::slotSelectCollection(QAction *act)
406 {
407  const Akonadi::Collection::Id id = act->data().value<Akonadi::Collection::Id>();
408  kmkernel->selectCollectionFromId( id );
409  KMMainWidget * mainWidget = kmkernel->getKMMainWidget();
410  if ( !mainWidget )
411  return ;
412  QWidget *mainWin = mainWidget->window();
413  if ( mainWin && !mainWin->isVisible() )
414  activate();
415 }
416 
417 void KMSystemTray::updateSystemTray()
418 {
419  initListOfCollection();
420 }
421 
422 void KMSystemTray::slotCollectionStatisticsChanged( Akonadi::Collection::Id id, const Akonadi::CollectionStatistics & )
423 {
424  //Exclude sent mail folder
425 
426  if ( CommonKernel->outboxCollectionFolder().id() == id ||
427  CommonKernel->sentCollectionFolder().id() == id ||
428  CommonKernel->templatesCollectionFolder().id() == id ||
429  CommonKernel->trashCollectionFolder().id() == id ||
430  CommonKernel->draftsCollectionFolder().id() == id ) {
431  return;
432  }
433  initListOfCollection();
434 }
435 
436 bool KMSystemTray::excludeFolder( const Akonadi::Collection& collection ) const
437 {
438  if (!collection.isValid()) {
439  return true;
440  }
441  if (!collection.contentMimeTypes().contains(KMime::Message::mimeType())) {
442  return true;
443  }
444  if ( CommonKernel->outboxCollectionFolder() == collection ||
445  CommonKernel->sentCollectionFolder() == collection ||
446  CommonKernel->templatesCollectionFolder() == collection ||
447  CommonKernel->trashCollectionFolder() == collection ||
448  CommonKernel->draftsCollectionFolder() == collection ) {
449  return true;
450  }
451 
452  if ( MailCommon::Util::isVirtualCollection( collection ) )
453  return true;
454  return false;
455 }
456 
457 bool KMSystemTray::ignoreNewMailInFolder(const Akonadi::Collection &collection)
458 {
459  if ( collection.hasAttribute<NewMailNotifierAttribute>() ) {
460  if (collection.attribute<NewMailNotifierAttribute>()->ignoreNewMail()) {
461  return true;
462  }
463  }
464  return false;
465 }
466 
467 }
468 #include "kmsystemtray.moc"
KMMainWidget::action
QAction * action(const QString &name)
Definition: kmmainwidget.h:121
globalsettings.h
KMail::KMSystemTray::updateSystemTray
void updateSystemTray()
Definition: kmsystemtray.cpp:417
kmmainwidget.h
QWidget
GlobalSettings
Definition: globalsettings.h:31
KMail::KMSystemTray::~KMSystemTray
~KMSystemTray()
destructor
Definition: kmsystemtray.cpp:142
KMail::KMSystemTray::setSystrayIconNotificationsEnabled
void setSystrayIconNotificationsEnabled(bool enable)
Use this method to disable any systray icon changing.
Definition: kmsystemtray.cpp:233
QObject
KMail::KMSystemTray::mode
int mode() const
Definition: kmsystemtray.cpp:174
kmsystemtray.h
KMMainWidget
Definition: kmmainwidget.h:83
kmkernel
#define kmkernel
Definition: kmkernel.h:22
KMail::KMSystemTray::hasUnreadMail
bool hasUnreadMail() const
Definition: kmsystemtray.cpp:400
KMail::KMSystemTray::setMode
void setMode(int mode)
Definition: kmsystemtray.cpp:154
QMenu
KMail::KMSystemTray::hideKMail
void hideKMail()
Definition: kmsystemtray.cpp:333
KStatusNotifierItem
KMail::KMSystemTray::setShowUnreadCount
void setShowUnreadCount(bool showUnreadCount)
Definition: kmsystemtray.cpp:146
KMMainWidget::sendQueuedAction
KAction * sendQueuedAction() const
Definition: kmmainwidget.h:126
KMMainWidget::sendQueueViaMenu
KActionMenu * sendQueueViaMenu() const
Definition: kmmainwidget.h:127
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:58:52 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kmail

Skip menu "kmail"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdepim API Reference

Skip menu "kdepim API Reference"
  • akonadi_next
  • akregator
  • blogilo
  • calendarsupport
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt2
  • kjots
  • kleopatra
  • kmail
  • knode
  • knotes
  • kontact
  • korgac
  • korganizer
  • ktimetracker
  • libkdepim
  • libkleo
  • libkpgp
  • mailcommon
  • messagelist
  • messageviewer

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal