• 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
kmmainwidget.cpp
Go to the documentation of this file.
1 /* -*- mode: C++; c-file-style: "gnu" -*-
2  This file is part of KMail, the KDE mail client.
3  Copyright (c) 2002 Don Sanders <sanders@kde.org>
4  Copyright (c) 2009, 2010, 2011, 2012 Montel Laurent <montel@kde.org>
5 
6  Based on the work of Stefan Taferner <taferner@kde.org>
7 
8  KMail is free software; you can redistribute it and/or modify it
9  under the terms of the GNU General Public License, version 2, as
10  published by the Free Software Foundation.
11 
12  KMail is distributed in the hope that it will be useful, but
13  WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License along
18  with this program; if not, write to the Free Software Foundation, Inc.,
19  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21 
22 // KMail includes
23 #include "kmreadermainwin.h"
24 #include "editor/composer.h"
25 #include "searchdialog/searchwindow.h"
26 #include "antispam-virus/antispamwizard.h"
27 #include "widgets/statusbarlabel.h"
28 #include "undostack.h"
29 #include "kmcommands.h"
30 #include "kmmainwin.h"
31 #include "kmsystemtray.h"
32 #include "customtemplatesmenu.h"
33 #include "folderselectiondialog.h"
34 #include "foldertreewidget.h"
35 #include "util.h"
36 #include "util/mailutil.h"
37 #include "kernel/mailkernel.h"
38 #include "dialog/archivefolderdialog.h"
39 #include "settings/globalsettings.h"
40 #include "foldertreeview.h"
41 #include "tag/tagactionmanager.h"
42 #include "foldershortcutactionmanager.h"
43 #include "widgets/collectionpane.h"
44 #if !defined(NDEBUG)
45  #include <ksieveui/debug/sievedebugdialog.h>
46  using KSieveUi::SieveDebugDialog;
47 #endif
48 
49 #include "collectionpage/collectionmaintenancepage.h"
50 #include "collectionpage/collectionquotapage.h"
51 #include "collectionpage/collectiontemplatespage.h"
52 #include "collectionpage/collectionshortcutpage.h"
53 #include "collectionpage/collectionviewpage.h"
54 #include "collectionpage/collectionmailinglistpage.h"
55 #include "tag/tagselectdialog.h"
56 #include "archivemailagentinterface.h"
57 #include "job/createnewcontactjob.h"
58 #include "sendlateragentinterface.h"
59 #include "folderarchiveagentinterface.h"
60 #include "agents/folderarchiveagent/folderarchiveutil.h"
61 
62 #include "pimcommon/acl/collectionaclpage.h"
63 #include "mailcommon/collectionpage/collectiongeneralpage.h"
64 #include "mailcommon/collectionpage/collectionexpirypage.h"
65 #include "mailcommon/collectionpage/expirecollectionattribute.h"
66 #include "mailcommon/filter/filtermanager.h"
67 #include "mailcommon/filter/mailfilter.h"
68 #include "mailcommon/widgets/favoritecollectionwidget.h"
69 #include "mailcommon/mailcommonsettings_base.h"
70 
71 // Other PIM includes
72 #include "kdepim-version.h"
73 
74 #include "messageviewer/utils/autoqpointer.h"
75 #include "messageviewer/settings/globalsettings.h"
76 #include "messageviewer/viewer/viewer.h"
77 #include "messageviewer/viewer/attachmentstrategy.h"
78 #include "messageviewer/header/headerstrategy.h"
79 #include "messageviewer/header/headerstyle.h"
80 #ifndef QT_NO_CURSOR
81 #include "messageviewer/utils/kcursorsaver.h"
82 #endif
83 
84 #include "messagecomposer/sender/messagesender.h"
85 #include "messagecomposer/helper/messagehelper.h"
86 
87 #include "templateparser/templateparser.h"
88 
89 #include "messagecore/settings/globalsettings.h"
90 #include "messagecore/misc/mailinglist.h"
91 #include "messagecore/helpers/messagehelpers.h"
92 
93 #include "dialog/kmknotify.h"
94 
95 #include "vacationmanager.h"
96 
97 
98 // LIBKDEPIM includes
99 #include "progresswidget/progressmanager.h"
100 #include "misc/broadcaststatus.h"
101 
102 // KDEPIMLIBS includes
103 #include <Akonadi/AgentManager>
104 #include <Akonadi/AttributeFactory>
105 #include <akonadi/itemfetchjob.h>
106 #include <akonadi/collectionattributessynchronizationjob.h>
107 #include <akonadi/collectionfetchjob.h>
108 #include <akonadi/collectionfetchscope.h>
109 #include <akonadi/contact/contactsearchjob.h>
110 #include <akonadi/collectionpropertiesdialog.h>
111 #include <akonadi/entitydisplayattribute.h>
112 #include <akonadi/entitylistview.h>
113 #include <akonadi/etmviewstatesaver.h>
114 #include <akonadi/agentinstance.h>
115 #include <akonadi/agenttype.h>
116 #include <akonadi/changerecorder.h>
117 #include <akonadi/session.h>
118 #include <akonadi/entitytreemodel.h>
119 #include <akonadi/favoritecollectionsmodel.h>
120 #include <akonadi/itemfetchscope.h>
121 #include <akonadi/itemmodifyjob.h>
122 #include <akonadi/control.h>
123 #include <akonadi/collectiondialog.h>
124 #include <akonadi/collectionstatistics.h>
125 #include <akonadi/collectionstatisticsdelegate.h>
126 #include <Akonadi/EntityMimeTypeFilterModel>
127 #include <akonadi/kmime/messageflags.h>
128 #include <akonadi/kmime/removeduplicatesjob.h>
129 #include <akonadi/collectiondeletejob.h>
130 #include <akonadi/dbusconnectionpool.h>
131 #include <Akonadi/CachePolicy>
132 
133 #include <kpimidentities/identity.h>
134 #include <kpimidentities/identitymanager.h>
135 #include <kpimutils/email.h>
136 #include <mailtransport/transportmanager.h>
137 #include <mailtransport/transport.h>
138 #include <kmime/kmime_mdn.h>
139 #include <kmime/kmime_header_parsing.h>
140 #include <kmime/kmime_message.h>
141 #include <ksieveui/managesievescriptsdialog.h>
142 #include <ksieveui/util/util.h>
143 
144 // KDELIBS includes
145 #include <kaboutdata.h>
146 #include <kicon.h>
147 #include <kwindowsystem.h>
148 #include <krun.h>
149 #include <kmessagebox.h>
150 #include <kactionmenu.h>
151 #include <kmenu.h>
152 #include <kacceleratormanager.h>
153 #include <kglobal.h>
154 #include <kglobalsettings.h>
155 #include <kstandardshortcut.h>
156 #include <kshortcutsdialog.h>
157 #include <kcharsets.h>
158 #include <kdebug.h>
159 #include <kfiledialog.h>
160 #include <ktip.h>
161 #include <kstandarddirs.h>
162 #include <kstandardaction.h>
163 #include <ktoggleaction.h>
164 #include <knotification.h>
165 #include <knotifyconfigwidget.h>
166 #include <kstringhandler.h>
167 #include <kconfiggroup.h>
168 #include <ktoolinvocation.h>
169 #include <kxmlguifactory.h>
170 #include <kxmlguiclient.h>
171 #include <kstatusbar.h>
172 #include <kaction.h>
173 #include <ktreewidgetsearchline.h>
174 #include <Solid/Networking>
175 #include <nepomuk2/resourcemanager.h>
176 #include <KRecentFilesAction>
177 
178 // Qt includes
179 #include <QByteArray>
180 #include <QHeaderView>
181 #include <QLabel>
182 #include <QList>
183 #include <QSplitter>
184 #include <QVBoxLayout>
185 #include <QShortcut>
186 #include <QProcess>
187 #include <QDBusMessage>
188 #include <QDBusConnection>
189 #include <QTextDocument>
190 #include <QMenu>
191 #include <QtDBus/QDBusInterface>
192 #include <QtDBus/QDBusReply>
193 #include <QDBusPendingCallWatcher>
194 
195 // System includes
196 #include <assert.h>
197 #include <errno.h> // ugh
198 #include <akonadi/standardactionmanager.h>
199 
200 #include "kmmainwidget.moc"
201 
202 using namespace KMime;
203 using namespace Akonadi;
204 using namespace MailCommon;
205 using KPIM::ProgressManager;
206 using KPIM::BroadcastStatus;
207 using KMail::SearchWindow;
208 using KMail::AntiSpamWizard;
209 using KMime::Types::AddrSpecList;
210 using MessageViewer::AttachmentStrategy;
211 
212 Q_DECLARE_METATYPE(KPIM::ProgressItem*)
213 Q_DECLARE_METATYPE(Akonadi::Job*)
214 Q_DECLARE_METATYPE(QPointer<KPIM::ProgressItem>)
215 K_GLOBAL_STATIC( KMMainWidget::PtrList, theMainWidgetList )
216 
217 //-----------------------------------------------------------------------------
218  KMMainWidget::KMMainWidget( QWidget *parent, KXMLGUIClient *aGUIClient,
219  KActionCollection *actionCollection, KSharedConfig::Ptr config ) :
220  QWidget( parent ),
221  mMoveMsgToFolderAction(0),
222  mCollectionProperties( 0 ),
223  mFavoriteCollectionsView( 0 ),
224  mMsgView( 0 ),
225  mSplitter1( 0 ),
226  mSplitter2( 0 ),
227  mFolderViewSplitter( 0 ),
228  mArchiveFolderAction( 0 ),
229  mShowBusySplashTimer( 0 ),
230  mMsgActions( 0 ),
231  mCurrentFolder( 0 ),
232  mVacationIndicatorActive( false ),
233  mGoToFirstUnreadMessageInSelectedFolder( false )
234 {
235  // must be the first line of the constructor:
236  mStartupDone = false;
237  mWasEverShown = false;
238  mReaderWindowActive = true;
239  mReaderWindowBelow = true;
240  mFolderHtmlPref = false;
241  mFolderHtmlLoadExtPref = false;
242  mDestructed = false;
243  mActionCollection = actionCollection;
244  mTopLayout = new QVBoxLayout( this );
245  mTopLayout->setMargin( 0 );
246  mConfig = config;
247  mGUIClient = aGUIClient;
248  mFolderTreeWidget = 0;
249  mPreferHtmlAction = 0;
250  mPreferHtmlLoadExtAction = 0;
251  Akonadi::Control::widgetNeedsAkonadi( this );
252  mFavoritesModel = 0;
253  mVacationManager = new KMail::VacationManager(this);
254 
255 
256  // FIXME This should become a line separator as soon as the API
257  // is extended in kdelibs.
258  mToolbarActionSeparator = new QAction( this );
259  mToolbarActionSeparator->setSeparator( true );
260 
261  theMainWidgetList->append( this );
262 
263  readPreConfig();
264  createWidgets();
265  setupActions();
266 
267 
268  readConfig();
269 
270  if ( !kmkernel->isOffline() ) { //kmail is set to online mode, make sure the agents are also online
271  kmkernel->setAccountStatus(true);
272  }
273 
274 
275  QTimer::singleShot( 0, this, SLOT(slotShowStartupFolder()));
276 
277  connect( kmkernel, SIGNAL(startCheckMail()),
278  this, SLOT(slotStartCheckMail()) );
279 
280  connect( kmkernel, SIGNAL(endCheckMail()),
281  this, SLOT(slotEndCheckMail()) );
282 
283  connect( kmkernel, SIGNAL(configChanged()),
284  this, SLOT(slotConfigChanged()) );
285 
286  connect( kmkernel, SIGNAL(onlineStatusChanged(GlobalSettings::EnumNetworkState::type)),
287  this, SLOT(slotUpdateOnlineStatus(GlobalSettings::EnumNetworkState::type)) );
288 
289  connect( mTagActionManager, SIGNAL(tagActionTriggered(QString)),
290  this, SLOT(slotUpdateMessageTagList(QString)) );
291 
292  connect( mTagActionManager, SIGNAL(tagMoreActionClicked()),
293  this, SLOT(slotSelectMoreMessageTagList()) );
294 
295  kmkernel->toggleSystemTray();
296 
297  { // make sure the pages are registered only once, since there can be multiple instances of KMMainWidget
298  static bool pagesRegistered = false;
299 
300  if ( !pagesRegistered ) {
301  Akonadi::CollectionPropertiesDialog::registerPage( new PimCommon::CollectionAclPageFactory );
302  Akonadi::CollectionPropertiesDialog::registerPage( new MailCommon::CollectionGeneralPageFactory );
303  Akonadi::CollectionPropertiesDialog::registerPage( new CollectionMaintenancePageFactory );
304  Akonadi::CollectionPropertiesDialog::registerPage( new CollectionQuotaPageFactory );
305  Akonadi::CollectionPropertiesDialog::registerPage( new CollectionTemplatesPageFactory );
306  Akonadi::CollectionPropertiesDialog::registerPage( new MailCommon::CollectionExpiryPageFactory );
307  Akonadi::CollectionPropertiesDialog::registerPage( new CollectionViewPageFactory );
308  Akonadi::CollectionPropertiesDialog::registerPage( new CollectionMailingListPageFactory );
309  Akonadi::CollectionPropertiesDialog::registerPage( new CollectionShortcutPageFactory );
310 
311  pagesRegistered = true;
312  }
313  }
314 
315  KMainWindow *mainWin = dynamic_cast<KMainWindow*>(window());
316  KStatusBar *sb = mainWin ? mainWin->statusBar() : 0;
317  mVacationScriptIndicator = new KMail::StatusBarLabel( sb );
318  mVacationScriptIndicator->hide();
319  connect( mVacationScriptIndicator, SIGNAL(clicked()), SLOT(slotEditVacation()) );
320  if ( KSieveUi::Util::checkOutOfOfficeOnStartup() )
321  QTimer::singleShot( 0, this, SLOT(slotCheckVacation()) );
322 
323  restoreCollectionFolderViewConfig();
324 
325  if ( kmkernel->firstStart() ) {
326  if (MailCommon::Util::foundMailer()) {
327  if (KMessageBox::questionYesNo(this,i18n("Another mailer was found on system. Do you want to import data from it?")) == KMessageBox::Yes) {
328  const QString path = KStandardDirs::findExe( QLatin1String("importwizard" ) );
329  if ( !QProcess::startDetached( path ) ) {
330  KMessageBox::error( this, i18n( "Could not start the import wizard. "
331  "Please check your installation." ),
332  i18n( "Unable to start import wizard" ) );
333  }
334  } else {
335  KMail::Util::launchAccountWizard( this );
336  }
337  } else {
338  KMail::Util::launchAccountWizard( this );
339  }
340  }
341  // must be the last line of the constructor:
342  mStartupDone = true;
343 
344 
345  mCheckMailTimer.setInterval( 3 * 1000 );
346  mCheckMailTimer.setSingleShot( true );
347  connect( &mCheckMailTimer, SIGNAL(timeout()), SLOT(slotUpdateActionsAfterMailChecking()) );
348 
349 }
350 
351 void KMMainWidget::restoreCollectionFolderViewConfig(Akonadi::Collection::Id id)
352 {
353  ETMViewStateSaver *saver = new ETMViewStateSaver;
354  saver->setView( mFolderTreeWidget->folderTreeView() );
355  const KConfigGroup cfg( KMKernel::self()->config(), "CollectionFolderView" );
356  mFolderTreeWidget->restoreHeaderState( cfg.readEntry( "HeaderState", QByteArray() ) );
357  saver->restoreState( cfg );
358  //Restore startup folder
359 
360  if (id == -1) {
361  if (GlobalSettings::self()->startSpecificFolderAtStartup()) {
362  Akonadi::Collection::Id startupFolder = GlobalSettings::self()->startupFolder();
363  if ( startupFolder > 0 )
364  saver->restoreCurrentItem( QString::fromLatin1("c%1").arg(startupFolder) );
365  }
366  } else {
367  saver->restoreCurrentItem( QString::fromLatin1("c%1").arg(id) );
368  }
369 }
370 
371 
372 //-----------------------------------------------------------------------------
373 //The kernel may have already been deleted when this method is called,
374 //perform all cleanup that requires the kernel in destruct()
375 KMMainWidget::~KMMainWidget()
376 {
377  theMainWidgetList->removeAll( this );
378  qDeleteAll( mFilterCommands );
379  destruct();
380 }
381 
382 
383 //-----------------------------------------------------------------------------
384 //This method performs all cleanup that requires the kernel to exist.
385 void KMMainWidget::destruct()
386 {
387  if ( mDestructed )
388  return;
389  if ( mSearchWin )
390  mSearchWin->close();
391  writeConfig(false); /* don't force kmkernel sync when close BUG: 289287 */
392  writeFolderConfig();
393  deleteWidgets();
394  mCurrentFolder.clear();
395  delete mMoveOrCopyToDialog;
396  delete mSelectFromAllFoldersDialog;
397 
398  disconnect( kmkernel->folderCollectionMonitor(), SIGNAL(itemAdded(Akonadi::Item,Akonadi::Collection)), this, 0);
399  disconnect( kmkernel->folderCollectionMonitor(), SIGNAL(itemRemoved(Akonadi::Item)), this, 0);
400  disconnect( kmkernel->folderCollectionMonitor(), SIGNAL(itemMoved(Akonadi::Item,Akonadi::Collection,Akonadi::Collection)), this, 0);
401  disconnect( kmkernel->folderCollectionMonitor(), SIGNAL(collectionChanged(Akonadi::Collection,QSet<QByteArray>)), this, 0);
402  disconnect( kmkernel->folderCollectionMonitor(), SIGNAL(collectionStatisticsChanged(Akonadi::Collection::Id,Akonadi::CollectionStatistics)), this, 0);
403 
404  mDestructed = true;
405 }
406 
407 
408 void KMMainWidget::slotStartCheckMail()
409 {
410  if ( mCheckMailTimer.isActive() )
411  mCheckMailTimer.stop();
412 }
413 
414 void KMMainWidget::slotEndCheckMail()
415 {
416  if ( !mCheckMailTimer.isActive() )
417  mCheckMailTimer.start();
418 }
419 
420 void KMMainWidget::slotUpdateActionsAfterMailChecking()
421 {
422  const bool sendOnAll =
423  GlobalSettings::self()->sendOnCheck() == GlobalSettings::EnumSendOnCheck::SendOnAllChecks;
424  const bool sendOnManual =
425  GlobalSettings::self()->sendOnCheck() == GlobalSettings::EnumSendOnCheck::SendOnManualChecks;
426  if ( !kmkernel->isOffline() && ( sendOnAll || (sendOnManual /*&& sendOnCheck*/ ) ) ) {
427  slotSendQueued();
428  }
429  // update folder menus in case some mail got filtered to trash/current folder
430  // and we can enable "empty trash/move all to trash" action etc.
431  updateFolderMenu();
432 }
433 
434 void KMMainWidget::slotCollectionFetched( int collectionId )
435 {
436  // Called when a collection is fetched for the first time by the ETM.
437  // This is the right time to update the caption (which still says "Loading...")
438  // and to update the actions that depend on the number of mails in the folder.
439  if ( mCurrentFolder && collectionId == mCurrentFolder->collection().id() ) {
440  mCurrentFolder->setCollection( MailCommon::Util::updatedCollection( mCurrentFolder->collection() ) );
441  updateMessageActions();
442  updateFolderMenu();
443  }
444  // We call this for any collection, it could be one of our parents...
445  if ( mCurrentFolder ) {
446  emit captionChangeRequest( MailCommon::Util::fullCollectionPath( mCurrentFolder->collection() ) );
447  }
448 }
449 
450 void KMMainWidget::slotFolderChanged( const Akonadi::Collection& collection )
451 {
452  folderSelected( collection );
453  if (collection.cachePolicy().syncOnDemand())
454  AgentManager::self()->synchronizeCollection( collection, false );
455  mMsgActions->setCurrentMessage( Akonadi::Item() );
456  emit captionChangeRequest( MailCommon::Util::fullCollectionPath( collection ) );
457 }
458 
459 void KMMainWidget::folderSelected( const Akonadi::Collection & col )
460 {
461  // This is connected to the MainFolderView signal triggering when a folder is selected
462 
463  if ( mGoToFirstUnreadMessageInSelectedFolder )
464  {
465  // the default action has been overridden from outside
466  mPreSelectionMode = MessageList::Core::PreSelectFirstUnreadCentered;
467  } else {
468  // use the default action
469  switch ( GlobalSettings::self()->actionEnterFolder() )
470  {
471  case GlobalSettings::EnumActionEnterFolder::SelectFirstUnread:
472  mPreSelectionMode = MessageList::Core::PreSelectFirstUnreadCentered;
473  break;
474  case GlobalSettings::EnumActionEnterFolder::SelectLastSelected:
475  mPreSelectionMode = MessageList::Core::PreSelectLastSelected;
476  break;
477  case GlobalSettings::EnumActionEnterFolder::SelectNewest:
478  mPreSelectionMode = MessageList::Core::PreSelectNewestCentered;
479  break;
480  case GlobalSettings::EnumActionEnterFolder::SelectOldest:
481  mPreSelectionMode = MessageList::Core::PreSelectOldestCentered;
482  break;
483  default:
484  mPreSelectionMode = MessageList::Core::PreSelectNone;
485  break;
486  }
487  }
488 
489  mGoToFirstUnreadMessageInSelectedFolder = false;
490 #ifndef QT_NO_CURSOR
491  MessageViewer::KCursorSaver busy( MessageViewer::KBusyPtr::busy() );
492 #endif
493 
494  if (mMsgView)
495  mMsgView->clear(true);
496  const bool newFolder = mCurrentFolder && ( mCurrentFolder->collection() != col );
497 
498  // Delete any pending timer, if needed it will be recreated below
499  delete mShowBusySplashTimer;
500  mShowBusySplashTimer = 0;
501  if ( newFolder )
502  {
503  // We're changing folder: write configuration for the old one
504  writeFolderConfig();
505  }
506 
507  mCurrentFolder = FolderCollection::forCollection( col );
508 
509  readFolderConfig();
510  if (mMsgView)
511  {
512  mMsgView->setHtmlOverride(mFolderHtmlPref);
513  mMsgView->setHtmlLoadExtOverride(mFolderHtmlLoadExtPref);
514  }
515 
516  if ( !mCurrentFolder->isValid() && ( mMessagePane->count() < 2 ) )
517  slotIntro();
518 
519  updateMessageActions();
520  updateFolderMenu();
521 
522  // The message pane uses the selection model of the folder view to load the correct aggregation model and theme
523  // settings. At this point the selection model hasn't been updated yet to the user's new choice, so it would load
524  // the old folder settings instead.
525  QTimer::singleShot( 0, this, SLOT(slotShowSelectedFolderInPane()) );
526 }
527 
528 void KMMainWidget::slotShowSelectedFolderInPane()
529 {
530  if ( mCurrentFolder && mCurrentFolder->collection().isValid() ) {
531  mMessagePane->setCurrentFolder( mCurrentFolder->collection(), false , mPreSelectionMode );
532  }
533 }
534 
535 void KMMainWidget::clearViewer()
536 {
537  if (mMsgView) {
538  mMsgView->clear( true );
539  mMsgView->displayAboutPage();
540  }
541 }
542 
543 //-----------------------------------------------------------------------------
544 void KMMainWidget::readPreConfig()
545 {
546  mLongFolderList = GlobalSettings::self()->folderList() == GlobalSettings::EnumFolderList::longlist;
547  mReaderWindowActive = GlobalSettings::self()->readerWindowMode() != GlobalSettings::EnumReaderWindowMode::hide;
548  mReaderWindowBelow = GlobalSettings::self()->readerWindowMode() == GlobalSettings::EnumReaderWindowMode::below;
549 
550  mHtmlPref = MessageViewer::GlobalSettings::self()->htmlMail();
551  mHtmlLoadExtPref = MessageViewer::GlobalSettings::self()->htmlLoadExternal();
552  mEnableFavoriteFolderView = ( MailCommon::MailCommonSettings::self()->favoriteCollectionViewMode() != MailCommon::MailCommonSettings::EnumFavoriteCollectionViewMode::HiddenMode );
553  mEnableFolderQuickSearch = GlobalSettings::self()->enableFolderQuickSearch();
554  updateHtmlMenuEntry();
555 }
556 
557 
558 //-----------------------------------------------------------------------------
559 void KMMainWidget::readFolderConfig()
560 {
561  if ( !mCurrentFolder || !mCurrentFolder->isValid() )
562  return;
563 
564  KSharedConfig::Ptr config = KMKernel::self()->config();
565  KConfigGroup group( config, MailCommon::FolderCollection::configGroupName( mCurrentFolder->collection() ) );
566  mFolderHtmlPref =
567  group.readEntry( "htmlMailOverride", false );
568  mFolderHtmlLoadExtPref =
569  group.readEntry( "htmlLoadExternalOverride", false );
570 }
571 
572 
573 //-----------------------------------------------------------------------------
574 void KMMainWidget::writeFolderConfig()
575 {
576  if ( mCurrentFolder && mCurrentFolder->isValid() ) {
577  KSharedConfig::Ptr config = KMKernel::self()->config();
578  KConfigGroup group( config, MailCommon::FolderCollection::configGroupName( mCurrentFolder->collection() ) );
579  group.writeEntry( "htmlMailOverride", mFolderHtmlPref );
580  group.writeEntry( "htmlLoadExternalOverride", mFolderHtmlLoadExtPref );
581  }
582 }
583 
584 //-----------------------------------------------------------------------------
585 void KMMainWidget::layoutSplitters()
586 {
587  // This function can only be called when the old splitters are already deleted
588  assert( !mSplitter1 );
589  assert( !mSplitter2 );
590 
591  // For some reason, this is necessary here so that the copy action still
592  // works after changing the folder layout.
593  if ( mMsgView )
594  disconnect( mMsgView->copyAction(), SIGNAL(triggered(bool)),
595  mMsgView, SLOT(slotCopySelectedText()) );
596 
597  // If long folder list is enabled, the splitters are:
598  // Splitter 1: FolderView vs (HeaderAndSearch vs MessageViewer)
599  // Splitter 2: HeaderAndSearch vs MessageViewer
600  //
601  // If long folder list is disabled, the splitters are:
602  // Splitter 1: (FolderView vs HeaderAndSearch) vs MessageViewer
603  // Splitter 2: FolderView vs HeaderAndSearch
604 
605  // The folder view is both the folder tree and the favorite folder view, if
606  // enabled
607 
608  const bool opaqueResize = KGlobalSettings::opaqueResize();
609  const bool readerWindowAtSide = !mReaderWindowBelow && mReaderWindowActive;
610  const bool readerWindowBelow = mReaderWindowBelow && mReaderWindowActive;
611 
612  mSplitter1 = new QSplitter( this );
613  mSplitter2 = new QSplitter( mSplitter1 );
614 
615  QWidget * folderTreeWidget = mSearchAndTree;
616  if ( mFavoriteCollectionsView ) {
617  mFolderViewSplitter = new QSplitter( Qt::Vertical );
618  mFolderViewSplitter->setOpaqueResize( opaqueResize );
619  //mFolderViewSplitter->setChildrenCollapsible( false );
620  mFolderViewSplitter->addWidget( mFavoriteCollectionsView );
621  mFavoriteCollectionsView->setParent( mFolderViewSplitter );
622  mFolderViewSplitter->addWidget( mSearchAndTree );
623  folderTreeWidget = mFolderViewSplitter;
624  }
625 
626  if ( mLongFolderList ) {
627 
628  // add folder tree
629  mSplitter1->setOrientation( Qt::Horizontal );
630  mSplitter1->addWidget( folderTreeWidget );
631 
632  // and the rest to the right
633  mSplitter1->addWidget( mSplitter2 );
634 
635  // add the message list to the right or below
636  if ( readerWindowAtSide ) {
637  mSplitter2->setOrientation( Qt::Horizontal );
638  } else {
639  mSplitter2->setOrientation( Qt::Vertical );
640  }
641  mSplitter2->addWidget( mMessagePane );
642 
643  // add the preview window, if there is one
644  if ( mMsgView ) {
645  mSplitter2->addWidget( mMsgView );
646  }
647 
648  } else { // short folder list
649  if ( mReaderWindowBelow ) {
650  mSplitter1->setOrientation( Qt::Vertical );
651  mSplitter2->setOrientation( Qt::Horizontal );
652  } else { // at side or none
653  mSplitter1->setOrientation( Qt::Horizontal );
654  mSplitter2->setOrientation( Qt::Vertical );
655  }
656 
657  mSplitter1->addWidget( mSplitter2 );
658 
659  // add folder tree
660  mSplitter2->addWidget( folderTreeWidget );
661  // add message list to splitter 2
662  mSplitter2->addWidget( mMessagePane );
663 
664  // add the preview window, if there is one
665  if ( mMsgView )
666  mSplitter1->addWidget( mMsgView );
667  }
668 
669  //
670  // Set splitter properties
671  //
672  mSplitter1->setObjectName( QLatin1String("splitter1") );
673  mSplitter1->setOpaqueResize( opaqueResize );
674  //mSplitter1->setChildrenCollapsible( false );
675  mSplitter2->setObjectName( QLatin1String("splitter2") );
676  mSplitter2->setOpaqueResize( opaqueResize );
677  //mSplitter2->setChildrenCollapsible( false );
678 
679  //
680  // Set the stretch factors
681  //
682  mSplitter1->setStretchFactor( 0, 0 );
683  mSplitter2->setStretchFactor( 0, 0 );
684  mSplitter1->setStretchFactor( 1, 1 );
685  mSplitter2->setStretchFactor( 1, 1 );
686 
687  if ( mFavoriteCollectionsView ) {
688  mFolderViewSplitter->setStretchFactor( 0, 0 );
689  mFolderViewSplitter->setStretchFactor( 1, 1 );
690  }
691 
692  // Because the reader windows's width increases a tiny bit after each
693  // restart in short folder list mode with message window at side, disable
694  // the stretching as a workaround here
695  if ( readerWindowAtSide && !mLongFolderList ) {
696  mSplitter1->setStretchFactor( 0, 1 );
697  mSplitter1->setStretchFactor( 1, 0 );
698  }
699 
700  //
701  // Set the sizes of the splitters to the values stored in the config
702  //
703  QList<int> splitter1Sizes;
704  QList<int> splitter2Sizes;
705 
706  const int folderViewWidth = GlobalSettings::self()->folderViewWidth();
707  int ftHeight = GlobalSettings::self()->folderTreeHeight();
708  int headerHeight = GlobalSettings::self()->searchAndHeaderHeight();
709  const int messageViewerWidth = GlobalSettings::self()->readerWindowWidth();
710  int headerWidth = GlobalSettings::self()->searchAndHeaderWidth();
711  int messageViewerHeight = GlobalSettings::self()->readerWindowHeight();
712 
713  int ffvHeight = mFolderViewSplitter ? MailCommon::MailCommonSettings::self()->favoriteCollectionViewHeight() : 0;
714 
715  // If the message viewer was hidden before, make sure it is not zero height
716  if ( messageViewerHeight < 10 && readerWindowBelow ) {
717  headerHeight /= 2;
718  messageViewerHeight = headerHeight;
719  }
720 
721  if ( mLongFolderList ) {
722  if ( !readerWindowAtSide ) {
723  splitter1Sizes << folderViewWidth << headerWidth;
724  splitter2Sizes << headerHeight << messageViewerHeight;
725  } else {
726  splitter1Sizes << folderViewWidth << ( headerWidth + messageViewerWidth );
727  splitter2Sizes << headerWidth << messageViewerWidth;
728  }
729  } else {
730  if ( !readerWindowAtSide ) {
731  splitter1Sizes << headerHeight << messageViewerHeight;
732  splitter2Sizes << folderViewWidth << headerWidth;
733  } else {
734  splitter1Sizes << headerWidth << messageViewerWidth;
735  splitter2Sizes << ftHeight + ffvHeight << messageViewerHeight;
736  }
737  }
738 
739  mSplitter1->setSizes( splitter1Sizes );
740  mSplitter2->setSizes( splitter2Sizes );
741 
742  if ( mFolderViewSplitter ) {
743  QList<int> splitterSizes;
744  splitterSizes << ffvHeight << ftHeight;
745  mFolderViewSplitter->setSizes( splitterSizes );
746  }
747 
748  //
749  // Now add the splitters to the main layout
750  //
751  mTopLayout->addWidget( mSplitter1 );
752 
753  // Make sure the focus is on the view, and not on the quick search line edit, because otherwise
754  // shortcuts like + or j go to the wrong place.
755  // This would normally be done in the message list itself, but apparently something resets the focus
756  // again, probably all the reparenting we do here.
757  mMessagePane->focusView();
758 
759  // By default hide th unread and size columns on first run.
760  if ( kmkernel->firstStart() )
761  {
762  mFolderTreeWidget->folderTreeView()->hideColumn( 1 );
763  mFolderTreeWidget->folderTreeView()->hideColumn( 3 );
764  mFolderTreeWidget->folderTreeView()->header()->resizeSection( 0, folderViewWidth * 0.8 );
765  }
766 
767  // Make the copy action work, see disconnect comment above
768  if ( mMsgView )
769  connect( mMsgView->copyAction(), SIGNAL(triggered(bool)),
770  mMsgView, SLOT(slotCopySelectedText()) );
771 }
772 
773 //-----------------------------------------------------------------------------
774 void KMMainWidget::refreshFavoriteFoldersViewProperties()
775 {
776  if ( mFavoriteCollectionsView ) {
777  if ( MailCommon::MailCommonSettings::self()->favoriteCollectionViewMode() == MailCommon::MailCommonSettings::EnumFavoriteCollectionViewMode::IconMode )
778  mFavoriteCollectionsView->setViewMode( QListView::IconMode );
779  else if ( MailCommon::MailCommonSettings::self()->favoriteCollectionViewMode() == MailCommon::MailCommonSettings::EnumFavoriteCollectionViewMode::ListMode )
780  mFavoriteCollectionsView->setViewMode( QListView::ListMode );
781  else
782  Q_ASSERT(false); // we should never get here in hidden mode
783  mFavoriteCollectionsView->setDropActionMenuEnabled( kmkernel->showPopupAfterDnD() );
784  mFavoriteCollectionsView->setWordWrap( true );
785  mFavoriteCollectionsView->updateMode();
786  }
787 }
788 
789 //-----------------------------------------------------------------------------
790 void KMMainWidget::readConfig()
791 {
792  const bool oldLongFolderList = mLongFolderList;
793  const bool oldReaderWindowActive = mReaderWindowActive;
794  const bool oldReaderWindowBelow = mReaderWindowBelow;
795  const bool oldFavoriteFolderView = mEnableFavoriteFolderView;
796  const bool oldFolderQuickSearch = mEnableFolderQuickSearch;
797 
798  // on startup, the layout is always new and we need to relayout the widgets
799  bool layoutChanged = !mStartupDone;
800 
801  if ( mStartupDone )
802  {
803  readPreConfig();
804 
805  layoutChanged = ( oldLongFolderList != mLongFolderList ) ||
806  ( oldReaderWindowActive != mReaderWindowActive ) ||
807  ( oldReaderWindowBelow != mReaderWindowBelow ) ||
808  ( oldFavoriteFolderView != mEnableFavoriteFolderView );
809 
810  if ( layoutChanged ) {
811  deleteWidgets();
812  createWidgets();
813  Akonadi::Collection::Id id = -1;
814  if (mCurrentFolder && mCurrentFolder->collection().isValid() ) {
815  id = mCurrentFolder->collection().id();
816  }
817  restoreCollectionFolderViewConfig(id);
818  emit recreateGui();
819  } else if ( oldFolderQuickSearch != mEnableFolderQuickSearch ) {
820  if ( mEnableFolderQuickSearch )
821  mFolderTreeWidget->filterFolderLineEdit()->show();
822  else
823  mFolderTreeWidget->filterFolderLineEdit()->hide();
824  }
825  }
826 
827 
828  { // Read the config of the folder views and the header
829  if ( mMsgView ) {
830  mMsgView->readConfig();
831  }
832  mMessagePane->reloadGlobalConfiguration();
833  mFolderTreeWidget->readConfig();
834  if ( mFavoriteCollectionsView ) {
835  mFavoriteCollectionsView->readConfig();
836  }
837  refreshFavoriteFoldersViewProperties();
838  }
839 
840  { // area for config group "General"
841  if ( !mStartupDone )
842  {
843  // check mail on startup
844  // do it after building the kmmainwin, so that the progressdialog is available
845  QTimer::singleShot( 0, this, SLOT(slotCheckMailOnStartup()) );
846  }
847  }
848 
849  if ( layoutChanged ) {
850  layoutSplitters();
851  }
852 
853  updateMessageMenu();
854  updateFileMenu();
855  kmkernel->toggleSystemTray();
856 
857  connect( Akonadi::AgentManager::self(), SIGNAL(instanceAdded(Akonadi::AgentInstance)),
858  this, SLOT(updateFileMenu()) );
859  connect( Akonadi::AgentManager::self(), SIGNAL(instanceRemoved(Akonadi::AgentInstance)),
860  this, SLOT(updateFileMenu()) );
861 }
862 
863 //-----------------------------------------------------------------------------
864 void KMMainWidget::writeConfig(bool force)
865 {
866  // Don't save the sizes of all the widgets when we were never shown.
867  // This can happen in Kontact, where the KMail plugin is automatically
868  // loaded, but not necessarily shown.
869  // This prevents invalid sizes from being saved
870  if ( mWasEverShown ) {
871  // The height of the header widget can be 0, this happens when the user
872  // did not switch to the header widget onced and the "Welcome to KMail"
873  // HTML widget was shown the whole time
874  int headersHeight = mMessagePane->height();
875  if ( headersHeight == 0 )
876  headersHeight = height() / 2;
877 
878  GlobalSettings::self()->setSearchAndHeaderHeight( headersHeight );
879  GlobalSettings::self()->setSearchAndHeaderWidth( mMessagePane->width() );
880  if ( mFavoriteCollectionsView ) {
881  MailCommon::MailCommonSettings::self()->setFavoriteCollectionViewHeight( mFavoriteCollectionsView->height() );
882  GlobalSettings::self()->setFolderTreeHeight( mFolderTreeWidget->height() );
883  if ( !mLongFolderList ) {
884  GlobalSettings::self()->setFolderViewHeight( mFolderViewSplitter->height() );
885  }
886  }
887  else if ( !mLongFolderList && mFolderTreeWidget )
888  {
889  GlobalSettings::self()->setFolderTreeHeight( mFolderTreeWidget->height() );
890  }
891  if ( mFolderTreeWidget )
892  {
893  GlobalSettings::self()->setFolderViewWidth( mFolderTreeWidget->width() );
894  KSharedConfig::Ptr config = KMKernel::self()->config();
895  KConfigGroup group(config, "CollectionFolderView");
896 
897  ETMViewStateSaver saver;
898  saver.setView( mFolderTreeWidget->folderTreeView() );
899  saver.saveState( group );
900 
901  group.writeEntry( "HeaderState", mFolderTreeWidget->folderTreeView()->header()->saveState() );
902  //Work around from startup folder
903  group.deleteEntry( "Selection" );
904 #if 0
905  if (!GlobalSettings::self()->startSpecificFolderAtStartup()) {
906  group.deleteEntry( "Current" );
907  }
908 #endif
909  group.sync();
910  }
911 
912  if ( mMsgView ) {
913  if ( !mReaderWindowBelow )
914  GlobalSettings::self()->setReaderWindowWidth( mMsgView->width() );
915  mMsgView->viewer()->writeConfig(force);
916  GlobalSettings::self()->setReaderWindowHeight( mMsgView->height() );
917  }
918  }
919 }
920 
921 void KMMainWidget::writeReaderConfig()
922 {
923  if ( mWasEverShown ) {
924  if ( mMsgView ) {
925  mMsgView->viewer()->writeConfig();
926  }
927  }
928 }
929 
930 //-----------------------------------------------------------------------------
931 void KMMainWidget::deleteWidgets()
932 {
933  // Simply delete the top splitter, which always is mSplitter1, regardless
934  // of the layout. This deletes all children.
935  // akonadi action manager is created in createWidgets(), parented to this
936  // so not autocleaned up.
937  delete mAkonadiStandardActionManager;
938  mAkonadiStandardActionManager = 0;
939  delete mSplitter1;
940  mMsgView = 0;
941  mSearchAndTree = 0;
942  mFolderViewSplitter = 0;
943  mFavoriteCollectionsView = 0;
944  mSplitter1 = 0;
945  mSplitter2 = 0;
946  mFavoritesModel = 0;
947 }
948 
949 //-----------------------------------------------------------------------------
950 void KMMainWidget::createWidgets()
951 {
952  // Note that all widgets we create in this function have the parent 'this'.
953  // They will be properly reparented in layoutSplitters()
954 
955  //
956  // Create header view and search bar
957  //
958  FolderTreeWidget::TreeViewOptions opt = FolderTreeWidget::ShowUnreadCount;
959  opt |= FolderTreeWidget::UseLineEditForFiltering;
960  opt |= FolderTreeWidget::ShowCollectionStatisticAnimation;
961  opt |= FolderTreeWidget::DontKeyFilter;
962  mFolderTreeWidget = new FolderTreeWidget( this, mGUIClient, opt );
963 
964  connect( mFolderTreeWidget->folderTreeView(), SIGNAL(currentChanged(Akonadi::Collection)), this, SLOT(slotFolderChanged(Akonadi::Collection)) );
965 
966  connect( mFolderTreeWidget->folderTreeView()->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(updateFolderMenu()) );
967 
968  connect( mFolderTreeWidget->folderTreeView(), SIGNAL(prefereCreateNewTab(bool)), this, SLOT(slotCreateNewTab(bool)) );
969 
970  mFolderTreeWidget->setSelectionMode( QAbstractItemView::ExtendedSelection );
971  mMessagePane = new CollectionPane( !GlobalSettings::self()->startSpecificFolderAtStartup(), KMKernel::self()->entityTreeModel(),
972  mFolderTreeWidget->folderTreeView()->selectionModel(),
973  this );
974  connect( KMKernel::self()->entityTreeModel(), SIGNAL(collectionFetched(int)), this, SLOT(slotCollectionFetched(int)));
975 
976  mMessagePane->setXmlGuiClient( mGUIClient );
977  connect( mMessagePane, SIGNAL(messageSelected(Akonadi::Item)),
978  this, SLOT(slotMessageSelected(Akonadi::Item)) );
979  connect( mMessagePane, SIGNAL(fullSearchRequest()), this,SLOT(slotRequestFullSearchFromQuickSearch()) );
980  connect( mMessagePane, SIGNAL(selectionChanged()),
981  SLOT(startUpdateMessageActionsTimer()) );
982  connect( mMessagePane, SIGNAL(currentTabChanged()), this, SLOT(refreshMessageListSelection()) );
983  connect( mMessagePane, SIGNAL(messageActivated(Akonadi::Item)),
984  this, SLOT(slotMessageActivated(Akonadi::Item)) );
985  connect( mMessagePane, SIGNAL(messageStatusChangeRequest(Akonadi::Item,Akonadi::MessageStatus,Akonadi::MessageStatus)),
986  SLOT(slotMessageStatusChangeRequest(Akonadi::Item,Akonadi::MessageStatus,Akonadi::MessageStatus)) );
987 
988  connect( mMessagePane, SIGNAL(statusMessage(QString)),
989  BroadcastStatus::instance(), SLOT(setStatusMsg(QString)) );
990 
991 
992  //
993  // Create the reader window
994  //
995  if ( mReaderWindowActive ) {
996  mMsgView = new KMReaderWin( this, this, actionCollection(), 0 );
997  if ( mMsgActions ) {
998  mMsgActions->setMessageView( mMsgView );
999  }
1000  connect( mMsgView->viewer(), SIGNAL(replaceMsgByUnencryptedVersion()),
1001  this, SLOT(slotReplaceMsgByUnencryptedVersion()) );
1002  connect( mMsgView->viewer(), SIGNAL(popupMenu(Akonadi::Item,KUrl,KUrl,QPoint)),
1003  this, SLOT(slotMessagePopup(Akonadi::Item,KUrl,KUrl,QPoint)) );
1004  connect( mMsgView->viewer(), SIGNAL(moveMessageToTrash()),
1005  this, SLOT(slotMoveMessageToTrash()) );
1006  }
1007  else {
1008  if ( mMsgActions ) {
1009  mMsgActions->setMessageView( 0 );
1010  }
1011  }
1012 
1013  //
1014  // Create the folder tree
1015  // the "folder tree" consists of a quicksearch input field and the tree itself
1016  //
1017 
1018  mSearchAndTree = new QWidget( this );
1019  QVBoxLayout *vboxlayout = new QVBoxLayout;
1020  vboxlayout->setMargin(0);
1021  mSearchAndTree->setLayout( vboxlayout );
1022 
1023  vboxlayout->addWidget( mFolderTreeWidget );
1024 
1025  if ( !GlobalSettings::self()->enableFolderQuickSearch() ) {
1026  mFolderTreeWidget->filterFolderLineEdit()->hide();
1027  }
1028  //
1029  // Create the favorite folder view
1030  //
1031  mAkonadiStandardActionManager = new Akonadi::StandardMailActionManager( mGUIClient->actionCollection(), this );
1032  connect( mAkonadiStandardActionManager, SIGNAL(actionStateUpdated()), this, SLOT(slotAkonadiStandardActionUpdated()) );
1033 
1034  mAkonadiStandardActionManager->setCollectionSelectionModel( mFolderTreeWidget->folderTreeView()->selectionModel() );
1035  mAkonadiStandardActionManager->setItemSelectionModel( mMessagePane->currentItemSelectionModel() );
1036 
1037  if ( mEnableFavoriteFolderView ) {
1038 
1039  mFavoriteCollectionsView = new FavoriteCollectionWidget( mGUIClient, this );
1040  refreshFavoriteFoldersViewProperties();
1041 
1042  connect( mFavoriteCollectionsView, SIGNAL(currentChanged(Akonadi::Collection)), this, SLOT(slotFolderChanged(Akonadi::Collection)) );
1043 
1044  mFavoritesModel = new Akonadi::FavoriteCollectionsModel(
1045  mFolderTreeWidget->folderTreeView()->model(),
1046  KMKernel::self()->config()->group( "FavoriteCollections" ), this );
1047 
1048  mFavoriteCollectionsView->setModel( mFavoritesModel );
1049 
1050  Akonadi::CollectionStatisticsDelegate *delegate = new Akonadi::CollectionStatisticsDelegate( mFavoriteCollectionsView );
1051  delegate->setProgressAnimationEnabled( true );
1052  mFavoriteCollectionsView->setItemDelegate(delegate);
1053  delegate->setUnreadCountShown( true );
1054 
1055  mAkonadiStandardActionManager->setFavoriteCollectionsModel( mFavoritesModel );
1056  mAkonadiStandardActionManager->setFavoriteSelectionModel( mFavoriteCollectionsView->selectionModel() );
1057  }
1058 
1059  //Don't use mMailActionManager->createAllActions() to save memory by not
1060  //creating actions that doesn't make sense.
1061  QList<StandardActionManager::Type> standardActions;
1062  standardActions << StandardActionManager::CreateCollection
1063  << StandardActionManager::CopyCollections
1064  << StandardActionManager::DeleteCollections
1065  << StandardActionManager::SynchronizeCollections
1066  << StandardActionManager::CollectionProperties
1067  << StandardActionManager::CopyItems
1068  << StandardActionManager::Paste
1069  << StandardActionManager::DeleteItems
1070  << StandardActionManager::ManageLocalSubscriptions
1071  << StandardActionManager::CopyCollectionToMenu
1072  << StandardActionManager::CopyItemToMenu
1073  << StandardActionManager::MoveItemToMenu
1074  << StandardActionManager::MoveCollectionToMenu
1075  << StandardActionManager::CutItems
1076  << StandardActionManager::CutCollections
1077  << StandardActionManager::CreateResource
1078  << StandardActionManager::DeleteResources
1079  << StandardActionManager::ResourceProperties
1080  << StandardActionManager::SynchronizeResources
1081  << StandardActionManager::ToggleWorkOffline
1082  << StandardActionManager::SynchronizeCollectionsRecursive;
1083 
1084  Q_FOREACH( StandardActionManager::Type standardAction, standardActions ) {
1085  mAkonadiStandardActionManager->createAction( standardAction );
1086  }
1087 
1088 
1089  if (mEnableFavoriteFolderView) {
1090  QList<StandardActionManager::Type> favoriteActions;
1091  favoriteActions << StandardActionManager::AddToFavoriteCollections
1092  << StandardActionManager::RemoveFromFavoriteCollections
1093  << StandardActionManager::RenameFavoriteCollection
1094  << StandardActionManager::SynchronizeFavoriteCollections;
1095  Q_FOREACH( StandardActionManager::Type favoriteAction, favoriteActions) {
1096  mAkonadiStandardActionManager->createAction( favoriteAction );
1097  }
1098  }
1099 
1100  QList<StandardMailActionManager::Type> mailActions;
1101  mailActions << StandardMailActionManager::MarkAllMailAsRead
1102  << StandardMailActionManager::MoveToTrash
1103  << StandardMailActionManager::MoveAllToTrash
1104  << StandardMailActionManager::RemoveDuplicates
1105  << StandardMailActionManager::EmptyAllTrash
1106  << StandardMailActionManager::MarkMailAsRead
1107  << StandardMailActionManager::MarkMailAsUnread
1108  << StandardMailActionManager::MarkMailAsImportant
1109  << StandardMailActionManager::MarkMailAsActionItem;
1110 
1111  Q_FOREACH( StandardMailActionManager::Type mailAction, mailActions ) {
1112  mAkonadiStandardActionManager->createAction( mailAction );
1113  }
1114 
1115  mAkonadiStandardActionManager->interceptAction( Akonadi::StandardActionManager::CollectionProperties );
1116  connect( mAkonadiStandardActionManager->action( Akonadi::StandardActionManager::CollectionProperties ), SIGNAL(triggered(bool)), this, SLOT(slotCollectionProperties()) );
1117 
1118 
1119  //
1120  // Create all kinds of actions
1121  //
1122  mAkonadiStandardActionManager->action( Akonadi::StandardMailActionManager::RemoveDuplicates )->setShortcut( QKeySequence( Qt::CTRL + Qt::Key_Asterisk ) );
1123  mAkonadiStandardActionManager->interceptAction( Akonadi::StandardMailActionManager::RemoveDuplicates );
1124  connect( mAkonadiStandardActionManager->action( Akonadi::StandardMailActionManager::RemoveDuplicates ), SIGNAL(triggered(bool)), this, SLOT(slotRemoveDuplicates()) );
1125 
1126  {
1127  mCollectionProperties = mAkonadiStandardActionManager->action( Akonadi::StandardActionManager::CollectionProperties );
1128  }
1129  connect( kmkernel->folderCollectionMonitor(), SIGNAL(itemAdded(Akonadi::Item,Akonadi::Collection)),
1130  SLOT(slotItemAdded(Akonadi::Item,Akonadi::Collection)) );
1131  connect( kmkernel->folderCollectionMonitor(), SIGNAL(itemRemoved(Akonadi::Item)),
1132  SLOT(slotItemRemoved(Akonadi::Item)) );
1133  connect( kmkernel->folderCollectionMonitor(), SIGNAL(itemMoved(Akonadi::Item,Akonadi::Collection,Akonadi::Collection)),
1134  SLOT(slotItemMoved(Akonadi::Item,Akonadi::Collection,Akonadi::Collection)) );
1135  connect( kmkernel->folderCollectionMonitor(), SIGNAL(collectionChanged(Akonadi::Collection,QSet<QByteArray>)), SLOT(slotCollectionChanged(Akonadi::Collection,QSet<QByteArray>)) );
1136 
1137  connect( kmkernel->folderCollectionMonitor(), SIGNAL(collectionStatisticsChanged(Akonadi::Collection::Id,Akonadi::CollectionStatistics)), SLOT(slotCollectionStatisticsChanged(Akonadi::Collection::Id,Akonadi::CollectionStatistics)) );
1138 
1139 }
1140 
1141 void KMMainWidget::updateMoveAction( const Akonadi::CollectionStatistics& statistic )
1142 {
1143  const bool hasUnreadMails = (statistic.unreadCount() > 0);
1144  const bool hasMails = (statistic.count()>0);
1145  updateMoveAction(hasUnreadMails,hasMails);
1146 }
1147 
1148 void KMMainWidget::updateMoveAction( bool hasUnreadMails, bool hasMails )
1149 {
1150  const bool enable_goto_unread = hasUnreadMails
1151  || (GlobalSettings::self()->loopOnGotoUnread() == GlobalSettings::EnumLoopOnGotoUnread::LoopInAllFolders)
1152  || (GlobalSettings::self()->loopOnGotoUnread() == GlobalSettings::EnumLoopOnGotoUnread::LoopInAllMarkedFolders);
1153  actionCollection()->action( QLatin1String("go_next_message") )->setEnabled( hasMails );
1154  actionCollection()->action( QLatin1String("go_next_unread_message") )->setEnabled( enable_goto_unread );
1155  actionCollection()->action( QLatin1String("go_prev_message") )->setEnabled( hasMails );
1156  actionCollection()->action( QLatin1String("go_prev_unread_message") )->setEnabled( enable_goto_unread );
1157  if ( mAkonadiStandardActionManager->action( Akonadi::StandardMailActionManager::MarkAllMailAsRead ) ) {
1158  mAkonadiStandardActionManager->action( Akonadi::StandardMailActionManager::MarkAllMailAsRead )->setEnabled(hasUnreadMails);
1159  }
1160 }
1161 
1162 void KMMainWidget::updateAllToTrashAction(int statistics)
1163 {
1164  bool multiFolder = false;
1165  if ( mFolderTreeWidget ) {
1166  multiFolder = mFolderTreeWidget->selectedCollections().count() > 1;
1167  }
1168  if ( mAkonadiStandardActionManager->action( Akonadi::StandardMailActionManager::MoveAllToTrash ) ) {
1169  const bool folderWithContent = mCurrentFolder && !mCurrentFolder->isStructural();
1170  mAkonadiStandardActionManager->action( Akonadi::StandardMailActionManager::MoveAllToTrash )->setEnabled( folderWithContent
1171  && ( statistics > 0 )
1172  && mCurrentFolder->canDeleteMessages()
1173  && !multiFolder );
1174  }
1175 }
1176 
1177 void KMMainWidget::slotCollectionStatisticsChanged( const Akonadi::Collection::Id id, const Akonadi::CollectionStatistics& statistic )
1178 {
1179  if ( id == CommonKernel->outboxCollectionFolder().id() ) {
1180  const qint64 nbMsgOutboxCollection = statistic.count();
1181  mSendQueued->setEnabled( nbMsgOutboxCollection > 0 );
1182  mSendActionMenu->setEnabled( nbMsgOutboxCollection > 0 );
1183  } else if ( mCurrentFolder && ( id == mCurrentFolder->collection().id() ) ) {
1184  updateMoveAction( statistic );
1185  updateAllToTrashAction(statistic.count());
1186  mCurrentFolder->setCollection(MailCommon::Util::updatedCollection( mCurrentFolder->collection() ));
1187  }
1188 }
1189 
1190 void KMMainWidget::slotCreateNewTab( bool preferNewTab )
1191 {
1192  mMessagePane->setPreferEmptyTab( preferNewTab );
1193 }
1194 
1195 void KMMainWidget::slotCollectionChanged( const Akonadi::Collection&collection, const QSet<QByteArray>&set )
1196 {
1197  if ( mCurrentFolder
1198  && ( collection == mCurrentFolder->collection() )
1199  && ( set.contains( "MESSAGEFOLDER" ) || set.contains( "expirationcollectionattribute" ) ) ) {
1200  if ( set.contains( "MESSAGEFOLDER" ) )
1201  mMessagePane->resetModelStorage();
1202  else {
1203  mCurrentFolder->setCollection( collection );
1204  }
1205  } else if ( set.contains( "ENTITYDISPLAY" ) || set.contains( "NAME" ) ) {
1206 
1207  QIcon icon = KIcon( QLatin1String( "folder" ) );
1208  QString text;
1209 
1210  const QModelIndex idx = Akonadi::EntityTreeModel::modelIndexForCollection( KMKernel::self()->collectionModel(), collection );
1211  if ( idx.isValid() ) {
1212  text = idx.data().toString();
1213  icon = idx.data( Qt::DecorationRole ).value<QIcon>();
1214  mMessagePane->updateTabIconText( collection, text,icon );
1215  }
1216  }
1217 }
1218 
1219 
1220 void KMMainWidget::slotItemAdded( const Akonadi::Item &msg, const Akonadi::Collection &col )
1221 {
1222 
1223  if ( col.isValid() ) {
1224  if ( col == CommonKernel->outboxCollectionFolder() ) {
1225  startUpdateMessageActionsTimer();
1226  }
1227  }
1228 }
1229 
1230 void KMMainWidget::slotItemRemoved( const Akonadi::Item & item)
1231 {
1232  if ( item.isValid() && item.parentCollection().isValid() && ( item.parentCollection() == CommonKernel->outboxCollectionFolder() ) ) {
1233  startUpdateMessageActionsTimer();
1234  }
1235 }
1236 
1237 void KMMainWidget::slotItemMoved( const Akonadi::Item &item, const Akonadi::Collection &from, const Akonadi::Collection &to )
1238 {
1239  if ( item.isValid() && ( ( from.id() == CommonKernel->outboxCollectionFolder().id() )
1240  || to.id() == CommonKernel->outboxCollectionFolder().id() ) ) {
1241  startUpdateMessageActionsTimer();
1242  }
1243 }
1244 
1245 //-------------------------------------------------------------------------
1246 void KMMainWidget::slotFocusQuickSearch()
1247 {
1248  mMessagePane->focusQuickSearch();
1249 }
1250 
1251 //-------------------------------------------------------------------------
1252 bool KMMainWidget::slotSearch()
1253 {
1254  // check if we can search at all, ie. Nepomuk is running and email indexing is enabled
1255  if ( !Nepomuk2::ResourceManager::instance()->initialized() ) {
1256  KMessageBox::information( this, i18n( "The Nepomuk semantic search service is not available. Searching is not possible without it. "
1257  "You can enable it in \"System Settings\"." ), i18n( "Search Not Available" ) );
1258  return false;
1259  }
1260 
1261  {
1262  KConfig config( QLatin1String("akonadi_nepomuk_feederrc") );
1263  KConfigGroup cfgGroup( &config, "akonadi_nepomuk_email_feeder" );
1264  if ( !cfgGroup.readEntry( "Enabled", true ) ) {
1265  KMessageBox::information( this, i18n( "You have disabled full text indexing of emails. Searching is not possible without that. "
1266  "You can enable it in \"System Settings\". Note that searching will only be possible after "
1267  "your emails have been fully indexed, which can take some time." ) );
1268  return false;
1269  }
1270  }
1271 
1272 
1273  if (!mSearchWin)
1274  {
1275  mSearchWin = new SearchWindow(this, mCurrentFolder ? mCurrentFolder->collection() : Akonadi::Collection());
1276  mSearchWin->setModal( false );
1277  mSearchWin->setObjectName( QLatin1String("Search") );
1278  }
1279  else
1280  {
1281  mSearchWin->activateFolder(mCurrentFolder ? mCurrentFolder->collection() : Akonadi::Collection());
1282  }
1283 
1284  mSearchWin->show();
1285  KWindowSystem::activateWindow( mSearchWin->winId() );
1286  return true;
1287 }
1288 
1289 
1290 //-----------------------------------------------------------------------------
1291 void KMMainWidget::slotHelp()
1292 {
1293  KToolInvocation::invokeHelp();
1294 }
1295 
1296 
1297 //-----------------------------------------------------------------------------
1298 void KMMainWidget::slotFilter()
1299 {
1300  FilterIf->openFilterDialog( true );
1301 }
1302 
1303 void KMMainWidget::slotManageSieveScripts()
1304 {
1305  if ( !kmkernel->askToGoOnline() ) {
1306  return;
1307  }
1308  if (mManageSieveDialog)
1309  return;
1310 
1311  mManageSieveDialog = new KSieveUi::ManageSieveScriptsDialog( this );
1312  mManageSieveDialog->show();
1313 }
1314 
1315 
1316 //-----------------------------------------------------------------------------
1317 void KMMainWidget::slotAddrBook()
1318 {
1319  KRun::runCommand(QLatin1String("kaddressbook"), window());
1320 }
1321 
1322 
1323 //-----------------------------------------------------------------------------
1324 void KMMainWidget::slotImport()
1325 {
1326  KRun::runCommand(QLatin1String("kmailcvt"), window());
1327 }
1328 
1329 //-----------------------------------------------------------------------------
1330 void KMMainWidget::slotCheckMail()
1331 {
1332  kmkernel->checkMail();
1333 }
1334 
1335 //-----------------------------------------------------------------------------
1336 void KMMainWidget::slotCheckMailOnStartup()
1337 {
1338  kmkernel->checkMailOnStartup();
1339 }
1340 
1341 //-----------------------------------------------------------------------------
1342 void KMMainWidget::slotCheckOneAccount( QAction* item )
1343 {
1344  if ( !item ) {
1345  return;
1346  }
1347 
1348  Akonadi::AgentInstance agent = Akonadi::AgentManager::self()->instance( item->data().toString() );
1349  if ( agent.isValid() ) {
1350  if ( !agent.isOnline() ) {
1351  agent.setIsOnline( true );
1352  }
1353  agent.synchronize();
1354  } else {
1355  kDebug() << "account with identifier" << item->data().toString() << "not found";
1356  }
1357 }
1358 
1359 //-----------------------------------------------------------------------------
1360 void KMMainWidget::slotCompose()
1361 {
1362  KMail::Composer * win;
1363  KMime::Message::Ptr msg( new KMime::Message() );
1364 
1365  bool forceCursorPosition = false;
1366  if ( mCurrentFolder ) {
1367  MessageHelper::initHeader( msg, KMKernel::self()->identityManager(), mCurrentFolder->identity() );
1368  //Laurent: bug 289905
1369  /*
1370  if ( mCurrentFolder->collection().isValid() && mCurrentFolder->putRepliesInSameFolder() ) {
1371  KMime::Headers::Generic *header = new KMime::Headers::Generic( "X-KMail-Fcc", msg.get(), QString::number( mCurrentFolder->collection().id() ), "utf-8" );
1372  msg->setHeader( header );
1373  }
1374  */
1375  TemplateParser::TemplateParser parser( msg, TemplateParser::TemplateParser::NewMessage );
1376  parser.setIdentityManager( KMKernel::self()->identityManager() );
1377  parser.process( msg, mCurrentFolder->collection() );
1378  win = KMail::makeComposer( msg, false, false, KMail::Composer::New, mCurrentFolder->identity() );
1379  win->setCollectionForNewMessage( mCurrentFolder->collection() );
1380  forceCursorPosition = parser.cursorPositionWasSet();
1381  } else {
1382  MessageHelper::initHeader( msg, KMKernel::self()->identityManager() );
1383  TemplateParser::TemplateParser parser( msg, TemplateParser::TemplateParser::NewMessage );
1384  parser.setIdentityManager( KMKernel::self()->identityManager() );
1385  parser.process( KMime::Message::Ptr(), Akonadi::Collection() );
1386  win = KMail::makeComposer( msg, false, false, KMail::Composer::New );
1387  forceCursorPosition = parser.cursorPositionWasSet();
1388  }
1389  if (forceCursorPosition) {
1390  win->setFocusToEditor();
1391  }
1392  win->show();
1393 
1394 }
1395 
1396 //-----------------------------------------------------------------------------
1397 // TODO: do we want the list sorted alphabetically?
1398 void KMMainWidget::slotShowNewFromTemplate()
1399 {
1400  if ( mCurrentFolder )
1401  {
1402  const KPIMIdentities::Identity & ident =
1403  kmkernel->identityManager()->identityForUoidOrDefault( mCurrentFolder->identity() );
1404  mTemplateFolder = CommonKernel->collectionFromId( ident.templates().toLongLong() );
1405  }
1406 
1407  if ( !mTemplateFolder.isValid() ) {
1408  mTemplateFolder = CommonKernel->templatesCollectionFolder();
1409  }
1410  if ( !mTemplateFolder.isValid() )
1411  return;
1412 
1413  mTemplateMenu->menu()->clear();
1414 
1415  Akonadi::ItemFetchJob *job = new Akonadi::ItemFetchJob( mTemplateFolder );
1416  job->fetchScope().setAncestorRetrieval( ItemFetchScope::Parent );
1417  job->fetchScope().fetchFullPayload();
1418  connect( job, SIGNAL(result(KJob*)), SLOT(slotDelayedShowNewFromTemplate(KJob*)) );
1419 }
1420 
1421 void KMMainWidget::slotDelayedShowNewFromTemplate( KJob *job )
1422 {
1423  Akonadi::ItemFetchJob *fetchJob = qobject_cast<Akonadi::ItemFetchJob*>( job );
1424 
1425  const Akonadi::Item::List items = fetchJob->items();
1426  const int numberOfItems = items.count();
1427  for ( int idx = 0; idx < numberOfItems; ++idx ) {
1428  KMime::Message::Ptr msg = MessageCore::Util::message( items.at( idx ) );
1429  if ( msg ) {
1430  QString subj = msg->subject()->asUnicodeString();
1431  if ( subj.isEmpty() )
1432  subj = i18n("No Subject");
1433 
1434  QAction *templateAction = mTemplateMenu->menu()->addAction(KStringHandler::rsqueeze( subj.replace( QLatin1Char('&'), QLatin1String("&&") ) ) );
1435  QVariant var;
1436  var.setValue( items.at( idx ) );
1437  templateAction->setData( var );
1438  }
1439  }
1440 
1441  // If there are no templates available, add a menu entry which informs
1442  // the user about this.
1443  if ( mTemplateMenu->menu()->actions().isEmpty() ) {
1444  QAction *noAction = mTemplateMenu->menu()->addAction(
1445  i18n( "(no templates)" ) );
1446  noAction->setEnabled( false );
1447  }
1448 }
1449 
1450 
1451 //-----------------------------------------------------------------------------
1452 void KMMainWidget::slotNewFromTemplate( QAction *action )
1453 {
1454 
1455  if ( !mTemplateFolder.isValid() )
1456  return;
1457  const Akonadi::Item item = action->data().value<Akonadi::Item>();
1458  newFromTemplate( item );
1459 }
1460 
1461 
1462 //-----------------------------------------------------------------------------
1463 void KMMainWidget::newFromTemplate( const Akonadi::Item &msg )
1464 {
1465  if ( !msg.isValid() )
1466  return;
1467  KMCommand *command = new KMUseTemplateCommand( this, msg );
1468  command->start();
1469 }
1470 
1471 
1472 //-----------------------------------------------------------------------------
1473 void KMMainWidget::slotPostToML()
1474 {
1475  if ( mCurrentFolder && mCurrentFolder->isMailingListEnabled() ) {
1476  if (KMail::Util::mailingListPost( mCurrentFolder )) {
1477  return;
1478  }
1479  }
1480  slotCompose();
1481 }
1482 
1483 //-----------------------------------------------------------------------------
1484 void KMMainWidget::slotFolderMailingListProperties()
1485 {
1486  showCollectionProperties( QLatin1String( "KMail::CollectionMailingListPage" ) );
1487 }
1488 
1489 //-----------------------------------------------------------------------------
1490 void KMMainWidget::slotShowFolderShortcutDialog()
1491 {
1492  showCollectionProperties( QLatin1String( "KMail::CollectionShortcutPage" ) );
1493 }
1494 
1495 //-----------------------------------------------------------------------------
1496 void KMMainWidget::slotExpireFolder()
1497 {
1498  if ( !mCurrentFolder )
1499  return;
1500  bool mustDeleteExpirationAttribute = false;
1501  MailCommon::ExpireCollectionAttribute *attr = MailCommon::ExpireCollectionAttribute::expirationCollectionAttribute( mCurrentFolder->collection(), mustDeleteExpirationAttribute );
1502 ;
1503  bool canBeExpired = true;
1504  if ( !attr->isAutoExpire() ) {
1505  canBeExpired = false;
1506  } else if ( attr->unreadExpireUnits() == MailCommon::ExpireCollectionAttribute::ExpireNever &&
1507  attr->readExpireUnits() == MailCommon::ExpireCollectionAttribute::ExpireNever ) {
1508  canBeExpired = false;
1509  }
1510 
1511  if ( !canBeExpired ) {
1512  const QString message = i18n( "This folder does not have any expiry options set" );
1513  KMessageBox::information( this, message );
1514  if ( mustDeleteExpirationAttribute )
1515  delete attr;
1516  return;
1517  }
1518 
1519  if ( GlobalSettings::self()->warnBeforeExpire() ) {
1520  const QString message = i18n( "<qt>Are you sure you want to expire the folder <b>%1</b>?</qt>",
1521  Qt::escape( mCurrentFolder->name() ) );
1522  if ( KMessageBox::warningContinueCancel( this, message, i18n( "Expire Folder" ),
1523  KGuiItem( i18n( "&Expire" ) ) )
1524  != KMessageBox::Continue ) {
1525  if ( mustDeleteExpirationAttribute )
1526  delete attr;
1527  return;
1528  }
1529  }
1530 
1531  MailCommon::Util::expireOldMessages( mCurrentFolder->collection(), true /*immediate*/ );
1532  if ( mustDeleteExpirationAttribute )
1533  delete attr;
1534 }
1535 
1536 //-----------------------------------------------------------------------------
1537 void KMMainWidget::slotEmptyFolder()
1538 {
1539  if (!mCurrentFolder) return;
1540  const bool isTrash = CommonKernel->folderIsTrash( mCurrentFolder->collection() );
1541  if ( GlobalSettings::self()->confirmBeforeEmpty() )
1542  {
1543  const QString title = (isTrash) ? i18n("Empty Trash") : i18n("Move to Trash");
1544  const QString text = (isTrash) ?
1545  i18n("Are you sure you want to empty the trash folder?") :
1546  i18n("<qt>Are you sure you want to move all messages from "
1547  "folder <b>%1</b> to the trash?</qt>", Qt::escape( mCurrentFolder->name() ) );
1548 
1549  if (KMessageBox::warningContinueCancel(this, text, title, KGuiItem( title, QLatin1String("user-trash")))
1550  != KMessageBox::Continue) return;
1551  }
1552 #ifndef QT_NO_CURSOR
1553  MessageViewer::KCursorSaver busy( MessageViewer::KBusyPtr::busy() );
1554 #endif
1555  slotMarkAll();
1556  if (isTrash) {
1557  /* Don't ask for confirmation again when deleting, the user has already
1558  confirmed. */
1559  slotDeleteMsg( false );
1560  }
1561  else
1562  slotTrashSelectedMessages();
1563 
1564  if (mMsgView)
1565  mMsgView->clearCache();
1566 
1567  if ( !isTrash )
1568  BroadcastStatus::instance()->setStatusMsg(i18n("Moved all messages to the trash"));
1569 
1570  updateMessageActions();
1571 
1572  // Disable empty trash/move all to trash action - we've just deleted/moved
1573  // all folder contents.
1574  mAkonadiStandardActionManager->action( Akonadi::StandardMailActionManager::MoveAllToTrash )->setEnabled( false );
1575 }
1576 
1577 //-----------------------------------------------------------------------------
1578 void KMMainWidget::slotArchiveFolder()
1579 {
1580  if ( mCurrentFolder && mCurrentFolder->collection().isValid() ) {
1581  KMail::ArchiveFolderDialog archiveDialog;
1582  archiveDialog.setFolder( mCurrentFolder->collection() );
1583  archiveDialog.exec();
1584  }
1585 }
1586 
1587 //-----------------------------------------------------------------------------
1588 void KMMainWidget::slotRemoveFolder()
1589 {
1590  if ( !mCurrentFolder ) return;
1591  if ( !mCurrentFolder->collection().isValid() ) return;
1592  if ( mCurrentFolder->isSystemFolder() ) return;
1593  if ( mCurrentFolder->isReadOnly() ) return;
1594 
1595  Akonadi::CollectionFetchJob *job = new Akonadi::CollectionFetchJob( mCurrentFolder->collection(), CollectionFetchJob::FirstLevel, this );
1596  job->fetchScope().setContentMimeTypes( QStringList() << KMime::Message::mimeType() );
1597  job->setProperty( "collectionId", mCurrentFolder->collection().id() );
1598  connect( job, SIGNAL(result(KJob*)), SLOT(slotDelayedRemoveFolder(KJob*)) );
1599 }
1600 
1601 void KMMainWidget::slotDelayedRemoveFolder( KJob *job )
1602 {
1603  const Akonadi::CollectionFetchJob *fetchJob = qobject_cast<Akonadi::CollectionFetchJob*>( job );
1604  Akonadi::Collection::List listOfCollection = fetchJob->collections();
1605  const bool hasNotSubDirectory = listOfCollection.isEmpty();
1606 
1607  const Akonadi::Collection::Id id = fetchJob->property( "collectionId" ).toLongLong();
1608  Akonadi::Collection col = MailCommon::Util::updatedCollection(CommonKernel->collectionFromId( id ));
1609  QDir dir;
1610  QString str;
1611  QString title;
1612  QString buttonLabel;
1613  if ( col.resource() == QLatin1String( "akonadi_search_resource" ) ) {
1614  title = i18n("Delete Search");
1615  str = i18n("<qt>Are you sure you want to delete the search <b>%1</b>?<br />"
1616  "Any messages it shows will still be available in their original folder.</qt>",
1617  Qt::escape( col.name() ) );
1618  buttonLabel = i18nc("@action:button Delete search", "&Delete");
1619  } else {
1620  title = i18n("Delete Folder");
1621 
1622 
1623  if ( col.statistics().count() == 0 ) {
1624  if ( hasNotSubDirectory ) {
1625  str = i18n("<qt>Are you sure you want to delete the empty folder "
1626  "<b>%1</b>?</qt>",
1627  Qt::escape( col.name() ) );
1628  } else {
1629  str = i18n("<qt>Are you sure you want to delete the empty folder "
1630  "<resource>%1</resource> and all its subfolders? Those subfolders might "
1631  "not be empty and their contents will be discarded as well. "
1632  "<p><b>Beware</b> that discarded messages are not saved "
1633  "into your Trash folder and are permanently deleted.</p></qt>",
1634  Qt::escape( col.name() ) );
1635  }
1636  } else {
1637  if ( hasNotSubDirectory ) {
1638  str = i18n("<qt>Are you sure you want to delete the folder "
1639  "<resource>%1</resource>, discarding its contents? "
1640  "<p><b>Beware</b> that discarded messages are not saved "
1641  "into your Trash folder and are permanently deleted.</p></qt>",
1642  Qt::escape( col.name() ) );
1643  }else {
1644  str = i18n("<qt>Are you sure you want to delete the folder <resource>%1</resource> "
1645  "and all its subfolders, discarding their contents? "
1646  "<p><b>Beware</b> that discarded messages are not saved "
1647  "into your Trash folder and are permanently deleted.</p></qt>",
1648  Qt::escape( col.name() ) );
1649  }
1650  }
1651  buttonLabel = i18nc("@action:button Delete folder", "&Delete");
1652  }
1653 
1654  if ( KMessageBox::warningContinueCancel( this, str, title,
1655  KGuiItem( buttonLabel, QLatin1String("edit-delete" )),
1656  KStandardGuiItem::cancel(), QString(),
1657  KMessageBox::Notify | KMessageBox::Dangerous )
1658  == KMessageBox::Continue )
1659  {
1660  kmkernel->checkFolderFromResources( listOfCollection<<col );
1661 
1662  if (col.id() == mCurrentFolder->collection().id())
1663  mCurrentFolder.clear();
1664 
1665  Akonadi::CollectionDeleteJob *job = new Akonadi::CollectionDeleteJob( col );
1666  connect( job, SIGNAL(result(KJob*)), this, SLOT(slotDeletionCollectionResult(KJob*)) );
1667  }
1668 }
1669 
1670 void KMMainWidget::slotDeletionCollectionResult(KJob* job)
1671 {
1672  if ( job ) {
1673  if (Util::showJobErrorMessage( job )) {
1674  return;
1675  }
1676  }
1677 }
1678 
1679 //-----------------------------------------------------------------------------
1680 void KMMainWidget::slotExpireAll()
1681 {
1682  if ( GlobalSettings::self()->warnBeforeExpire() ) {
1683  const int ret = KMessageBox::warningContinueCancel(KMainWindow::memberList().first(),
1684  i18n("Are you sure you want to expire all old messages?"),
1685  i18n("Expire Old Messages?"), KGuiItem(i18n("Expire")));
1686  if (ret != KMessageBox::Continue) {
1687  return;
1688  }
1689  }
1690 
1691  kmkernel->expireAllFoldersNow();
1692 }
1693 
1694 
1695 //-----------------------------------------------------------------------------
1696 void KMMainWidget::slotOverrideHtml()
1697 {
1698  if ( mHtmlPref == mFolderHtmlPref ) {
1699  int result = KMessageBox::warningContinueCancel( this,
1700  // the warning text is taken from configuredialog.cpp:
1701  i18n( "Use of HTML in mail will make you more vulnerable to "
1702  "\"spam\" and may increase the likelihood that your system will be "
1703  "compromised by other present and anticipated security exploits." ),
1704  i18n( "Security Warning" ),
1705  KGuiItem(i18n( "Use HTML" )),
1706  KStandardGuiItem::cancel(),
1707  QLatin1String("OverrideHtmlWarning"), 0);
1708  if ( result == KMessageBox::Cancel ) {
1709  mPreferHtmlAction->setChecked( false );
1710  return;
1711  }
1712  }
1713  mFolderHtmlPref = !mFolderHtmlPref;
1714 
1715  //Update mPrefererHtmlLoadExtAction
1716  mPreferHtmlLoadExtAction->setEnabled( mCurrentFolder && (mHtmlPref ? !mFolderHtmlPref : mFolderHtmlPref) ? true : false );
1717 
1718  if (mMsgView) {
1719  mMsgView->setHtmlOverride(mFolderHtmlPref);
1720  mMsgView->update( true );
1721  }
1722 }
1723 
1724 //-----------------------------------------------------------------------------
1725 void KMMainWidget::slotOverrideHtmlLoadExt()
1726 {
1727  if ( mHtmlLoadExtPref == mFolderHtmlLoadExtPref ) {
1728  int result = KMessageBox::warningContinueCancel( this,
1729  // the warning text is taken from configuredialog.cpp:
1730  i18n( "Loading external references in html mail will make you more vulnerable to "
1731  "\"spam\" and may increase the likelihood that your system will be "
1732  "compromised by other present and anticipated security exploits." ),
1733  i18n( "Security Warning" ),
1734  KGuiItem(i18n( "Load External References" )),
1735  KStandardGuiItem::cancel(),
1736  QLatin1String("OverrideHtmlLoadExtWarning"), 0);
1737  if ( result == KMessageBox::Cancel ) {
1738  mPreferHtmlLoadExtAction->setChecked( false );
1739  return;
1740  }
1741  }
1742  mFolderHtmlLoadExtPref = !mFolderHtmlLoadExtPref;
1743 
1744  if (mMsgView) {
1745  mMsgView->setHtmlLoadExtOverride(mFolderHtmlLoadExtPref);
1746  mMsgView->update( true );
1747  }
1748 }
1749 
1750 //-----------------------------------------------------------------------------
1751 void KMMainWidget::slotMessageQueuedOrDrafted()
1752 {
1753  if (!CommonKernel->folderIsDraftOrOutbox(mCurrentFolder->collection()))
1754  return;
1755  if (mMsgView)
1756  mMsgView->update(true);
1757 }
1758 
1759 
1760 //-----------------------------------------------------------------------------
1761 void KMMainWidget::slotForwardInlineMsg()
1762 {
1763  if ( !mCurrentFolder ) {
1764  return;
1765  }
1766 
1767  const QList<Akonadi::Item> selectedMessages = mMessagePane->selectionAsMessageItemList();
1768  if ( selectedMessages.isEmpty() )
1769  return;
1770  KMForwardCommand * command = new KMForwardCommand(
1771  this, selectedMessages, mCurrentFolder->identity()
1772  );
1773 
1774  command->start();
1775 }
1776 
1777 
1778 //-----------------------------------------------------------------------------
1779 void KMMainWidget::slotForwardAttachedMsg()
1780 {
1781  if ( !mCurrentFolder ) {
1782  return;
1783  }
1784 
1785  const QList<Akonadi::Item> selectedMessages = mMessagePane->selectionAsMessageItemList();
1786  if ( selectedMessages.isEmpty() )
1787  return;
1788  KMForwardAttachedCommand * command = new KMForwardAttachedCommand(
1789  this, selectedMessages, mCurrentFolder->identity()
1790  );
1791 
1792  command->start();
1793 }
1794 
1795 
1796 //-----------------------------------------------------------------------------
1797 void KMMainWidget::slotUseTemplate()
1798 {
1799  newFromTemplate( mMessagePane->currentItem() );
1800 }
1801 
1802 
1803 //-----------------------------------------------------------------------------
1804 void KMMainWidget::slotResendMsg()
1805 {
1806  const Akonadi::Item msg = mMessagePane->currentItem();
1807  if ( !msg.isValid() )
1808  return;
1809  KMCommand *command = new KMResendMessageCommand( this, msg );
1810 
1811  command->start();
1812 }
1813 
1814 //-----------------------------------------------------------------------------
1815 // Message moving and permanent deletion
1816 //
1817 
1818 void KMMainWidget::moveMessageSelected( MessageList::Core::MessageItemSetReference ref, const Akonadi::Collection &dest, bool confirmOnDeletion )
1819 {
1820  QList<Akonadi::Item> selectMsg = mMessagePane->itemListFromPersistentSet( ref );
1821  // If this is a deletion, ask for confirmation
1822  if ( !dest.isValid() && confirmOnDeletion )
1823  {
1824  int ret = KMessageBox::warningContinueCancel(
1825  this,
1826  i18np(
1827  "<qt>Do you really want to delete the selected message?<br />"
1828  "Once deleted, it cannot be restored.</qt>",
1829  "<qt>Do you really want to delete the %1 selected messages?<br />"
1830  "Once deleted, they cannot be restored.</qt>",
1831  selectMsg.count()
1832  ),
1833  selectMsg.count() > 1 ? i18n( "Delete Messages" ) : i18n( "Delete Message" ),
1834  KStandardGuiItem::del(),
1835  KStandardGuiItem::cancel(),
1836  QLatin1String("NoConfirmDelete")
1837  );
1838  if ( ret == KMessageBox::Cancel )
1839  {
1840  mMessagePane->deletePersistentSet( ref );
1841  return; // user canceled the action
1842  }
1843  }
1844  mMessagePane->markMessageItemsAsAboutToBeRemoved( ref, true );
1845  // And stuff them into a KMMoveCommand :)
1846  KMMoveCommand *command = new KMMoveCommand( dest, selectMsg,ref );
1847  QObject::connect(
1848  command, SIGNAL(moveDone(KMMoveCommand*)),
1849  this, SLOT(slotMoveMessagesCompleted(KMMoveCommand*))
1850  );
1851  command->start();
1852 
1853  if ( dest.isValid() )
1854  BroadcastStatus::instance()->setStatusMsg( i18n( "Moving messages..." ) );
1855  else
1856  BroadcastStatus::instance()->setStatusMsg( i18n( "Deleting messages..." ) );
1857 }
1858 
1859 void KMMainWidget::slotMoveMessagesCompleted( KMMoveCommand *command )
1860 {
1861  Q_ASSERT( command );
1862  mMessagePane->markMessageItemsAsAboutToBeRemoved( command->refSet(), false );
1863  mMessagePane->deletePersistentSet( command->refSet() );
1864  // Bleah :D
1865  const bool moveWasReallyADelete = !command->destFolder().isValid();
1866 
1867  if ( command->result() == KMCommand::OK )
1868  {
1869  if ( moveWasReallyADelete )
1870  BroadcastStatus::instance()->setStatusMsg( i18n( "Messages deleted successfully." ) );
1871  else
1872  BroadcastStatus::instance()->setStatusMsg( i18n( "Messages moved successfully." ) );
1873  } else {
1874  if ( moveWasReallyADelete )
1875  {
1876  if ( command->result() == KMCommand::Failed )
1877  BroadcastStatus::instance()->setStatusMsg( i18n( "Deleting messages failed." ) );
1878  else
1879  BroadcastStatus::instance()->setStatusMsg( i18n( "Deleting messages canceled." ) );
1880  } else {
1881  if ( command->result() == KMCommand::Failed )
1882  BroadcastStatus::instance()->setStatusMsg( i18n( "Moving messages failed." ) );
1883  else
1884  BroadcastStatus::instance()->setStatusMsg( i18n( "Moving messages canceled." ) );
1885  }
1886  }
1887  // The command will autodelete itself and will also kill the set.
1888 }
1889 
1890 void KMMainWidget::slotDeleteMsg( bool confirmDelete )
1891 {
1892  // Create a persistent message set from the current selection
1893  MessageList::Core::MessageItemSetReference ref = mMessagePane->selectionAsPersistentSet();
1894  if ( ref != -1 )
1895  moveMessageSelected( ref, Akonadi::Collection(), confirmDelete );
1896 }
1897 
1898 void KMMainWidget::slotDeleteThread( bool confirmDelete )
1899 {
1900  // Create a persistent set from the current thread.
1901  MessageList::Core::MessageItemSetReference ref = mMessagePane->currentThreadAsPersistentSet();
1902  if ( ref != -1 )
1903  moveMessageSelected( ref, Akonadi::Collection(), confirmDelete );
1904 }
1905 
1906 FolderSelectionDialog* KMMainWidget::moveOrCopyToDialog()
1907 {
1908  if ( !mMoveOrCopyToDialog ) {
1909  FolderSelectionDialog::SelectionFolderOption options = FolderSelectionDialog::HideVirtualFolder;
1910  mMoveOrCopyToDialog = new FolderSelectionDialog( this, options );
1911  mMoveOrCopyToDialog->setModal( true );
1912  }
1913  return mMoveOrCopyToDialog;
1914 }
1915 
1916 FolderSelectionDialog* KMMainWidget::selectFromAllFoldersDialog()
1917 {
1918  if ( !mSelectFromAllFoldersDialog ) {
1919  FolderSelectionDialog::SelectionFolderOptions options = FolderSelectionDialog::None;
1920  options |= FolderSelectionDialog::NotAllowToCreateNewFolder;
1921 
1922  mSelectFromAllFoldersDialog = new FolderSelectionDialog( this, options );
1923  mSelectFromAllFoldersDialog->setModal( true );
1924  }
1925  return mSelectFromAllFoldersDialog;
1926 }
1927 
1928 void KMMainWidget::slotMoveSelectedMessageToFolder()
1929 {
1930  QPointer<MailCommon::FolderSelectionDialog> dialog( moveOrCopyToDialog() );
1931  dialog->setCaption( i18n( "Move Messages to Folder" ) );
1932  if ( dialog->exec() && dialog ) {
1933  const Akonadi::Collection dest = dialog->selectedCollection();
1934  if ( dest.isValid() ) {
1935  moveSelectedMessagesToFolder( dest );
1936  }
1937  }
1938 }
1939 
1940 void KMMainWidget::moveSelectedMessagesToFolder( const Akonadi::Collection & dest )
1941 {
1942  MessageList::Core::MessageItemSetReference ref = mMessagePane->selectionAsPersistentSet();
1943  if ( ref != -1 ) {
1944  //Need to verify if dest == src ??? akonadi do it for us.
1945  moveMessageSelected( ref, dest, false );
1946  }
1947 }
1948 
1949 
1950 void KMMainWidget::copyMessageSelected( const QList<Akonadi::Item> &selectMsg, const Akonadi::Collection &dest )
1951 {
1952  if ( selectMsg.isEmpty() )
1953  return;
1954  // And stuff them into a KMCopyCommand :)
1955  KMCommand *command = new KMCopyCommand( dest, selectMsg );
1956  QObject::connect(
1957  command, SIGNAL(completed(KMCommand*)),
1958  this, SLOT(slotCopyMessagesCompleted(KMCommand*))
1959  );
1960  command->start();
1961  BroadcastStatus::instance()->setStatusMsg( i18n( "Copying messages..." ) );
1962 }
1963 
1964 
1965 void KMMainWidget::slotCopyMessagesCompleted( KMCommand *command )
1966 {
1967  Q_ASSERT( command );
1968  if ( command->result() == KMCommand::OK )
1969  {
1970  BroadcastStatus::instance()->setStatusMsg( i18n( "Messages copied successfully." ) );
1971  } else {
1972  if ( command->result() == KMCommand::Failed )
1973  BroadcastStatus::instance()->setStatusMsg( i18n( "Copying messages failed." ) );
1974  else
1975  BroadcastStatus::instance()->setStatusMsg( i18n( "Copying messages canceled." ) );
1976  }
1977  // The command will autodelete itself and will also kill the set.
1978 }
1979 
1980 void KMMainWidget::slotCopySelectedMessagesToFolder()
1981 {
1982  QPointer<MailCommon::FolderSelectionDialog> dialog( moveOrCopyToDialog() );
1983  dialog->setCaption( i18n( "Copy Messages to Folder" ) );
1984 
1985  if ( dialog->exec() && dialog ) {
1986  const Akonadi::Collection dest = dialog->selectedCollection();
1987  if ( dest.isValid() ) {
1988  copySelectedMessagesToFolder( dest );
1989  }
1990  }
1991 }
1992 
1993 void KMMainWidget::copySelectedMessagesToFolder( const Akonadi::Collection& dest )
1994 {
1995  const QList<Akonadi::Item > lstMsg = mMessagePane->selectionAsMessageItemList();
1996  if ( !lstMsg.isEmpty() ) {
1997  copyMessageSelected( lstMsg, dest );
1998  }
1999 }
2000 
2001 //-----------------------------------------------------------------------------
2002 // Message trashing
2003 //
2004 void KMMainWidget::trashMessageSelected( MessageList::Core::MessageItemSetReference ref )
2005 {
2006  if ( !mCurrentFolder ) {
2007  return;
2008  }
2009 
2010  const QList<Akonadi::Item> select = mMessagePane->itemListFromPersistentSet( ref );
2011  mMessagePane->markMessageItemsAsAboutToBeRemoved( ref, true );
2012 
2013  // FIXME: Why we don't use KMMoveCommand( trashFolder(), selectedMessages ); ?
2014  // And stuff them into a KMTrashMsgCommand :)
2015  KMCommand *command = new KMTrashMsgCommand( mCurrentFolder->collection(), select,ref );
2016 
2017  QObject::connect(
2018  command, SIGNAL(moveDone(KMMoveCommand*)),
2019  this, SLOT(slotTrashMessagesCompleted(KMMoveCommand*))
2020  );
2021  command->start();
2022  BroadcastStatus::instance()->setStatusMsg( i18n( "Moving messages to trash..." ) );
2023 }
2024 
2025 void KMMainWidget::slotTrashMessagesCompleted( KMMoveCommand *command )
2026 {
2027  Q_ASSERT( command );
2028  mMessagePane->markMessageItemsAsAboutToBeRemoved( command->refSet(), false );
2029  mMessagePane->deletePersistentSet( command->refSet() );
2030  if ( command->result() == KMCommand::OK )
2031  {
2032  BroadcastStatus::instance()->setStatusMsg( i18n( "Messages moved to trash successfully." ) );
2033  } else {
2034  if ( command->result() == KMCommand::Failed ) {
2035  BroadcastStatus::instance()->setStatusMsg( i18n( "Moving messages to trash failed." ) );
2036  } else
2037  BroadcastStatus::instance()->setStatusMsg( i18n( "Moving messages to trash canceled." ) );
2038  }
2039 
2040  // The command will autodelete itself and will also kill the set.
2041 }
2042 
2043 void KMMainWidget::slotTrashSelectedMessages()
2044 {
2045  MessageList::Core::MessageItemSetReference ref = mMessagePane->selectionAsPersistentSet();
2046  if ( ref != -1 ) {
2047  trashMessageSelected( ref );
2048  }
2049 }
2050 
2051 void KMMainWidget::slotTrashThread()
2052 {
2053  MessageList::Core::MessageItemSetReference ref = mMessagePane->currentThreadAsPersistentSet();
2054  if ( ref != -1 )
2055  trashMessageSelected( ref );
2056 }
2057 
2058 //-----------------------------------------------------------------------------
2059 // Message tag setting for messages
2060 //
2061 // FIXME: The "selection" version of these functions is in MessageActions.
2062 // We should probably move everything there....
2063 void KMMainWidget::toggleMessageSetTag( const QList<Akonadi::Item> &select, const QString &taglabel )
2064 {
2065  if ( select.isEmpty() )
2066  return;
2067  KMCommand *command = new KMSetTagCommand( QList<QString>()<<taglabel,select, KMSetTagCommand::Toggle );
2068  command->start();
2069 }
2070 
2071 
2072 void KMMainWidget::slotSelectMoreMessageTagList()
2073 {
2074  const QList<Akonadi::Item> selectedMessages = mMessagePane->selectionAsMessageItemList();
2075  if ( selectedMessages.isEmpty() )
2076  return;
2077 
2078  TagSelectDialog dlg( this, selectedMessages.count(), selectedMessages.first() );
2079  if ( dlg.exec() ) {
2080  const QList<QString> lst = dlg.selectedTag();
2081 
2082  KMCommand *command = new KMSetTagCommand( lst, selectedMessages, KMSetTagCommand::CleanExistingAndAddNew );
2083  command->start();
2084  }
2085 }
2086 
2087 
2088 void KMMainWidget::slotUpdateMessageTagList( const QString &taglabel )
2089 {
2090  // Create a persistent set from the current thread.
2091  const QList<Akonadi::Item> selectedMessages = mMessagePane->selectionAsMessageItemList();
2092  if ( selectedMessages.isEmpty() )
2093  return;
2094  toggleMessageSetTag( selectedMessages, taglabel );
2095 }
2096 
2097 void KMMainWidget::refreshMessageListSelection()
2098 {
2099  mAkonadiStandardActionManager->setItemSelectionModel( mMessagePane->currentItemSelectionModel() );
2100  slotMessageSelected(mMessagePane->currentItem());
2101 }
2102 
2103 //-----------------------------------------------------------------------------
2104 // Status setting for threads
2105 //
2106 // FIXME: The "selection" version of these functions is in MessageActions.
2107 // We should probably move everything there....
2108 void KMMainWidget::setMessageSetStatus( const QList<Akonadi::Item> &select,
2109  const Akonadi::MessageStatus &status,
2110  bool toggle )
2111 {
2112  KMCommand *command = new KMSetStatusCommand( status, select, toggle );
2113  command->start();
2114 }
2115 
2116 void KMMainWidget::setCurrentThreadStatus( const Akonadi::MessageStatus &status, bool toggle )
2117 {
2118  const QList<Akonadi::Item> select = mMessagePane->currentThreadAsMessageList();
2119  if ( select.isEmpty() )
2120  return;
2121  setMessageSetStatus( select, status, toggle );
2122 }
2123 
2124 void KMMainWidget::slotSetThreadStatusUnread()
2125 {
2126  setCurrentThreadStatus( MessageStatus::statusRead(), true );
2127 }
2128 
2129 void KMMainWidget::slotSetThreadStatusImportant()
2130 {
2131  setCurrentThreadStatus( MessageStatus::statusImportant(), true );
2132 }
2133 
2134 void KMMainWidget::slotSetThreadStatusRead()
2135 {
2136  setCurrentThreadStatus( MessageStatus::statusRead(), false );
2137 }
2138 
2139 void KMMainWidget::slotSetThreadStatusToAct()
2140 {
2141  setCurrentThreadStatus( MessageStatus::statusToAct(), true );
2142 }
2143 
2144 void KMMainWidget::slotSetThreadStatusWatched()
2145 {
2146  setCurrentThreadStatus( MessageStatus::statusWatched(), true );
2147  if ( mWatchThreadAction->isChecked() )
2148  mIgnoreThreadAction->setChecked(false);
2149 }
2150 
2151 void KMMainWidget::slotSetThreadStatusIgnored()
2152 {
2153  setCurrentThreadStatus( MessageStatus::statusIgnored(), true );
2154  if ( mIgnoreThreadAction->isChecked() )
2155  mWatchThreadAction->setChecked(false);
2156 }
2157 
2158 //-----------------------------------------------------------------------------
2159 void KMMainWidget::slotRedirectMsg()
2160 {
2161  const QList<Akonadi::Item> selectedMessages = mMessagePane->selectionAsMessageItemList();
2162  if ( selectedMessages.isEmpty() )
2163  return;
2164 
2165  KMCommand *command = new KMRedirectCommand( this, selectedMessages );
2166  command->start();
2167 }
2168 
2169 
2170 //-----------------------------------------------------------------------------
2171 void KMMainWidget::slotCustomReplyToMsg( const QString &tmpl )
2172 {
2173  const Akonadi::Item msg = mMessagePane->currentItem();
2174  if ( !msg.isValid() )
2175  return;
2176 
2177  const QString text = mMsgView ? mMsgView->copyText() : QString();
2178 
2179  kDebug() << "Reply with template:" << tmpl;
2180 
2181  KMCommand *command = new KMReplyCommand( this,
2182  msg,
2183  MessageComposer::ReplySmart,
2184  text, false,
2185  tmpl );
2186  command->start();
2187 }
2188 
2189 
2190 //-----------------------------------------------------------------------------
2191 void KMMainWidget::slotCustomReplyAllToMsg( const QString &tmpl )
2192 {
2193  const Akonadi::Item msg = mMessagePane->currentItem();
2194  if ( !msg.isValid() )
2195  return;
2196 
2197  const QString text = mMsgView? mMsgView->copyText() : QString();
2198 
2199  kDebug() << "Reply to All with template:" << tmpl;
2200 
2201  KMCommand *command = new KMReplyCommand(this,
2202  msg,
2203  MessageComposer::ReplyAll,
2204  text,
2205  false,
2206  tmpl
2207  );
2208 
2209  command->start();
2210 }
2211 
2212 
2213 //-----------------------------------------------------------------------------
2214 void KMMainWidget::slotCustomForwardMsg( const QString &tmpl )
2215 {
2216  if ( !mCurrentFolder ) {
2217  return;
2218  }
2219 
2220  const QList<Akonadi::Item> selectedMessages = mMessagePane->selectionAsMessageItemList();
2221  if ( selectedMessages.isEmpty() )
2222  return;
2223 
2224  kDebug() << "Forward with template:" << tmpl;
2225  KMForwardCommand * command = new KMForwardCommand(
2226  this, selectedMessages, mCurrentFolder->identity(), tmpl
2227  );
2228 
2229  command->start();
2230 }
2231 
2232 
2233 void KMMainWidget::openFilterDialog(const QByteArray &field, const QString &value)
2234 {
2235  FilterIf->openFilterDialog( false );
2236  FilterIf->createFilter( field, value );
2237 }
2238 
2239 //-----------------------------------------------------------------------------
2240 void KMMainWidget::slotSubjectFilter()
2241 {
2242  const KMime::Message::Ptr msg = mMessagePane->currentMessage();
2243  if ( !msg )
2244  return;
2245 
2246  openFilterDialog("Subject", msg->subject()->asUnicodeString());
2247 }
2248 
2249 //-----------------------------------------------------------------------------
2250 void KMMainWidget::slotFromFilter()
2251 {
2252  KMime::Message::Ptr msg = mMessagePane->currentMessage();
2253  if ( !msg )
2254  return;
2255 
2256  AddrSpecList al = MessageHelper::extractAddrSpecs( msg, "From" );
2257  if ( al.empty() )
2258  openFilterDialog("From", msg->from()->asUnicodeString());
2259  else
2260  openFilterDialog("From", al.front().asString());
2261 }
2262 
2263 //-----------------------------------------------------------------------------
2264 void KMMainWidget::slotToFilter()
2265 {
2266  KMime::Message::Ptr msg = mMessagePane->currentMessage();
2267  if ( !msg )
2268  return;
2269  openFilterDialog("To", msg->to()->asUnicodeString());
2270 }
2271 
2272 //-----------------------------------------------------------------------------
2273 void KMMainWidget::slotUndo()
2274 {
2275  kmkernel->undoStack()->undo();
2276  updateMessageActions();
2277  updateFolderMenu();
2278 }
2279 
2280 
2281 //-----------------------------------------------------------------------------
2282 void KMMainWidget::slotJumpToFolder()
2283 {
2284  QPointer<MailCommon::FolderSelectionDialog> dialog( selectFromAllFoldersDialog() );
2285  dialog->setCaption( i18n( "Jump to Folder") );
2286  if ( dialog->exec() && dialog ) {
2287  Akonadi::Collection collection = dialog->selectedCollection();
2288  if ( collection.isValid() ) {
2289  slotSelectCollectionFolder( collection );
2290  }
2291  }
2292 }
2293 
2294 void KMMainWidget::slotSelectCollectionFolder( const Akonadi::Collection & col )
2295 {
2296  if ( mFolderTreeWidget ) {
2297  mFolderTreeWidget->selectCollectionFolder( col );
2298  slotFolderChanged( col );
2299  }
2300 }
2301 
2302 void KMMainWidget::slotApplyFilters()
2303 {
2304  const QList<Akonadi::Item> selectedMessages = mMessagePane->selectionAsMessageItemList();
2305  if ( selectedMessages.isEmpty() )
2306  return;
2307  applyFilters( selectedMessages );
2308 }
2309 
2310 void KMMainWidget::slotApplyFiltersOnFolder()
2311 {
2312  if ( mCurrentFolder && mCurrentFolder->collection().isValid() ) {
2313  Akonadi::ItemFetchJob *job = new Akonadi::ItemFetchJob( mCurrentFolder->collection(), this );
2314  connect( job, SIGNAL(result(KJob*)), this, SLOT(slotFetchItemsForFolderDone(KJob*)) );
2315  }
2316 }
2317 
2318 void KMMainWidget::slotFetchItemsForFolderDone(KJob*job)
2319 {
2320  Akonadi::ItemFetchJob *fjob = dynamic_cast<Akonadi::ItemFetchJob*>( job );
2321  Q_ASSERT( fjob );
2322  Akonadi::Item::List items = fjob->items();
2323  applyFilters( items );
2324 }
2325 
2326 void KMMainWidget::applyFilters( const QList<Akonadi::Item>& selectedMessages )
2327 {
2328 #ifndef QT_NO_CURSOR
2329  MessageViewer::KCursorSaver busy( MessageViewer::KBusyPtr::busy() );
2330 #endif
2331 
2332  MailCommon::FilterManager::instance()->filter( selectedMessages );
2333 }
2334 
2335 //-----------------------------------------------------------------------------
2336 void KMMainWidget::slotCheckVacation()
2337 {
2338  updateVacationScriptStatus( false );
2339  if ( !kmkernel->askToGoOnline() )
2340  return;
2341 
2342  mVacationManager->checkVacation();
2343  connect(mVacationManager, SIGNAL(updateVacationScriptStatus(bool,QString)), SLOT(updateVacationScriptStatus(bool,QString)) );
2344  connect(mVacationManager, SIGNAL(editVacation()), SLOT(slotEditVacation()) );
2345 }
2346 
2347 void KMMainWidget::slotEditVacation()
2348 {
2349  if ( !kmkernel->askToGoOnline() ) {
2350  return;
2351  }
2352 
2353  mVacationManager->slotEditVacation();
2354 }
2355 
2356 //-----------------------------------------------------------------------------
2357 void KMMainWidget::slotDebugSieve()
2358 {
2359 #if !defined(NDEBUG)
2360  if ( mSieveDebugDialog )
2361  return;
2362 
2363  mSieveDebugDialog = new KSieveUi::SieveDebugDialog( this );
2364  mSieveDebugDialog->exec();
2365  delete mSieveDebugDialog;
2366 #endif
2367 }
2368 
2369 //-----------------------------------------------------------------------------
2370 void KMMainWidget::slotStartCertManager()
2371 {
2372  if ( !QProcess::startDetached(QLatin1String("kleopatra") ) )
2373  KMessageBox::error( this, i18n( "Could not start certificate manager; "
2374  "please check your installation." ),
2375  i18n( "KMail Error" ) );
2376  else
2377  kDebug() << "\nslotStartCertManager(): certificate manager started.";
2378 }
2379 
2380 //-----------------------------------------------------------------------------
2381 void KMMainWidget::slotStartWatchGnuPG()
2382 {
2383  if ( !QProcess::startDetached(QLatin1String("kwatchgnupg")) )
2384  KMessageBox::error( this, i18n( "Could not start GnuPG LogViewer (kwatchgnupg); "
2385  "please check your installation." ),
2386  i18n( "KMail Error" ) );
2387 }
2388 
2389 //-----------------------------------------------------------------------------
2390 void KMMainWidget::slotConfigChanged()
2391 {
2392  readConfig();
2393  mMsgActions->setupForwardActions();
2394  mMsgActions->setupForwardingActionsList( mGUIClient );
2395 }
2396 
2397 //-----------------------------------------------------------------------------
2398 void KMMainWidget::slotSaveMsg()
2399 {
2400  const QList<Akonadi::Item> selectedMessages = mMessagePane->selectionAsMessageItemList();
2401  if ( selectedMessages.isEmpty() )
2402  return;
2403  KMSaveMsgCommand *saveCommand = new KMSaveMsgCommand( this, selectedMessages );
2404  saveCommand->start();
2405 }
2406 
2407 //-----------------------------------------------------------------------------
2408 void KMMainWidget::slotOpenMsg()
2409 {
2410  KMOpenMsgCommand *openCommand = new KMOpenMsgCommand( this, KUrl(), overrideEncoding(), this );
2411 
2412  openCommand->start();
2413 }
2414 
2415 //-----------------------------------------------------------------------------
2416 void KMMainWidget::slotSaveAttachments()
2417 {
2418  const QList<Akonadi::Item> selectedMessages = mMessagePane->selectionAsMessageItemList();
2419  if ( selectedMessages.isEmpty() )
2420  return;
2421 
2422  // Avoid re-downloading in the common case that only one message is selected, and the message
2423  // is also displayed in the viewer. For this, create a dummy item without a parent collection / item id,
2424  // so that KMCommand doesn't download it.
2425  KMSaveAttachmentsCommand *saveCommand = 0;
2426  if ( mMsgView && selectedMessages.size() == 1 &&
2427  mMsgView->message().hasPayload<KMime::Message::Ptr>() &&
2428  selectedMessages.first().id() == mMsgView->message().id() ) {
2429  Akonadi::Item dummyItem;
2430  dummyItem.setPayload<KMime::Message::Ptr>( mMsgView->message().payload<KMime::Message::Ptr>() );
2431  saveCommand = new KMSaveAttachmentsCommand( this, dummyItem );
2432  } else {
2433  saveCommand = new KMSaveAttachmentsCommand( this, selectedMessages );
2434  }
2435 
2436  saveCommand->start();
2437 }
2438 
2439 void KMMainWidget::slotOnlineStatus()
2440 {
2441  // KMKernel will emit a signal when we toggle the network state that is caught by
2442  // KMMainWidget::slotUpdateOnlineStatus to update our GUI
2443  if ( GlobalSettings::self()->networkState() == GlobalSettings::EnumNetworkState::Online ) {
2444  // if online; then toggle and set it offline.
2445  kmkernel->stopNetworkJobs();
2446  } else {
2447  kmkernel->resumeNetworkJobs();
2448  slotCheckVacation();
2449  }
2450 }
2451 
2452 void KMMainWidget::slotUpdateOnlineStatus( GlobalSettings::EnumNetworkState::type )
2453 {
2454  if ( !mAkonadiStandardActionManager ) {
2455  return;
2456  }
2457  KAction * action = mAkonadiStandardActionManager->action( Akonadi::StandardActionManager::ToggleWorkOffline );
2458  if ( GlobalSettings::self()->networkState() == GlobalSettings::EnumNetworkState::Online ) {
2459  action->setText( i18n("Work Offline") );
2460  action->setIcon( KIcon(QLatin1String("user-offline")) );
2461  } else {
2462  action->setText( i18n("Work Online") );
2463  action->setIcon( KIcon(QLatin1String("user-online")) );
2464  }
2465 }
2466 
2467 
2468 //-----------------------------------------------------------------------------
2469 void KMMainWidget::slotSendQueued()
2470 {
2471  if ( kmkernel->msgSender() ) {
2472  kmkernel->msgSender()->sendQueued();
2473  }
2474 }
2475 
2476 //-----------------------------------------------------------------------------
2477 void KMMainWidget::slotSendQueuedVia( QAction *item )
2478 {
2479  const QStringList availTransports = MailTransport::TransportManager::self()->transportNames();
2480  if ( !availTransports.isEmpty() && availTransports.contains( item->text() ) ) {
2481  if ( kmkernel->msgSender() ) {
2482  kmkernel->msgSender()->sendQueued( item->text() );
2483  }
2484  }
2485 }
2486 
2487 //-----------------------------------------------------------------------------
2488 void KMMainWidget::slotShowBusySplash()
2489 {
2490  if ( mReaderWindowActive ) {
2491  mMsgView->displayBusyPage();
2492  }
2493 }
2494 
2495 void KMMainWidget::showOfflinePage()
2496 {
2497  if ( !mReaderWindowActive ) return;
2498 
2499  mMsgView->displayOfflinePage();
2500 }
2501 
2502 void KMMainWidget::showResourceOfflinePage()
2503 {
2504  if ( !mReaderWindowActive ) return;
2505 
2506  mMsgView->displayResourceOfflinePage();
2507 }
2508 
2509 
2510 //-----------------------------------------------------------------------------
2511 void KMMainWidget::slotReplaceMsgByUnencryptedVersion()
2512 {
2513  kDebug();
2514  Akonadi::Item oldMsg = mMessagePane->currentItem();
2515  if ( oldMsg.isValid() ) {
2516 #if 0
2517  kDebug() << "Old message found";
2518  if ( oldMsg->hasUnencryptedMsg() ) {
2519  kDebug() << "Extra unencrypted message found";
2520  KMime::Message* newMsg = oldMsg->unencryptedMsg();
2521  // adjust the message id
2522  {
2523  QString msgId( oldMsg->msgId() );
2524  QString prefix("DecryptedMsg.");
2525  int oldIdx = msgId.indexOf(prefix, 0, Qt::CaseInsensitive);
2526  if ( -1 == oldIdx ) {
2527  int leftAngle = msgId.lastIndexOf( '<' );
2528  msgId = msgId.insert( (-1 == leftAngle) ? 0 : ++leftAngle, prefix );
2529  }
2530  else {
2531  // toggle between "DecryptedMsg." and "DeCryptedMsg."
2532  // to avoid same message id
2533  QCharRef c = msgId[ oldIdx+2 ];
2534  if ( 'C' == c )
2535  c = 'c';
2536  else
2537  c = 'C';
2538  }
2539  newMsg->setMsgId( msgId );
2540  mMsgView->setIdOfLastViewedMessage( msgId );
2541  }
2542  // insert the unencrypted message
2543  kDebug() << "Adding unencrypted message to folder";
2544  mFolder->addMsg( newMsg );
2545  /* Figure out its index in the folder for selecting. This must be count()-1,
2546  * since we append. Be safe and do find, though, just in case. */
2547  int newMsgIdx = mFolder->find( newMsg );
2548  Q_ASSERT( newMsgIdx != -1 );
2549  /* we need this unget, to have the message displayed correctly initially */
2550  mFolder->unGetMsg( newMsgIdx );
2551  int idx = mFolder->find( oldMsg );
2552  Q_ASSERT( idx != -1 );
2553  /* only select here, so the old one is not un-Gotten before, which would
2554  * render the pointer we hold invalid so that find would fail */
2555 #if 0
2556  // FIXME (Pragma)
2557  mHeaders->setCurrentItemByIndex( newMsgIdx );
2558 #endif
2559  // remove the old one
2560  if ( idx != -1 ) {
2561  kDebug() << "Deleting encrypted message";
2562  mFolder->take( idx );
2563  }
2564 
2565  kDebug() << "Updating message actions";
2566  updateMessageActions();
2567 
2568  kDebug() << "Done.";
2569  } else
2570  kDebug() << "NO EXTRA UNENCRYPTED MESSAGE FOUND";
2571 #else
2572  kDebug() << "AKONADI PORT: Disabled code in " << Q_FUNC_INFO;
2573 #endif
2574  } else
2575  kDebug() << "PANIC: NO OLD MESSAGE FOUND";
2576 }
2577 
2578 void KMMainWidget::slotFocusOnNextMessage()
2579 {
2580  mMessagePane->focusNextMessageItem(MessageList::Core::MessageTypeAny, true,false );
2581 }
2582 
2583 void KMMainWidget::slotFocusOnPrevMessage()
2584 {
2585  mMessagePane->focusPreviousMessageItem( MessageList::Core::MessageTypeAny, true, false );
2586 }
2587 
2588 void KMMainWidget::slotSelectFirstMessage()
2589 {
2590  mMessagePane->selectFirstMessageItem( MessageList::Core::MessageTypeAny, true );
2591 }
2592 
2593 void KMMainWidget::slotSelectLastMessage()
2594 {
2595  mMessagePane->selectLastMessageItem( MessageList::Core::MessageTypeAny, true );
2596 }
2597 
2598 void KMMainWidget::slotSelectFocusedMessage()
2599 {
2600  mMessagePane->selectFocusedMessageItem(true );
2601 }
2602 
2603 void KMMainWidget::slotSelectNextMessage()
2604 {
2605  mMessagePane->selectNextMessageItem( MessageList::Core::MessageTypeAny,
2606  MessageList::Core::ClearExistingSelection,
2607  true, false );
2608 }
2609 
2610 void KMMainWidget::slotExtendSelectionToNextMessage()
2611 {
2612  mMessagePane->selectNextMessageItem(
2613  MessageList::Core::MessageTypeAny,
2614  MessageList::Core::GrowOrShrinkExistingSelection,
2615  true, // center item
2616  false // don't loop in folder
2617  );
2618 }
2619 
2620 void KMMainWidget::slotSelectNextUnreadMessage()
2621 {
2622  // The looping logic is: "Don't loop" just never loops, "Loop in current folder"
2623  // loops just in current folder, "Loop in all folders" loops in the current folder
2624  // first and then after confirmation jumps to the next folder.
2625  // A bad point here is that if you answer "No, and don't ask me again" to the confirmation
2626  // dialog then you have "Loop in current folder" and "Loop in all folders" that do
2627  // the same thing and no way to get the old behaviour. However, after a consultation on #kontact,
2628  // for bug-to-bug backward compatibility, the masters decided to keep it b0rken :D
2629  // If nobody complains, it stays like it is: if you complain enough maybe the masters will
2630  // decide to reconsider :)
2631  if ( !mMessagePane->selectNextMessageItem(
2632  MessageList::Core::MessageTypeUnreadOnly,
2633  MessageList::Core::ClearExistingSelection,
2634  true, // center item
2635  /*GlobalSettings::self()->loopOnGotoUnread() == GlobalSettings::EnumLoopOnGotoUnread::LoopInCurrentFolder*/
2636  GlobalSettings::self()->loopOnGotoUnread() != GlobalSettings::EnumLoopOnGotoUnread::DontLoop
2637  ) )
2638  {
2639  // no next unread message was found in the current folder
2640  if ( ( GlobalSettings::self()->loopOnGotoUnread() ==
2641  GlobalSettings::EnumLoopOnGotoUnread::LoopInAllFolders ) ||
2642  ( GlobalSettings::self()->loopOnGotoUnread() ==
2643  GlobalSettings::EnumLoopOnGotoUnread::LoopInAllMarkedFolders ) )
2644  {
2645  mGoToFirstUnreadMessageInSelectedFolder = true;
2646  mFolderTreeWidget->folderTreeView()->selectNextUnreadFolder( true );
2647  mGoToFirstUnreadMessageInSelectedFolder = false;
2648  }
2649  }
2650 }
2651 
2652 void KMMainWidget::slotSelectPreviousMessage()
2653 {
2654  mMessagePane->selectPreviousMessageItem( MessageList::Core::MessageTypeAny,
2655  MessageList::Core::ClearExistingSelection,
2656  true, false );
2657 }
2658 
2659 void KMMainWidget::slotExtendSelectionToPreviousMessage()
2660 {
2661  mMessagePane->selectPreviousMessageItem(
2662  MessageList::Core::MessageTypeAny,
2663  MessageList::Core::GrowOrShrinkExistingSelection,
2664  true, // center item
2665  false // don't loop in folder
2666  );
2667 }
2668 
2669 void KMMainWidget::slotSelectPreviousUnreadMessage()
2670 {
2671  if ( !mMessagePane->selectPreviousMessageItem(
2672  MessageList::Core::MessageTypeUnreadOnly,
2673  MessageList::Core::ClearExistingSelection,
2674  true, // center item
2675  GlobalSettings::self()->loopOnGotoUnread() == GlobalSettings::EnumLoopOnGotoUnread::LoopInCurrentFolder
2676  ) )
2677  {
2678  // no next unread message was found in the current folder
2679  if ( ( GlobalSettings::self()->loopOnGotoUnread() ==
2680  GlobalSettings::EnumLoopOnGotoUnread::LoopInAllFolders ) ||
2681  ( GlobalSettings::self()->loopOnGotoUnread() ==
2682  GlobalSettings::EnumLoopOnGotoUnread::LoopInAllMarkedFolders ) )
2683  {
2684  mGoToFirstUnreadMessageInSelectedFolder = true;
2685  mFolderTreeWidget->folderTreeView()->selectPrevUnreadFolder();
2686  mGoToFirstUnreadMessageInSelectedFolder = false;
2687  }
2688  }
2689 }
2690 
2691 void KMMainWidget::slotDisplayCurrentMessage()
2692 {
2693  if ( mMessagePane->currentItem().isValid() && !mMessagePane->searchEditHasFocus() )
2694  slotMessageActivated( mMessagePane->currentItem() );
2695 }
2696 
2697 // Called by double-clicked or 'Enter' in the messagelist -> pop up reader window
2698 void KMMainWidget::slotMessageActivated( const Akonadi::Item &msg )
2699 {
2700  if ( !mCurrentFolder || !msg.isValid() )
2701  return;
2702 
2703  if ( CommonKernel->folderIsDraftOrOutbox( mCurrentFolder->collection() ) )
2704  {
2705  mMsgActions->setCurrentMessage( msg );
2706  mMsgActions->editCurrentMessage();
2707  return;
2708  }
2709 
2710  if ( CommonKernel->folderIsTemplates( mCurrentFolder->collection() ) ) {
2711  slotUseTemplate();
2712  return;
2713  }
2714 
2715  // Try to fetch the mail, even in offline mode, it might be cached
2716  ItemFetchJob *itemFetchJob = MessageViewer::Viewer::createFetchJob( msg );
2717  connect( itemFetchJob, SIGNAL(itemsReceived(Akonadi::Item::List)),
2718  SLOT(slotItemsFetchedForActivation(Akonadi::Item::List)) );
2719  connect( itemFetchJob, SIGNAL(result(KJob*)),
2720  SLOT(itemsFetchForActivationDone(KJob*)) );
2721 }
2722 
2723 void KMMainWidget::slotItemsFetchedForActivation( const Akonadi::Item::List &list )
2724 {
2725  Q_ASSERT( list.size() == 1 );
2726 
2727  const Item msg = list.first();
2728 
2729  KMReaderMainWin *win = new KMReaderMainWin( mFolderHtmlPref, mFolderHtmlLoadExtPref );
2730  const bool useFixedFont = mMsgView ? mMsgView->isFixedFont() :
2731  MessageViewer::GlobalSettings::self()->useFixedFont();
2732  win->setUseFixedFont( useFixedFont );
2733 
2734 
2735  const Akonadi::Collection parentCollection = MailCommon::Util::parentCollectionFromItem(msg);
2736  win->showMessage( overrideEncoding(), msg, parentCollection );
2737  win->show();
2738 }
2739 
2740 void KMMainWidget::itemsFetchForActivationDone( KJob * job )
2741 {
2742  if ( job->error() ) {
2743  kDebug() << job->error() << job->errorString();
2744  BroadcastStatus::instance()->setStatusMsg( job->errorString() );
2745  }
2746 }
2747 
2748 void KMMainWidget::slotMessageStatusChangeRequest( const Akonadi::Item &item, const Akonadi::MessageStatus & set, const Akonadi::MessageStatus &clear )
2749 {
2750  if ( !item.isValid() )
2751  return;
2752 
2753  if ( clear.toQInt32() != Akonadi::MessageStatus().toQInt32() )
2754  {
2755  KMCommand *command = new KMSetStatusCommand( clear, Akonadi::Item::List() << item, true );
2756  command->start();
2757  }
2758 
2759  if ( set.toQInt32() != Akonadi::MessageStatus().toQInt32() )
2760  {
2761  KMCommand *command = new KMSetStatusCommand( set, Akonadi::Item::List() << item, false );
2762  command->start();
2763  }
2764 }
2765 
2766 //-----------------------------------------------------------------------------
2767 void KMMainWidget::slotMarkAll()
2768 {
2769  mMessagePane->selectAll();
2770  updateMessageActions();
2771 }
2772 
2773 void KMMainWidget::slotMessagePopup(const Akonadi::Item&msg ,const KUrl&aUrl,const KUrl &imageUrl,const QPoint& aPoint)
2774 {
2775  updateMessageMenu();
2776 
2777  const QString email = KPIMUtils::firstEmailAddress( aUrl.path() ).toLower();
2778  if ( aUrl.protocol() == QLatin1String("mailto") && !email.isEmpty()) {
2779  Akonadi::ContactSearchJob *job = new Akonadi::ContactSearchJob( this );
2780  job->setLimit( 1 );
2781  job->setQuery( Akonadi::ContactSearchJob::Email, email, Akonadi::ContactSearchJob::ExactMatch );
2782  job->setProperty( "msg", QVariant::fromValue( msg ) );
2783  job->setProperty( "point", aPoint );
2784  job->setProperty( "imageUrl", imageUrl );
2785  job->setProperty( "url", aUrl );
2786  connect( job, SIGNAL(result(KJob*)), SLOT(slotContactSearchJobForMessagePopupDone(KJob*)) );
2787  } else {
2788  showMessagePopup(msg, aUrl, imageUrl, aPoint, false, false);
2789  }
2790 }
2791 
2792 void KMMainWidget::slotContactSearchJobForMessagePopupDone( KJob *job )
2793 {
2794  const Akonadi::ContactSearchJob *searchJob = qobject_cast<Akonadi::ContactSearchJob*>( job );
2795  const bool contactAlreadyExists = !searchJob->contacts().isEmpty();
2796 
2797  const QList<Akonadi::Item> listContact = searchJob->items();
2798  const bool uniqueContactFound = (listContact.count() == 1);
2799  if (uniqueContactFound) {
2800  mMsgView->setContactItem(listContact.first(), searchJob->contacts().at(0));
2801  } else {
2802  mMsgView->clearContactItem();
2803  }
2804  const Akonadi::Item msg = job->property( "msg" ).value<Akonadi::Item>();
2805  const QPoint aPoint = job->property( "point" ).toPoint();
2806  const KUrl imageUrl = job->property("imageUrl").value<KUrl>();
2807  const KUrl url = job->property( "url" ).value<KUrl>();
2808 
2809  showMessagePopup(msg, url, imageUrl, aPoint, contactAlreadyExists, uniqueContactFound);
2810 }
2811 
2812 void KMMainWidget::showMessagePopup(const Akonadi::Item&msg ,const KUrl&url,const KUrl &imageUrl,const QPoint& aPoint, bool contactAlreadyExists, bool uniqueContactFound)
2813 {
2814  KMenu *menu = new KMenu;
2815 
2816  bool urlMenuAdded = false;
2817 
2818  if ( !url.isEmpty() ) {
2819  if ( url.protocol() == QLatin1String( "mailto" ) ) {
2820  // popup on a mailto URL
2821  menu->addAction( mMsgView->mailToComposeAction() );
2822  menu->addAction( mMsgView->mailToReplyAction() );
2823  menu->addAction( mMsgView->mailToForwardAction() );
2824 
2825  menu->addSeparator();
2826 
2827  if ( contactAlreadyExists ) {
2828  if (uniqueContactFound) {
2829  menu->addAction( mMsgView->editContactAction() );
2830  } else {
2831  menu->addAction( mMsgView->openAddrBookAction() );
2832  }
2833  } else {
2834  menu->addAction( mMsgView->addAddrBookAction() );
2835  }
2836  menu->addSeparator();
2837  menu->addMenu(mMsgView->viewHtmlOption());
2838  menu->addSeparator();
2839  menu->addAction( mMsgView->copyURLAction() );
2840  urlMenuAdded = true;
2841  } else if ( url.protocol() != QLatin1String( "attachment" ) ) {
2842  // popup on a not-mailto URL
2843  menu->addAction( mMsgView->urlOpenAction() );
2844  menu->addAction( mMsgView->addBookmarksAction() );
2845  menu->addAction( mMsgView->urlSaveAsAction() );
2846  menu->addAction( mMsgView->copyURLAction() );
2847  if (mMsgView->isAShortUrl(url)) {
2848  menu->addSeparator();
2849  menu->addAction( mMsgView->expandShortUrlAction() );
2850  }
2851  if (!imageUrl.isEmpty()) {
2852  menu->addSeparator();
2853  menu->addAction( mMsgView->copyImageLocation());
2854  menu->addAction( mMsgView->downloadImageToDiskAction());
2855  menu->addAction( mMsgView->shareImage());
2856  if (mMsgView->adblockEnabled()) {
2857  menu->addSeparator();
2858  menu->addAction( mMsgView->blockImage());
2859  }
2860  }
2861  urlMenuAdded = true;
2862  }
2863  kDebug() << "URL is:" << url;
2864  }
2865  const QString selectedText = mMsgView ? mMsgView->copyText() : QString();
2866  if ( mMsgView && !selectedText.isEmpty() ) {
2867  if ( urlMenuAdded ) {
2868  menu->addSeparator();
2869  }
2870  menu->addAction( mMsgActions->replyMenu() );
2871  menu->addSeparator();
2872 
2873  menu->addAction( mMsgView->copyAction() );
2874  menu->addAction( mMsgView->selectAllAction() );
2875  menu->addSeparator();
2876  mMsgActions->addWebShortcutsMenu(menu,selectedText);
2877  menu->addSeparator();
2878  menu->addAction(mMsgView->translateAction());
2879  menu->addSeparator();
2880  menu->addAction( mMsgView->speakTextAction());
2881  } else if ( !urlMenuAdded ) {
2882  // popup somewhere else (i.e., not a URL) on the message
2883  if (!mMessagePane->currentMessage()) {
2884  // no messages
2885  delete menu;
2886  return;
2887  }
2888  Akonadi::Collection parentCol = msg.parentCollection();
2889  if ( parentCol.isValid() && CommonKernel->folderIsTemplates( parentCol) ) {
2890  menu->addAction( mUseAction );
2891  } else {
2892  menu->addAction( mMsgActions->replyMenu() );
2893  menu->addAction( mMsgActions->forwardMenu() );
2894  }
2895  if ( parentCol.isValid() && CommonKernel->folderIsSentMailFolder( parentCol ) ) {
2896  menu->addAction( sendAgainAction() );
2897  } else {
2898  menu->addAction( editAction() );
2899  }
2900  menu->addAction( mailingListActionMenu() );
2901  menu->addSeparator();
2902 
2903  menu->addAction( mCopyActionMenu );
2904  menu->addAction( mMoveActionMenu );
2905 
2906  menu->addSeparator();
2907 
2908  menu->addAction( mMsgActions->messageStatusMenu() );
2909  menu->addSeparator();
2910  if ( mMsgView ) {
2911  if (!imageUrl.isEmpty()) {
2912  menu->addSeparator();
2913  menu->addAction( mMsgView->copyImageLocation());
2914  menu->addAction( mMsgView->downloadImageToDiskAction());
2915  menu->addAction( mMsgView->shareImage());
2916  menu->addSeparator();
2917  if (mMsgView->adblockEnabled()) {
2918  menu->addAction( mMsgView->blockImage() );
2919  menu->addSeparator();
2920  }
2921  }
2922  menu->addAction( mMsgView->viewSourceAction() );
2923  menu->addAction( mMsgView->toggleFixFontAction() );
2924  menu->addAction( mMsgView->toggleMimePartTreeAction() );
2925  }
2926  menu->addSeparator();
2927  menu->addAction( mMsgActions->printPreviewAction() );
2928  menu->addAction( mMsgActions->printAction() );
2929  menu->addAction( mSaveAsAction );
2930  menu->addAction( mSaveAttachmentsAction );
2931  menu->addSeparator();
2932  if ( parentCol.isValid() && CommonKernel->folderIsTrash(parentCol) ) {
2933  menu->addAction( mDeleteAction );
2934  } else {
2935  menu->addAction( akonadiStandardAction( Akonadi::StandardMailActionManager::MoveToTrash ) );
2936  }
2937  menu->addSeparator();
2938  menu->addAction( mMsgActions->createTodoAction() );
2939  menu->addSeparator();
2940  if (mMsgView) {
2941  menu->addAction( mMsgView->saveMessageDisplayFormatAction() );
2942  menu->addAction( mMsgView->resetMessageDisplayFormatAction() );
2943  menu->addSeparator();
2944  }
2945  menu->addAction( mMsgActions->annotateAction() );
2946  if (mMsgView && mMsgView->adblockEnabled()) {
2947  menu->addSeparator();
2948  menu->addAction( mMsgView->openBlockableItems());
2949  }
2950  }
2951  KAcceleratorManager::manage(menu);
2952  menu->exec( aPoint, 0 );
2953  delete menu;
2954 }
2955 //-----------------------------------------------------------------------------
2956 void KMMainWidget::getAccountMenu()
2957 {
2958  mActMenu->clear();
2959  const Akonadi::AgentInstance::List lst = MailCommon::Util::agentInstances();
2960  foreach ( const Akonadi::AgentInstance& type, lst )
2961  {
2962  // Explicitly make a copy, as we're not changing values of the list but only
2963  // the local copy which is passed to action.
2964  QAction* action = mActMenu->addAction( QString( type.name() ).replace(QLatin1Char('&'), QLatin1String("&&")) );
2965  action->setData( type.identifier() );
2966  }
2967 }
2968 
2969 //-----------------------------------------------------------------------------
2970 void KMMainWidget::getTransportMenu()
2971 {
2972 
2973  mSendMenu->clear();
2974  QStringList availTransports = MailTransport::TransportManager::self()->transportNames();
2975  QStringList::Iterator it;
2976  QStringList::Iterator end( availTransports.end() );
2977 
2978  for (it = availTransports.begin(); it != end ; ++it)
2979  mSendMenu->addAction((*it).replace(QLatin1Char('&'), QLatin1String("&&")));
2980 }
2981 
2982 
2983 //-----------------------------------------------------------------------------
2984 void KMMainWidget::setupActions()
2985 {
2986  mMsgActions = new KMail::MessageActions( actionCollection(), this );
2987  mMsgActions->setMessageView( mMsgView );
2988 
2989  //----- File Menu
2990  mSaveAsAction = new KAction(KIcon(QLatin1String("document-save")), i18n("Save &As..."), this);
2991  actionCollection()->addAction(QLatin1String("file_save_as"), mSaveAsAction );
2992  connect(mSaveAsAction, SIGNAL(triggered(bool)), SLOT(slotSaveMsg()));
2993  mSaveAsAction->setShortcut(KStandardShortcut::save());
2994 
2995  mOpenAction = KStandardAction::open( this, SLOT(slotOpenMsg()),
2996  actionCollection() );
2997 
2998  mOpenRecentAction = KStandardAction::openRecent( this, SLOT(slotOpenRecentMsg(KUrl)),
2999  actionCollection() );
3000  KConfigGroup grp = mConfig->group(QLatin1String("Recent Files"));
3001  mOpenRecentAction->loadEntries(grp);
3002 
3003  {
3004  KAction *action = new KAction(i18n("&Expire All Folders"), this);
3005  actionCollection()->addAction(QLatin1String("expire_all_folders"), action );
3006  connect(action, SIGNAL(triggered(bool)), SLOT(slotExpireAll()));
3007  }
3008  {
3009  KAction *action = new KAction(KIcon(QLatin1String("mail-receive")), i18n("Check &Mail"), this);
3010  actionCollection()->addAction(QLatin1String("check_mail"), action );
3011  connect(action, SIGNAL(triggered(bool)), SLOT(slotCheckMail()));
3012  action->setShortcut(QKeySequence(Qt::CTRL+Qt::Key_L));
3013  }
3014 
3015  KActionMenu *actActionMenu = new KActionMenu(KIcon(QLatin1String("mail-receive")), i18n("Check Mail In"), this);
3016  actActionMenu->setIconText( i18n("Check Mail") );
3017  actActionMenu->setToolTip( i18n("Check Mail") );
3018  actionCollection()->addAction(QLatin1String("check_mail_in"), actActionMenu );
3019  actActionMenu->setDelayed(true); //needed for checking "all accounts"
3020  connect(actActionMenu, SIGNAL(triggered(bool)), this, SLOT(slotCheckMail()));
3021  mActMenu = actActionMenu->menu();
3022  connect(mActMenu, SIGNAL(triggered(QAction*)),
3023  SLOT(slotCheckOneAccount(QAction*)));
3024  connect(mActMenu, SIGNAL(aboutToShow()), SLOT(getAccountMenu()));
3025 
3026  mSendQueued = new KAction(KIcon(QLatin1String("mail-send")), i18n("&Send Queued Messages"), this);
3027  actionCollection()->addAction(QLatin1String("send_queued"), mSendQueued );
3028  connect(mSendQueued, SIGNAL(triggered(bool)), SLOT(slotSendQueued()));
3029  {
3030 
3031  KAction * action = mAkonadiStandardActionManager->action( Akonadi::StandardActionManager::ToggleWorkOffline );
3032  mAkonadiStandardActionManager->interceptAction( Akonadi::StandardActionManager::ToggleWorkOffline );
3033  action->setCheckable(false);
3034  connect( action, SIGNAL(triggered(bool)), this, SLOT(slotOnlineStatus()) );
3035  action->setText( i18n("Online status (unknown)") );
3036  }
3037 
3038  mSendActionMenu = new KActionMenu(KIcon(QLatin1String("mail-send-via")), i18n("Send Queued Messages Via"), this);
3039  actionCollection()->addAction(QLatin1String("send_queued_via"), mSendActionMenu );
3040  mSendActionMenu->setDelayed(true);
3041 
3042  mSendMenu = mSendActionMenu->menu();
3043  connect(mSendMenu,SIGNAL(triggered(QAction*)), SLOT(slotSendQueuedVia(QAction*)));
3044  connect(mSendMenu,SIGNAL(aboutToShow()),SLOT(getTransportMenu()));
3045 
3046  //----- Tools menu
3047  if (parent()->inherits("KMMainWin")) {
3048  KAction *action = new KAction(KIcon(QLatin1String("x-office-address-book")), i18n("&Address Book"), this);
3049  actionCollection()->addAction(QLatin1String("addressbook"), action );
3050  connect(action, SIGNAL(triggered(bool)), SLOT(slotAddrBook()));
3051  if (KStandardDirs::findExe(QLatin1String("kaddressbook")).isEmpty())
3052  action->setEnabled(false);
3053  }
3054 
3055  {
3056  KAction *action = new KAction(KIcon(QLatin1String("pgp-keys")), i18n("Certificate Manager"), this);
3057  actionCollection()->addAction(QLatin1String("tools_start_certman"), action );
3058  connect(action, SIGNAL(triggered(bool)), SLOT(slotStartCertManager()));
3059  // disable action if no certman binary is around
3060  if (KStandardDirs::findExe(QLatin1String("kleopatra")).isEmpty())
3061  action->setEnabled(false);
3062  }
3063  {
3064  KAction *action = new KAction(KIcon(QLatin1String("pgp-keys")), i18n("GnuPG Log Viewer"), this);
3065  actionCollection()->addAction(QLatin1String("tools_start_kwatchgnupg"), action );
3066  connect(action, SIGNAL(triggered(bool)), SLOT(slotStartWatchGnuPG()));
3067 #ifdef Q_OS_WIN32
3068  // not ported yet, underlying infrastructure missing on Windows
3069  const bool usableKWatchGnupg = false;
3070 #else
3071  // disable action if no kwatchgnupg binary is around
3072  bool usableKWatchGnupg = !KStandardDirs::findExe(QLatin1String("kwatchgnupg")).isEmpty();
3073 #endif
3074  action->setEnabled(usableKWatchGnupg);
3075  }
3076  {
3077  KAction *action = new KAction(KIcon(QLatin1String("document-import")), i18n("&Import Messages..."), this);
3078  actionCollection()->addAction(QLatin1String("import"), action );
3079  connect(action, SIGNAL(triggered(bool)), SLOT(slotImport()));
3080  if (KStandardDirs::findExe(QLatin1String("kmailcvt")).isEmpty()) action->setEnabled(false);
3081  }
3082 
3083 #if !defined(NDEBUG)
3084  {
3085  KAction *action = new KAction(i18n("&Debug Sieve..."), this);
3086  actionCollection()->addAction(QLatin1String("tools_debug_sieve"), action );
3087  connect(action, SIGNAL(triggered(bool)), SLOT(slotDebugSieve()));
3088  }
3089 #endif
3090 
3091  {
3092  KAction *action = new KAction(i18n("Filter &Log Viewer..."), this);
3093  actionCollection()->addAction(QLatin1String("filter_log_viewer"), action );
3094  connect(action, SIGNAL(triggered(bool)), SLOT(slotFilterLogViewer()));
3095  }
3096  {
3097  KAction *action = new KAction(i18n("&Anti-Spam Wizard..."), this);
3098  actionCollection()->addAction(QLatin1String("antiSpamWizard"), action );
3099  connect(action, SIGNAL(triggered(bool)), SLOT(slotAntiSpamWizard()));
3100  }
3101  {
3102  KAction *action = new KAction(i18n("&Anti-Virus Wizard..."), this);
3103  actionCollection()->addAction(QLatin1String("antiVirusWizard"), action );
3104  connect(action, SIGNAL(triggered(bool)), SLOT(slotAntiVirusWizard()));
3105  }
3106  {
3107  KAction *action = new KAction( i18n("&Account Wizard..."), this );
3108  actionCollection()->addAction( QLatin1String("accountWizard"), action );
3109  connect( action, SIGNAL(triggered(bool)), SLOT(slotAccountWizard()) );
3110  }
3111  {
3112  KAction *action = new KAction( i18n("&Import Wizard..."), this );
3113  actionCollection()->addAction( QLatin1String("importWizard"), action );
3114  connect( action, SIGNAL(triggered(bool)), SLOT(slotImportWizard()) );
3115  }
3116  if ( KSieveUi::Util::allowOutOfOfficeSettings() )
3117  {
3118  KAction *action = new KAction( i18n("Edit \"Out of Office\" Replies..."), this );
3119  actionCollection()->addAction( QLatin1String("tools_edit_vacation"), action );
3120  connect( action, SIGNAL(triggered(bool)), SLOT(slotEditVacation()) );
3121  }
3122 
3123  {
3124  KAction *action = new KAction(i18n("&Configure Automatic Archiving..."), this);
3125  actionCollection()->addAction(QLatin1String("tools_automatic_archiving"), action );
3126  connect(action, SIGNAL(triggered(bool)), SLOT(slotConfigureAutomaticArchiving()));
3127  }
3128 
3129  {
3130  KAction *action = new KAction(i18n("Configure Send Later Agent..."), this);
3131  actionCollection()->addAction(QLatin1String("tools_configure_sendlater"), action );
3132  connect(action, SIGNAL(triggered(bool)), SLOT(slotConfigureSendLater()));
3133  }
3134 
3135  {
3136  KAction *action = new KAction(i18n("&Configure Folder Archive Agent..."), this);
3137  actionCollection()->addAction(QLatin1String("tools_configure_folderarchiving"), action );
3138  connect(action, SIGNAL(triggered(bool)), SLOT(slotConfigureFolderArchiving()));
3139  }
3140 
3141 
3142  // Disable the standard action delete key sortcut.
3143  KAction* const standardDelAction = akonadiStandardAction( Akonadi::StandardActionManager::DeleteItems );
3144  standardDelAction->setShortcut( QKeySequence() );
3145 
3146  //----- Edit Menu
3147 
3148  /* The delete action is nowhere in the gui, by default, so we need to make
3149  * sure it is plugged into the KAccel now, since that won't happen on
3150  * XMLGui construction or manual ->plug(). This is only a problem when run
3151  * as a part, though. */
3152  mDeleteAction = new KAction(KIcon(QLatin1String("edit-delete")), i18nc("@action Hard delete, bypassing trash", "&Delete"), this);
3153  actionCollection()->addAction(QLatin1String("delete"), mDeleteAction );
3154  connect(mDeleteAction, SIGNAL(triggered(bool)), SLOT(slotDeleteMsg()));
3155  mDeleteAction->setShortcut(QKeySequence(Qt::SHIFT+Qt::Key_Delete));
3156 
3157  mTrashThreadAction = new KAction(i18n("M&ove Thread to Trash"), this);
3158  actionCollection()->addAction(QLatin1String("move_thread_to_trash"), mTrashThreadAction );
3159  mTrashThreadAction->setShortcut(QKeySequence(Qt::CTRL+Qt::Key_Delete));
3160  mTrashThreadAction->setIcon(KIcon(QLatin1String("user-trash")));
3161  mTrashThreadAction->setHelpText(i18n("Move thread to trashcan") );
3162  connect(mTrashThreadAction, SIGNAL(triggered(bool)), SLOT(slotTrashThread()));
3163 
3164  mDeleteThreadAction = new KAction(KIcon(QLatin1String("edit-delete")), i18n("Delete T&hread"), this);
3165  actionCollection()->addAction(QLatin1String("delete_thread"), mDeleteThreadAction );
3166  connect(mDeleteThreadAction, SIGNAL(triggered(bool)), SLOT(slotDeleteThread()));
3167  mDeleteThreadAction->setShortcut(QKeySequence(Qt::CTRL+Qt::SHIFT+Qt::Key_Delete));
3168 
3169  {
3170  KAction *action = new KAction(KIcon(QLatin1String("edit-find-mail")), i18n("&Find Messages..."), this);
3171  actionCollection()->addAction(QLatin1String("search_messages"), action );
3172  connect(action, SIGNAL(triggered(bool)), SLOT(slotRequestFullSearchFromQuickSearch()));
3173  action->setShortcut(QKeySequence(Qt::Key_S));
3174  }
3175  {
3176  KAction *action = new KAction(i18n("Select &All Messages"), this);
3177  actionCollection()->addAction(QLatin1String("mark_all_messages"), action );
3178  connect(action, SIGNAL(triggered(bool)), SLOT(slotMarkAll()));
3179  action->setShortcut( QKeySequence( Qt::CTRL + Qt::Key_A ) );
3180  }
3181 
3182  //----- Folder Menu
3183 
3184  mFolderMailingListPropertiesAction = new KAction(i18n("&Mailing List Management..."), this);
3185  actionCollection()->addAction(QLatin1String("folder_mailinglist_properties"), mFolderMailingListPropertiesAction );
3186  connect(mFolderMailingListPropertiesAction, SIGNAL(triggered(bool)), SLOT(slotFolderMailingListProperties()));
3187  // mFolderMailingListPropertiesAction->setIcon(KIcon("document-properties-mailing-list"));
3188 
3189  mShowFolderShortcutDialogAction = new KAction(KIcon(QLatin1String("configure-shortcuts")), i18n("&Assign Shortcut..."), this);
3190  actionCollection()->addAction(QLatin1String("folder_shortcut_command"), mShowFolderShortcutDialogAction );
3191  connect( mShowFolderShortcutDialogAction, SIGNAL(triggered(bool)),
3192  SLOT(slotShowFolderShortcutDialog()) );
3193 
3194  // FIXME: this action is not currently enabled in the rc file, but even if
3195  // it were there is inconsistency between the action name and action.
3196  // "Expiration Settings" implies that this will lead to a settings dialogue
3197  // and it should be followed by a "...", but slotExpireFolder() performs
3198  // an immediate expiry.
3199  //
3200  // TODO: expire action should be disabled if there is no content or if
3201  // the folder can't delete messages.
3202  //
3203  // Leaving the action here for the moment, it and the "Expire" option in the
3204  // folder popup menu should be combined or at least made consistent. Same for
3205  // slotExpireFolder() and FolderViewItem::slotShowExpiryProperties().
3206  mExpireFolderAction = new KAction(i18n("&Expiration Settings"), this);
3207  actionCollection()->addAction(QLatin1String("expire"), mExpireFolderAction );
3208  connect(mExpireFolderAction, SIGNAL(triggered(bool)), SLOT(slotExpireFolder()));
3209 
3210 
3211  mAkonadiStandardActionManager->interceptAction( Akonadi::StandardMailActionManager::MoveToTrash );
3212  connect( mAkonadiStandardActionManager->action( Akonadi::StandardMailActionManager::MoveToTrash ), SIGNAL(triggered(bool)), this, SLOT(slotTrashSelectedMessages()) );
3213 
3214 
3215  mAkonadiStandardActionManager->interceptAction( Akonadi::StandardMailActionManager::MoveAllToTrash );
3216  connect( mAkonadiStandardActionManager->action( Akonadi::StandardMailActionManager::MoveAllToTrash ), SIGNAL(triggered(bool)), this, SLOT(slotEmptyFolder()) );
3217 
3218  mAkonadiStandardActionManager->interceptAction( Akonadi::StandardActionManager::DeleteCollections );
3219  connect( mAkonadiStandardActionManager->action( Akonadi::StandardActionManager::DeleteCollections ), SIGNAL(triggered(bool)), this, SLOT(slotRemoveFolder()) );
3220 
3221  // ### PORT ME: Add this to the context menu. Not possible right now because
3222  // the context menu uses XMLGUI, and that would add the entry to
3223  // all collection context menus
3224  mArchiveFolderAction = new KAction( i18n( "&Archive Folder..." ), this );
3225  actionCollection()->addAction( QLatin1String("archive_folder"), mArchiveFolderAction );
3226  connect( mArchiveFolderAction, SIGNAL(triggered(bool)), SLOT(slotArchiveFolder()) );
3227 
3228  mPreferHtmlAction = new KToggleAction(i18n("Prefer &HTML to Plain Text"), this);
3229  actionCollection()->addAction(QLatin1String("prefer_html"), mPreferHtmlAction );
3230  connect(mPreferHtmlAction, SIGNAL(triggered(bool)), SLOT(slotOverrideHtml()));
3231 
3232  mPreferHtmlLoadExtAction = new KToggleAction(i18n("Load E&xternal References"), this);
3233  actionCollection()->addAction(QLatin1String("prefer_html_external_refs"), mPreferHtmlLoadExtAction );
3234  connect(mPreferHtmlLoadExtAction, SIGNAL(triggered(bool)), SLOT(slotOverrideHtmlLoadExt()));
3235 
3236  {
3237  KAction *action = mAkonadiStandardActionManager->action( Akonadi::StandardActionManager::CopyCollections);
3238  action->setShortcut(QKeySequence(Qt::SHIFT+Qt::CTRL+Qt::Key_C));
3239  }
3240  {
3241  KAction *action = mAkonadiStandardActionManager->action( Akonadi::StandardActionManager::Paste);
3242  action->setShortcut(QKeySequence(Qt::SHIFT+Qt::CTRL+Qt::Key_V));
3243  }
3244  {
3245  KAction *action = mAkonadiStandardActionManager->action( Akonadi::StandardActionManager::CopyItems);
3246  action->setShortcut(QKeySequence(Qt::ALT+Qt::CTRL+Qt::Key_C));
3247  }
3248  {
3249  KAction *action = mAkonadiStandardActionManager->action( Akonadi::StandardActionManager::CutItems );
3250  action->setShortcut(QKeySequence(Qt::ALT+Qt::CTRL+Qt::Key_X));
3251  }
3252 
3253  {
3254  KAction *action = mAkonadiStandardActionManager->action( Akonadi::StandardActionManager::CopyItemToMenu );
3255  action->setText(i18n("Copy Message To...") );
3256  action = mAkonadiStandardActionManager->action( Akonadi::StandardActionManager::MoveItemToMenu );
3257  action->setText(i18n("Move Message To...") );
3258  }
3259 
3260  //----- Message Menu
3261  {
3262  KAction *action = new KAction(KIcon(QLatin1String("mail-message-new")), i18n("&New Message..."), this);
3263  actionCollection()->addAction(QLatin1String("new_message"), action );
3264  action->setIconText( i18nc("@action:intoolbar New Empty Message", "New" ) );
3265  connect(action, SIGNAL(triggered(bool)), SLOT(slotCompose()));
3266  // do not set a New shortcut if kmail is a component
3267  if ( !kmkernel->xmlGuiInstance().isValid() ) {
3268  action->setShortcut(KStandardShortcut::openNew());
3269  }
3270  }
3271 
3272  mTemplateMenu = new KActionMenu( KIcon( QLatin1String("document-new") ), i18n("Message From &Template"),
3273  actionCollection() );
3274  mTemplateMenu->setDelayed( true );
3275  actionCollection()->addAction(QLatin1String("new_from_template"), mTemplateMenu );
3276  connect( mTemplateMenu->menu(), SIGNAL(aboutToShow()), this,
3277  SLOT(slotShowNewFromTemplate()) );
3278  connect( mTemplateMenu->menu(), SIGNAL(triggered(QAction*)), this,
3279  SLOT(slotNewFromTemplate(QAction*)) );
3280 
3281  mMessageNewList = new KAction( KIcon( QLatin1String("mail-message-new-list") ),
3282  i18n( "New Message t&o Mailing-List..." ),
3283  this );
3284  actionCollection()->addAction(QLatin1String("post_message"), mMessageNewList);
3285  connect( mMessageNewList, SIGNAL(triggered(bool)),
3286  SLOT(slotPostToML()) );
3287  mMessageNewList->setShortcut( QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_N ) );
3288 
3289  mSendAgainAction = new KAction(i18n("Send A&gain..."), this);
3290  actionCollection()->addAction(QLatin1String("send_again"), mSendAgainAction );
3291  connect(mSendAgainAction, SIGNAL(triggered(bool)), SLOT(slotResendMsg()));
3292 
3293  //----- Create filter actions
3294  mFilterMenu = new KActionMenu(KIcon(QLatin1String("view-filter")), i18n("&Create Filter"), this);
3295  actionCollection()->addAction(QLatin1String("create_filter"), mFilterMenu );
3296  connect( mFilterMenu, SIGNAL(triggered(bool)), this,
3297  SLOT(slotFilter()) );
3298  {
3299  KAction *action = new KAction(i18n("Filter on &Subject..."), this);
3300  actionCollection()->addAction(QLatin1String("subject_filter"), action );
3301  connect(action, SIGNAL(triggered(bool)), SLOT(slotSubjectFilter()));
3302  mFilterMenu->addAction( action );
3303  }
3304 
3305  {
3306  KAction *action = new KAction(i18n("Filter on &From..."), this);
3307  actionCollection()->addAction(QLatin1String("from_filter"), action );
3308  connect(action, SIGNAL(triggered(bool)), SLOT(slotFromFilter()));
3309  mFilterMenu->addAction( action );
3310  }
3311  {
3312  KAction *action = new KAction(i18n("Filter on &To..."), this);
3313  actionCollection()->addAction(QLatin1String("to_filter"), action );
3314  connect(action, SIGNAL(triggered(bool)), SLOT(slotToFilter()));
3315  mFilterMenu->addAction( action );
3316  }
3317  mFilterMenu->addAction( mMsgActions->listFilterAction() );
3318 
3319  mUseAction = new KAction( KIcon(QLatin1String("document-new")), i18n("New Message From &Template"), this );
3320  actionCollection()->addAction(QLatin1String("use_template"), mUseAction);
3321  connect(mUseAction, SIGNAL(triggered(bool)), SLOT(slotUseTemplate()));
3322  mUseAction->setShortcut(QKeySequence(Qt::SHIFT + Qt::Key_N));
3323 
3324  //----- "Mark Thread" submenu
3325  mThreadStatusMenu = new KActionMenu(i18n("Mark &Thread"), this);
3326  actionCollection()->addAction(QLatin1String("thread_status"), mThreadStatusMenu );
3327 
3328  mMarkThreadAsReadAction = new KAction(KIcon(QLatin1String("mail-mark-read")), i18n("Mark Thread as &Read"), this);
3329  actionCollection()->addAction(QLatin1String("thread_read"), mMarkThreadAsReadAction );
3330  connect(mMarkThreadAsReadAction, SIGNAL(triggered(bool)), SLOT(slotSetThreadStatusRead()));
3331  mMarkThreadAsReadAction->setHelpText(i18n("Mark all messages in the selected thread as read"));
3332  mThreadStatusMenu->addAction( mMarkThreadAsReadAction );
3333 
3334  mMarkThreadAsUnreadAction = new KAction(KIcon(QLatin1String("mail-mark-unread")), i18n("Mark Thread as &Unread"), this);
3335  actionCollection()->addAction(QLatin1String("thread_unread"), mMarkThreadAsUnreadAction );
3336  connect(mMarkThreadAsUnreadAction, SIGNAL(triggered(bool)), SLOT(slotSetThreadStatusUnread()));
3337  mMarkThreadAsUnreadAction->setHelpText(i18n("Mark all messages in the selected thread as unread"));
3338  mThreadStatusMenu->addAction( mMarkThreadAsUnreadAction );
3339 
3340  mThreadStatusMenu->addSeparator();
3341 
3342  //----- "Mark Thread" toggle actions
3343  mToggleThreadImportantAction = new KToggleAction(KIcon(QLatin1String("mail-mark-important")), i18n("Mark Thread as &Important"), this);
3344  actionCollection()->addAction(QLatin1String("thread_flag"), mToggleThreadImportantAction );
3345  connect(mToggleThreadImportantAction, SIGNAL(triggered(bool)), SLOT(slotSetThreadStatusImportant()));
3346  mToggleThreadImportantAction->setCheckedState( KGuiItem(i18n("Remove &Important Thread Mark")) );
3347  mThreadStatusMenu->addAction( mToggleThreadImportantAction );
3348 
3349  mToggleThreadToActAction = new KToggleAction(KIcon(QLatin1String("mail-mark-task")), i18n("Mark Thread as &Action Item"), this);
3350  actionCollection()->addAction(QLatin1String("thread_toact"), mToggleThreadToActAction );
3351  connect(mToggleThreadToActAction, SIGNAL(triggered(bool)), SLOT(slotSetThreadStatusToAct()));
3352  mToggleThreadToActAction->setCheckedState( KGuiItem(i18n("Remove &Action Item Thread Mark")) );
3353  mThreadStatusMenu->addAction( mToggleThreadToActAction );
3354 
3355  //------- "Watch and ignore thread" actions
3356  mWatchThreadAction = new KToggleAction(KIcon(QLatin1String("mail-thread-watch")), i18n("&Watch Thread"), this);
3357  actionCollection()->addAction(QLatin1String("thread_watched"), mWatchThreadAction );
3358  connect(mWatchThreadAction, SIGNAL(triggered(bool)), SLOT(slotSetThreadStatusWatched()));
3359 
3360  mIgnoreThreadAction = new KToggleAction(KIcon(QLatin1String("mail-thread-ignored")), i18n("&Ignore Thread"), this);
3361  actionCollection()->addAction(QLatin1String("thread_ignored"), mIgnoreThreadAction );
3362  connect(mIgnoreThreadAction, SIGNAL(triggered(bool)), SLOT(slotSetThreadStatusIgnored()));
3363 
3364  mThreadStatusMenu->addSeparator();
3365  mThreadStatusMenu->addAction( mWatchThreadAction );
3366  mThreadStatusMenu->addAction( mIgnoreThreadAction );
3367 
3368  mSaveAttachmentsAction = new KAction(KIcon(QLatin1String("mail-attachment")), i18n("Save A&ttachments..."), this);
3369  actionCollection()->addAction(QLatin1String("file_save_attachments"), mSaveAttachmentsAction );
3370  connect(mSaveAttachmentsAction, SIGNAL(triggered(bool)), SLOT(slotSaveAttachments()));
3371 
3372  mMoveActionMenu = mAkonadiStandardActionManager->action( Akonadi::StandardActionManager::MoveItemToMenu);
3373 
3374  mCopyActionMenu = mAkonadiStandardActionManager->action( Akonadi::StandardActionManager::CopyItemToMenu);
3375 
3376  mApplyAllFiltersAction =
3377  new KAction( KIcon( QLatin1String("view-filter") ), i18n( "Appl&y All Filters" ), this );
3378  actionCollection()->addAction( QLatin1String("apply_filters"), mApplyAllFiltersAction );
3379  connect( mApplyAllFiltersAction, SIGNAL(triggered(bool)),
3380  SLOT(slotApplyFilters()) );
3381  mApplyAllFiltersAction->setShortcut( QKeySequence( Qt::CTRL + Qt::Key_J ) );
3382 
3383  mApplyFilterActionsMenu = new KActionMenu( i18n( "A&pply Filter" ), this );
3384  actionCollection()->addAction( QLatin1String("apply_filter_actions"), mApplyFilterActionsMenu );
3385 
3386  {
3387  KAction *action = new KAction(i18nc("View->","&Expand Thread / Group"), this);
3388  actionCollection()->addAction(QLatin1String("expand_thread"), action );
3389  action->setShortcut(QKeySequence(Qt::Key_Period));
3390  action->setHelpText(i18n("Expand the current thread or group"));
3391  connect(action, SIGNAL(triggered(bool)), SLOT(slotExpandThread()));
3392  }
3393  {
3394  KAction *action = new KAction(i18nc("View->","&Collapse Thread / Group"), this);
3395  actionCollection()->addAction(QLatin1String("collapse_thread"), action );
3396  action->setShortcut(QKeySequence(Qt::Key_Comma));
3397  action->setHelpText( i18n("Collapse the current thread or group"));
3398  connect(action, SIGNAL(triggered(bool)), SLOT(slotCollapseThread()));
3399  }
3400  {
3401  KAction *action = new KAction(i18nc("View->","Ex&pand All Threads"), this);
3402  actionCollection()->addAction(QLatin1String("expand_all_threads"), action );
3403  action->setShortcut(QKeySequence(Qt::CTRL+Qt::Key_Period));
3404  action->setHelpText( i18n("Expand all threads in the current folder"));
3405  connect(action, SIGNAL(triggered(bool)), SLOT(slotExpandAllThreads()));
3406  }
3407  {
3408  KAction *action = new KAction(i18nc("View->","C&ollapse All Threads"), this);
3409  actionCollection()->addAction(QLatin1String("collapse_all_threads"), action );
3410  action->setShortcut(QKeySequence(Qt::CTRL+Qt::Key_Comma));
3411  action->setHelpText( i18n("Collapse all threads in the current folder"));
3412  connect(action, SIGNAL(triggered(bool)), SLOT(slotCollapseAllThreads()));
3413  }
3414 
3415 
3416  KAction *dukeOfMonmoth = new KAction(i18n("&Display Message"), this);
3417  actionCollection()->addAction(QLatin1String("display_message"), dukeOfMonmoth );
3418  connect(dukeOfMonmoth, SIGNAL(triggered(bool)), SLOT(slotDisplayCurrentMessage()));
3419  KShortcut shortcut = KShortcut(QKeySequence( Qt::Key_Enter ));
3420  shortcut.setAlternate( QKeySequence( Qt::Key_Return ) );
3421  dukeOfMonmoth->setShortcuts( shortcut );
3422 
3423  //----- Go Menu
3424  {
3425  KAction *action = new KAction(i18n("&Next Message"), this);
3426  actionCollection()->addAction(QLatin1String("go_next_message"), action );
3427  action->setShortcuts(KShortcut( QLatin1String("N; Right") ));
3428  action->setHelpText(i18n("Go to the next message"));
3429  connect(action, SIGNAL(triggered(bool)), SLOT(slotSelectNextMessage()));
3430  }
3431  {
3432  KAction *action = new KAction(i18n("Next &Unread Message"), this);
3433  actionCollection()->addAction(QLatin1String("go_next_unread_message"), action );
3434  action->setShortcut(QKeySequence(Qt::Key_Plus));
3435  if ( QApplication::isRightToLeft() ) {
3436  action->setIcon( KIcon( QLatin1String("go-previous") ) );
3437  } else {
3438  action->setIcon( KIcon( QLatin1String("go-next") ) );
3439  }
3440  action->setIconText( i18nc( "@action:inmenu Goto next unread message", "Next" ) );
3441  action->setHelpText(i18n("Go to the next unread message"));
3442  connect(action, SIGNAL(triggered(bool)), SLOT(slotSelectNextUnreadMessage()));
3443  }
3444  {
3445  KAction *action = new KAction(i18n("&Previous Message"), this);
3446  actionCollection()->addAction(QLatin1String("go_prev_message"), action );
3447  action->setHelpText(i18n("Go to the previous message"));
3448  action->setShortcuts(KShortcut( QLatin1String("P; Left") ));
3449  connect(action, SIGNAL(triggered(bool)), SLOT(slotSelectPreviousMessage()));
3450  }
3451  {
3452  KAction *action = new KAction(i18n("Previous Unread &Message"), this);
3453  actionCollection()->addAction(QLatin1String("go_prev_unread_message"), action );
3454  action->setShortcut(QKeySequence(Qt::Key_Minus));
3455  if ( QApplication::isRightToLeft() ) {
3456  action->setIcon( KIcon( QLatin1String("go-next") ) );
3457  } else {
3458  action->setIcon( KIcon( QLatin1String("go-previous") ) );
3459  }
3460  action->setIconText( i18nc( "@action:inmenu Goto previous unread message.","Previous" ) );
3461  action->setHelpText(i18n("Go to the previous unread message"));
3462  connect(action, SIGNAL(triggered(bool)), SLOT(slotSelectPreviousUnreadMessage()));
3463  }
3464  {
3465  KAction *action = new KAction(i18n("Next Unread &Folder"), this);
3466  actionCollection()->addAction(QLatin1String("go_next_unread_folder"), action );
3467  connect(action, SIGNAL(triggered(bool)), SLOT(slotNextUnreadFolder()));
3468  action->setShortcut(QKeySequence(Qt::ALT+Qt::Key_Plus));
3469  action->setHelpText(i18n("Go to the next folder with unread messages"));
3470  }
3471  {
3472  KAction *action = new KAction(i18n("Previous Unread F&older"), this);
3473  actionCollection()->addAction(QLatin1String("go_prev_unread_folder"), action );
3474  action->setShortcut(QKeySequence(Qt::ALT+Qt::Key_Minus));
3475  action->setHelpText(i18n("Go to the previous folder with unread messages"));
3476  connect(action, SIGNAL(triggered(bool)), SLOT(slotPrevUnreadFolder()));
3477  }
3478  {
3479  KAction *action = new KAction(i18nc("Go->","Next Unread &Text"), this);
3480  actionCollection()->addAction(QLatin1String("go_next_unread_text"), action );
3481  action->setShortcut(QKeySequence(Qt::Key_Space));
3482  action->setHelpText(i18n("Go to the next unread text"));
3483  action->setWhatsThis( i18n("Scroll down current message. "
3484  "If at end of current message, "
3485  "go to next unread message."));
3486  connect(action, SIGNAL(triggered(bool)), SLOT(slotReadOn()));
3487  }
3488 
3489  //----- Settings Menu
3490  {
3491  KAction *action = new KAction(i18n("Configure &Filters..."), this);
3492  action->setMenuRole( QAction::NoRole ); // do not move to application menu on OS X
3493  actionCollection()->addAction(QLatin1String("filter"), action );
3494  connect(action, SIGNAL(triggered(bool)), SLOT(slotFilter()));
3495  }
3496  {
3497  KAction *action = new KAction(i18n("Manage &Sieve Scripts..."), this);
3498  actionCollection()->addAction(QLatin1String("sieveFilters"), action );
3499  connect(action, SIGNAL(triggered(bool)), SLOT(slotManageSieveScripts()));
3500  }
3501  {
3502  KAction *action = new KAction(KIcon(QLatin1String("kmail")), i18n("KMail &Introduction"), this);
3503  actionCollection()->addAction(QLatin1String("help_kmail_welcomepage"), action );
3504  action->setHelpText( i18n("Display KMail's Welcome Page") );
3505  connect(action, SIGNAL(triggered(bool)), SLOT(slotIntro()));
3506  }
3507 
3508  // ----- Standard Actions
3509 
3510 // KStandardAction::configureNotifications(this, SLOT(slotEditNotifications()), actionCollection());
3511  {
3512  KAction *action = new KAction( KIcon(QLatin1String("preferences-desktop-notification")),
3513  i18n("Configure &Notifications..."), this );
3514  action->setMenuRole( QAction::NoRole ); // do not move to application menu on OS X
3515  actionCollection()->addAction( QLatin1String("kmail_configure_notifications"), action );
3516  connect(action, SIGNAL(triggered(bool)), SLOT(slotEditNotifications()));
3517  }
3518 
3519  {
3520  KAction *action = new KAction(KIcon(QLatin1String("configure")), i18n("&Configure KMail..."), this);
3521  actionCollection()->addAction(QLatin1String("kmail_configure_kmail"), action );
3522  connect(action, SIGNAL(triggered(bool)), kmkernel, SLOT(slotShowConfigurationDialog()));
3523  }
3524 
3525  {
3526  mExpireConfigAction = new KAction( i18n( "Expire..." ), this );
3527  actionCollection()->addAction( QLatin1String("expire_settings"),mExpireConfigAction );
3528  connect( mExpireConfigAction, SIGNAL(triggered(bool)), this, SLOT(slotShowExpiryProperties()) );
3529  }
3530 
3531  {
3532  KAction *action = new KAction( KIcon( QLatin1String("bookmark-new" )), i18n( "Add Favorite Folder..." ), this );
3533  actionCollection()->addAction( QLatin1String("add_favorite_folder"), action );
3534  connect( action, SIGNAL(triggered(bool)), this, SLOT(slotAddFavoriteFolder()) );
3535  }
3536 
3537  {
3538  mServerSideSubscription = new KAction( KIcon( QLatin1String("folder-bookmarks") ), i18n( "Serverside Subscription..." ), this);
3539  actionCollection()->addAction( QLatin1String("serverside_subscription"), mServerSideSubscription);
3540  connect( mServerSideSubscription, SIGNAL(triggered(bool)), this, SLOT(slotServerSideSubscription()) );
3541  }
3542 
3543 
3544  {
3545  mApplyFiltersOnFolder = new KAction( KIcon( QLatin1String("view-filter") ), i18n( "Appl&y All Filters On Folder" ), this );
3546  actionCollection()->addAction( QLatin1String("apply_filters_on_folder"), mApplyFiltersOnFolder );
3547  connect( mApplyFiltersOnFolder, SIGNAL(triggered(bool)),
3548  SLOT(slotApplyFiltersOnFolder()) );
3549 
3550  }
3551 
3552  {
3553  KAction *action = new KAction(KIcon(QLatin1String("kmail")), i18n("&Export KMail Data..."), this);
3554  actionCollection()->addAction(QLatin1String("kmail_export_data"), action );
3555  connect(action, SIGNAL(triggered(bool)), this, SLOT(slotExportData()));
3556  }
3557 
3558  {
3559  KAction *action = new KAction(KIcon( QLatin1String( "contact-new" ) ),i18n("New AddressBook Contact..."),this);
3560  actionCollection()->addAction(QLatin1String("kmail_new_addressbook_contact"), action );
3561  connect(action, SIGNAL(triggered(bool)), this, SLOT(slotCreateAddressBookContact()));
3562 
3563 
3564  }
3565 
3566  actionCollection()->addAction(KStandardAction::Undo, QLatin1String("kmail_undo"), this, SLOT(slotUndo()));
3567 
3568  KStandardAction::tipOfDay( this, SLOT(slotShowTip()), actionCollection() );
3569 
3570  menutimer = new QTimer( this );
3571  menutimer->setObjectName( QLatin1String("menutimer") );
3572  menutimer->setSingleShot( true );
3573  connect( menutimer, SIGNAL(timeout()), SLOT(updateMessageActionsDelayed()) );
3574  connect( kmkernel->undoStack(),
3575  SIGNAL(undoStackChanged()), this, SLOT(slotUpdateUndo()));
3576 
3577  updateMessageActions();
3578  updateFolderMenu();
3579  mTagActionManager = new KMail::TagActionManager( this, actionCollection(), mMsgActions,
3580  mGUIClient );
3581  mFolderShortcutActionManager = new KMail::FolderShortcutActionManager( this, actionCollection() );
3582 
3583  {
3584  KAction *action = new KAction( i18n("Copy Message to Folder"), this );
3585  actionCollection()->addAction(QLatin1String( "copy_message_to_folder"), action );
3586  connect( action, SIGNAL(triggered(bool)),
3587  SLOT(slotCopySelectedMessagesToFolder()) );
3588  action->setShortcut( QKeySequence( Qt::Key_C ) );
3589  }
3590  {
3591  KAction *action = new KAction( i18n("Jump to Folder..."), this );
3592  actionCollection()->addAction( QLatin1String("jump_to_folder"), action );
3593  connect( action, SIGNAL(triggered(bool)),
3594  SLOT(slotJumpToFolder()) );
3595  action->setShortcut( QKeySequence( Qt::Key_J ) );
3596  }
3597  {
3598  KAction *action = new KAction(i18n("Abort Current Operation"), this);
3599  actionCollection()->addAction(QLatin1String("cancel"), action );
3600  connect( action, SIGNAL(triggered(bool)),
3601  ProgressManager::instance(), SLOT(slotAbortAll()) );
3602  action->setShortcut( QKeySequence( Qt::Key_Escape ) );
3603  }
3604  {
3605  KAction *action = new KAction(i18n("Focus on Next Folder"), this);
3606  actionCollection()->addAction(QLatin1String("inc_current_folder"), action );
3607  connect( action, SIGNAL(triggered(bool)),
3608  mFolderTreeWidget->folderTreeView(), SLOT(slotFocusNextFolder()) );
3609  action->setShortcut( QKeySequence( Qt::CTRL+Qt::Key_Right ) );
3610  }
3611  {
3612  KAction *action = new KAction(i18n("Focus on Previous Folder"), this);
3613  actionCollection()->addAction(QLatin1String("dec_current_folder"), action );
3614  connect( action, SIGNAL(triggered(bool)),
3615  mFolderTreeWidget->folderTreeView(), SLOT(slotFocusPrevFolder()) );
3616  action->setShortcut( QKeySequence( Qt::CTRL+Qt::Key_Left ) );
3617  }
3618  {
3619  KAction *action = new KAction(i18n("Select Folder with Focus"), this);
3620  actionCollection()->addAction(QLatin1String("select_current_folder"), action );
3621 
3622  connect( action, SIGNAL(triggered(bool)),
3623  mFolderTreeWidget->folderTreeView(), SLOT(slotSelectFocusFolder()) );
3624  action->setShortcut( QKeySequence( Qt::CTRL+Qt::Key_Space ) );
3625  }
3626  {
3627  KAction *action = new KAction(i18n("Focus on First Folder"), this);
3628  actionCollection()->addAction(QLatin1String("focus_first_folder"), action );
3629  connect( action, SIGNAL(triggered(bool)),
3630  mFolderTreeWidget->folderTreeView(), SLOT(slotFocusFirstFolder()) );
3631  action->setShortcut( QKeySequence( Qt::CTRL + Qt::Key_Home ) );
3632  }
3633  {
3634  KAction *action = new KAction(i18n("Focus on Last Folder"), this);
3635  actionCollection()->addAction(QLatin1String("focus_last_folder"), action );
3636  connect( action, SIGNAL(triggered(bool)),
3637  mFolderTreeWidget->folderTreeView(), SLOT(slotFocusLastFolder()) );
3638  action->setShortcut( QKeySequence( Qt::CTRL + Qt::Key_End ) );
3639  }
3640  {
3641  KAction *action = new KAction(i18n("Focus on Next Message"), this);
3642  actionCollection()->addAction(QLatin1String("inc_current_message"), action );
3643  connect( action, SIGNAL(triggered(bool)),
3644  this, SLOT(slotFocusOnNextMessage()) );
3645  action->setShortcut( QKeySequence( Qt::ALT+Qt::Key_Right ) );
3646  }
3647  {
3648  KAction *action = new KAction(i18n("Focus on Previous Message"), this);
3649  actionCollection()->addAction(QLatin1String("dec_current_message"), action );
3650  connect( action, SIGNAL(triggered(bool)),
3651  this, SLOT(slotFocusOnPrevMessage()) );
3652  action->setShortcut( QKeySequence( Qt::ALT+Qt::Key_Left ) );
3653  }
3654  {
3655  KAction *action = new KAction(i18n("Select First Message"), this);
3656  actionCollection()->addAction(QLatin1String("select_first_message"), action );
3657  connect ( action, SIGNAL(triggered(bool)),
3658  this, SLOT(slotSelectFirstMessage()) );
3659  action->setShortcut( QKeySequence( Qt::ALT + Qt::Key_Home ) );
3660  }
3661  {
3662  KAction *action = new KAction(i18n("Select Last Message"), this);
3663  actionCollection()->addAction(QLatin1String("select_last_message"), action );
3664  connect ( action, SIGNAL(triggered(bool)),
3665  this, SLOT(slotSelectLastMessage()) );
3666  action->setShortcut( QKeySequence( Qt::ALT + Qt::Key_End ) );
3667  }
3668  {
3669  KAction *action = new KAction(i18n("Select Message with Focus"), this);
3670  actionCollection()->addAction( QLatin1String("select_current_message"), action );
3671  connect( action, SIGNAL(triggered(bool)),
3672  this, SLOT(slotSelectFocusedMessage()) );
3673  action->setShortcut( QKeySequence( Qt::ALT+Qt::Key_Space ) );
3674  }
3675 
3676  {
3677  KAction *action = new KAction( i18n("Set Focus to Quick Search"), this );
3678  action->setShortcut( QKeySequence( Qt::ALT + Qt::Key_Q ) );
3679  actionCollection()->addAction( QLatin1String("focus_to_quickseach"), action );
3680  connect( action, SIGNAL(triggered(bool)),
3681  SLOT(slotFocusQuickSearch()) );
3682  }
3683  {
3684  KAction *action = new KAction( i18n( "Extend Selection to Previous Message" ), this );
3685  action->setShortcut( QKeySequence( Qt::SHIFT + Qt::Key_Left ) );
3686  actionCollection()->addAction( QLatin1String("previous_message"), action );
3687  connect( action, SIGNAL(triggered(bool)),
3688  this, SLOT(slotExtendSelectionToPreviousMessage()) );
3689  }
3690  {
3691  KAction *action = new KAction( i18n( "Extend Selection to Next Message" ), this );
3692  action->setShortcut( QKeySequence( Qt::SHIFT + Qt::Key_Right ) );
3693  actionCollection()->addAction( QLatin1String("next_message"), action );
3694  connect( action, SIGNAL(triggered(bool)),
3695  this, SLOT(slotExtendSelectionToNextMessage()) );
3696  }
3697 
3698  {
3699  mMoveMsgToFolderAction = new KAction( i18n("Move Message to Folder"), this );
3700  mMoveMsgToFolderAction->setShortcut( QKeySequence( Qt::Key_M ) );
3701  actionCollection()->addAction( QLatin1String("move_message_to_folder"), mMoveMsgToFolderAction );
3702  connect( mMoveMsgToFolderAction, SIGNAL(triggered(bool)),
3703  SLOT(slotMoveSelectedMessageToFolder()) );
3704  }
3705 
3706  mArchiveAction = new KAction( i18n("Archive"), this);
3707  actionCollection()->addAction( QLatin1String("archive_mails"), mArchiveAction );
3708  connect( mArchiveAction, SIGNAL(triggered(bool)),
3709  SLOT(slotArchiveMails()) );
3710 
3711 
3712 }
3713 
3714 void KMMainWidget::slotAddFavoriteFolder()
3715 {
3716  if (!mFavoritesModel)
3717  return;
3718  QPointer<MailCommon::FolderSelectionDialog> dialog( selectFromAllFoldersDialog() );
3719  dialog->setCaption( i18n("Add Favorite Folder") );
3720  if ( dialog->exec() && dialog ) {
3721  const Akonadi::Collection collection = dialog->selectedCollection();
3722  if ( collection.isValid() ) {
3723  mFavoritesModel->addCollection( collection );
3724  }
3725  }
3726 }
3727 
3728 //-----------------------------------------------------------------------------
3729 void KMMainWidget::slotEditNotifications()
3730 {
3731  KMail::KMKnotify notifyDlg( this );
3732  notifyDlg.exec();
3733 }
3734 
3735 void KMMainWidget::slotShowExpiryProperties()
3736 {
3737  showCollectionProperties( QLatin1String( "MailCommon::CollectionExpiryPage" ) );
3738 }
3739 
3740 //-----------------------------------------------------------------------------
3741 void KMMainWidget::slotReadOn()
3742 {
3743  if ( !mMsgView )
3744  return;
3745  if ( !mMsgView->viewer()->atBottom() ) {
3746  mMsgView->viewer()->slotJumpDown();
3747  return;
3748  }
3749  slotSelectNextUnreadMessage();
3750 }
3751 
3752 void KMMainWidget::slotNextUnreadFolder()
3753 {
3754  if ( !mFolderTreeWidget )
3755  return;
3756  mGoToFirstUnreadMessageInSelectedFolder = true;
3757  mFolderTreeWidget->folderTreeView()->selectNextUnreadFolder();
3758  mGoToFirstUnreadMessageInSelectedFolder = false;
3759 }
3760 
3761 void KMMainWidget::slotPrevUnreadFolder()
3762 {
3763  if ( !mFolderTreeWidget )
3764  return;
3765  mGoToFirstUnreadMessageInSelectedFolder = true;
3766  mFolderTreeWidget->folderTreeView()->selectPrevUnreadFolder();
3767  mGoToFirstUnreadMessageInSelectedFolder = false;
3768 }
3769 
3770 void KMMainWidget::slotExpandThread()
3771 {
3772  mMessagePane->setCurrentThreadExpanded( true );
3773 }
3774 
3775 void KMMainWidget::slotCollapseThread()
3776 {
3777  mMessagePane->setCurrentThreadExpanded( false );
3778 }
3779 
3780 void KMMainWidget::slotExpandAllThreads()
3781 {
3782  // TODO: Make this asynchronous ? (if there is enough demand)
3783 #ifndef QT_NO_CURSOR
3784  MessageViewer::KCursorSaver busy( MessageViewer::KBusyPtr::busy() );
3785 #endif
3786  mMessagePane->setAllThreadsExpanded( true );
3787 }
3788 
3789 void KMMainWidget::slotCollapseAllThreads()
3790 {
3791  // TODO: Make this asynchronous ? (if there is enough demand)
3792 #ifndef QT_NO_CURSOR
3793  MessageViewer::KCursorSaver busy( MessageViewer::KBusyPtr::busy() );
3794 #endif
3795  mMessagePane->setAllThreadsExpanded( false );
3796 }
3797 
3798 //-----------------------------------------------------------------------------
3799 void KMMainWidget::updateMessageMenu()
3800 {
3801  updateMessageActions();
3802 }
3803 
3804 void KMMainWidget::startUpdateMessageActionsTimer()
3805 {
3806  // FIXME: This delay effectively CAN make the actions to be in an incoherent state
3807  // Maybe we should mark actions as "dirty" here and check it in every action handler...
3808  updateMessageActions( true );
3809 
3810  menutimer->stop();
3811  menutimer->start( 500 );
3812 }
3813 
3814 void KMMainWidget::updateMessageActions( bool fast )
3815 {
3816  Akonadi::Item::List selectedItems;
3817  Akonadi::Item::List selectedVisibleItems;
3818  bool allSelectedBelongToSameThread = false;
3819  if (mCurrentFolder && mCurrentFolder->isValid() &&
3820  mMessagePane->getSelectionStats( selectedItems, selectedVisibleItems, &allSelectedBelongToSameThread )
3821  )
3822  {
3823  mMsgActions->setCurrentMessage( mMessagePane->currentItem(), selectedVisibleItems );
3824  } else {
3825  mMsgActions->setCurrentMessage( Akonadi::Item() );
3826  }
3827 
3828  if ( !fast )
3829  updateMessageActionsDelayed();
3830 
3831 }
3832 
3833 
3834 void KMMainWidget::updateMessageActionsDelayed()
3835 {
3836  int count;
3837  Akonadi::Item::List selectedItems;
3838  Akonadi::Item::List selectedVisibleItems;
3839  bool allSelectedBelongToSameThread = false;
3840  Akonadi::Item currentMessage;
3841  if (mCurrentFolder && mCurrentFolder->isValid() &&
3842  mMessagePane->getSelectionStats( selectedItems, selectedVisibleItems, &allSelectedBelongToSameThread )
3843  )
3844  {
3845  count = selectedItems.count();
3846 
3847  currentMessage = mMessagePane->currentItem();
3848 
3849  } else {
3850  count = 0;
3851  currentMessage = Akonadi::Item();
3852  }
3853 
3854  mApplyFiltersOnFolder->setEnabled( mCurrentFolder && mCurrentFolder->isValid() );
3855 
3856  //
3857  // Here we have:
3858  //
3859  // - A list of selected messages stored in selectedSernums.
3860  // The selected messages might contain some invisible ones as a selected
3861  // collapsed node "includes" all the children in the selection.
3862  // - A list of selected AND visible messages stored in selectedVisibleSernums.
3863  // This list does not contain children of selected and collapsed nodes.
3864  //
3865  // Now, actions can operate on:
3866  // - Any set of messages
3867  // These are called "mass actions" and are enabled whenever we have a message selected.
3868  // In fact we should differentiate between actions that operate on visible selection
3869  // and those that operate on the selection as a whole (without considering visibility)...
3870  // - A single thread
3871  // These are called "thread actions" and are enabled whenever all the selected messages belong
3872  // to the same thread. If the selection doesn't cover the whole thread then the action
3873  // will act on the whole thread anyway (thus will silently extend the selection)
3874  // - A single message
3875  // And we have two sub-cases:
3876  // - The selection must contain exactly one message
3877  // These actions can't ignore the hidden messages and thus must be disabled if
3878  // the selection contains any.
3879  // - The selection must contain exactly one visible message
3880  // These actions will ignore the hidden message and thus can be enabled if
3881  // the selection contains any.
3882  //
3883 
3884  bool readOnly = mCurrentFolder && mCurrentFolder->isValid() && ( mCurrentFolder->rights() & Akonadi::Collection::ReadOnly );
3885  // can we apply strictly single message actions ? (this is false if the whole selection contains more than one message)
3886  bool single_actions = count == 1;
3887  // can we apply loosely single message actions ? (this is false if the VISIBLE selection contains more than one message)
3888  bool singleVisibleMessageSelected = selectedVisibleItems.count() == 1;
3889  // can we apply "mass" actions to the selection ? (this is actually always true if the selection is non-empty)
3890  bool mass_actions = count >= 1;
3891  // does the selection identify a single thread ?
3892  bool thread_actions = mass_actions && allSelectedBelongToSameThread && mMessagePane->isThreaded();
3893  // can we apply flags to the selected messages ?
3894  bool flags_available = GlobalSettings::self()->allowLocalFlags() || !(mCurrentFolder && mCurrentFolder->isValid() ? readOnly : true);
3895 
3896  mThreadStatusMenu->setEnabled( thread_actions );
3897  // these need to be handled individually, the user might have them
3898  // in the toolbar
3899  mWatchThreadAction->setEnabled( thread_actions && flags_available );
3900  mIgnoreThreadAction->setEnabled( thread_actions && flags_available );
3901  mMarkThreadAsReadAction->setEnabled( thread_actions );
3902  mMarkThreadAsUnreadAction->setEnabled( thread_actions );
3903  mToggleThreadToActAction->setEnabled( thread_actions && flags_available );
3904  mToggleThreadImportantAction->setEnabled( thread_actions && flags_available );
3905  bool canDeleteMessages = mCurrentFolder && mCurrentFolder->isValid() && ( mCurrentFolder->rights() & Akonadi::Collection::CanDeleteItem );
3906 
3907  mTrashThreadAction->setEnabled( thread_actions && canDeleteMessages );
3908  mDeleteThreadAction->setEnabled( thread_actions && canDeleteMessages );
3909 
3910  if ( currentMessage.isValid() )
3911  {
3912  MessageStatus status;
3913  status.setStatusFromFlags( currentMessage.flags() );
3914  mTagActionManager->updateActionStates ( count, mMessagePane->currentItem() );
3915  if (thread_actions)
3916  {
3917  mToggleThreadToActAction->setChecked( status.isToAct() );
3918  mToggleThreadImportantAction->setChecked( status.isImportant() );
3919  mWatchThreadAction->setChecked( status.isWatched() );
3920  mIgnoreThreadAction->setChecked( status.isIgnored() );
3921  }
3922  }
3923 
3924  mMoveActionMenu->setEnabled( mass_actions && canDeleteMessages );
3925  if (mMoveMsgToFolderAction)
3926  mMoveMsgToFolderAction->setEnabled( mass_actions && canDeleteMessages );
3927  //mCopyActionMenu->setEnabled( mass_actions );
3928 
3929  mDeleteAction->setEnabled( mass_actions && canDeleteMessages );
3930 
3931  mExpireConfigAction->setEnabled( canDeleteMessages );
3932 
3933  if ( mMsgView ) {
3934  mMsgView->findInMessageAction()->setEnabled( mass_actions && !CommonKernel->folderIsTemplates( mCurrentFolder->collection() ) );
3935  }
3936  mMsgActions->forwardInlineAction()->setEnabled( mass_actions && !CommonKernel->folderIsTemplates( mCurrentFolder->collection() ) );
3937  mMsgActions->forwardAttachedAction()->setEnabled( mass_actions && !CommonKernel->folderIsTemplates( mCurrentFolder->collection() ) );
3938  mMsgActions->forwardMenu()->setEnabled( mass_actions && !CommonKernel->folderIsTemplates( mCurrentFolder->collection() ) );
3939 
3940  mMsgActions->editAction()->setEnabled( single_actions );
3941  mUseAction->setEnabled( single_actions && CommonKernel->folderIsTemplates( mCurrentFolder->collection() ) );
3942  filterMenu()->setEnabled( single_actions );
3943  mMsgActions->redirectAction()->setEnabled( /*single_actions &&*/mass_actions && !CommonKernel->folderIsTemplates( mCurrentFolder->collection() ) );
3944 
3945  if ( mMsgActions->customTemplatesMenu() )
3946  {
3947  mMsgActions->customTemplatesMenu()->forwardActionMenu()->setEnabled( mass_actions );
3948  mMsgActions->customTemplatesMenu()->replyActionMenu()->setEnabled( single_actions );
3949  mMsgActions->customTemplatesMenu()->replyAllActionMenu()->setEnabled( single_actions );
3950  }
3951 
3952  // "Print" will act on the current message: it will ignore any hidden selection
3953  mMsgActions->printAction()->setEnabled( singleVisibleMessageSelected );
3954  // "Print preview" will act on the current message: it will ignore any hidden selection
3955  KAction *printPreviewAction = mMsgActions->printPreviewAction();
3956  if (printPreviewAction)
3957  printPreviewAction->setEnabled( singleVisibleMessageSelected );
3958 
3959  // "View Source" will act on the current message: it will ignore any hidden selection
3960  if (mMsgView) {
3961  mMsgView->viewSourceAction()->setEnabled( singleVisibleMessageSelected );
3962  }
3963  MessageStatus status;
3964  status.setStatusFromFlags( currentMessage.flags() );
3965 
3966  QList< QAction *> actionList;
3967  bool statusSendAgain = single_actions && ( ( currentMessage.isValid() && status.isSent() ) || ( currentMessage.isValid() && CommonKernel->folderIsSentMailFolder( mCurrentFolder->collection() ) ) );
3968  if ( statusSendAgain ) {
3969  actionList << mSendAgainAction;
3970  } else if ( single_actions ) {
3971  actionList << messageActions()->editAction();
3972  }
3973  actionList << mSaveAttachmentsAction;
3974  if (FolderArchive::FolderArchiveUtil::folderArchiveAgentEnabled() && mCurrentFolder && FolderArchive::FolderArchiveUtil::resourceSupportArchiving(mCurrentFolder->collection().resource()))
3975  actionList << mArchiveAction;
3976  mGUIClient->unplugActionList( QLatin1String( "messagelist_actionlist" ) );
3977  mGUIClient->plugActionList( QLatin1String( "messagelist_actionlist" ), actionList );
3978  mSendAgainAction->setEnabled( statusSendAgain );
3979 
3980  mSaveAsAction->setEnabled( mass_actions );
3981 
3982  if ((mCurrentFolder&& mCurrentFolder->isValid())) {
3983  updateMoveAction( mCurrentFolder->statistics() );
3984  }
3985  else {
3986  updateMoveAction(false,false);
3987  }
3988 
3989  const qint64 nbMsgOutboxCollection = MailCommon::Util::updatedCollection( CommonKernel->outboxCollectionFolder() ).statistics().count();
3990 
3991  mSendQueued->setEnabled( nbMsgOutboxCollection > 0 );
3992  mSendActionMenu->setEnabled( nbMsgOutboxCollection > 0 );
3993 
3994  const bool newPostToMailingList = mCurrentFolder && mCurrentFolder->isMailingListEnabled();
3995  mMessageNewList->setEnabled(newPostToMailingList);
3996 
3997  slotUpdateOnlineStatus( static_cast<GlobalSettingsBase::EnumNetworkState::type>( GlobalSettings::self()->networkState() ) );
3998  if (action( QLatin1String("kmail_undo") ))
3999  action( QLatin1String("kmail_undo") )->setEnabled( kmkernel->undoStack()->size() > 0 );
4000 
4001  // Enable / disable all filters.
4002  foreach ( QAction *filterAction, mFilterMenuActions ) {
4003  filterAction->setEnabled( count > 0 );
4004  }
4005 
4006  mApplyAllFiltersAction->setEnabled( count);
4007  mApplyFilterActionsMenu->setEnabled( count );
4008 }
4009 
4010 
4011 void KMMainWidget::slotAkonadiStandardActionUpdated()
4012 {
4013  bool multiFolder = false;
4014  if ( mFolderTreeWidget ) {
4015  multiFolder = mFolderTreeWidget->selectedCollections().count() > 1;
4016  }
4017  if ( mCollectionProperties ) {
4018  if ( mCurrentFolder && mCurrentFolder->collection().isValid() ) {
4019  const Akonadi::AgentInstance instance =
4020  Akonadi::AgentManager::self()->instance( mCurrentFolder->collection().resource() );
4021 
4022  mCollectionProperties->setEnabled( !multiFolder &&
4023  !mCurrentFolder->isStructural() &&
4024  (instance.status()!=Akonadi::AgentInstance::Broken) );
4025  } else {
4026  mCollectionProperties->setEnabled(false);
4027  }
4028  QList< QAction* > collectionProperties;
4029  if ( mCollectionProperties->isEnabled() )
4030  collectionProperties << mCollectionProperties;
4031  mGUIClient->unplugActionList( QLatin1String("akonadi_collection_collectionproperties_actionlist") );
4032  mGUIClient->plugActionList( QLatin1String("akonadi_collection_collectionproperties_actionlist"), collectionProperties );
4033 
4034  }
4035 
4036  const bool folderWithContent = mCurrentFolder && !mCurrentFolder->isStructural();
4037 
4038  if ( mAkonadiStandardActionManager->action( Akonadi::StandardActionManager::DeleteCollections ) ) {
4039 
4040  mAkonadiStandardActionManager->action( Akonadi::StandardActionManager::DeleteCollections )->setEnabled( mCurrentFolder
4041  && !multiFolder
4042  && ( mCurrentFolder->collection().rights() & Collection::CanDeleteCollection )
4043  && !mCurrentFolder->isSystemFolder()
4044  && folderWithContent
4045  && mCurrentFolder->collection().resource() != QLatin1String("akonadi_nepomuktag_resource") );
4046  }
4047 
4048  if ( mAkonadiStandardActionManager->action( Akonadi::StandardMailActionManager::MoveAllToTrash ) ) {
4049  mAkonadiStandardActionManager->action( Akonadi::StandardMailActionManager::MoveAllToTrash )->setEnabled( folderWithContent
4050  && ( mCurrentFolder->count() > 0 )
4051  && mCurrentFolder->canDeleteMessages()
4052  && !multiFolder );
4053  mAkonadiStandardActionManager->action( Akonadi::StandardMailActionManager::MoveAllToTrash )->setText( (mCurrentFolder && CommonKernel->folderIsTrash(mCurrentFolder->collection())) ? i18n("E&mpty Trash") : i18n("&Move All Messages to Trash") );
4054  }
4055 
4056 
4057  QList< QAction* > addToFavorite;
4058  QAction *actionAddToFavoriteCollections = akonadiStandardAction( Akonadi::StandardActionManager::AddToFavoriteCollections );
4059  if ( actionAddToFavoriteCollections ) {
4060  if ( mEnableFavoriteFolderView && actionAddToFavoriteCollections->isEnabled() )
4061  addToFavorite << actionAddToFavoriteCollections;
4062  mGUIClient->unplugActionList( QLatin1String("akonadi_collection_add_to_favorites_actionlist") );
4063  mGUIClient->plugActionList( QLatin1String("akonadi_collection_add_to_favorites_actionlist"), addToFavorite );
4064  }
4065 
4066  QList< QAction* > syncActionList;
4067  QAction *actionSync = akonadiStandardAction( Akonadi::StandardActionManager::SynchronizeCollections );
4068  if ( actionSync && actionSync->isEnabled() ) {
4069  syncActionList << actionSync;
4070  }
4071  actionSync = akonadiStandardAction( Akonadi::StandardActionManager::SynchronizeCollectionsRecursive );
4072  if ( actionSync && actionSync->isEnabled() ) {
4073  syncActionList << actionSync;
4074  }
4075  mGUIClient->unplugActionList( QLatin1String("akonadi_collection_sync_actionlist") );
4076  mGUIClient->plugActionList( QLatin1String("akonadi_collection_sync_actionlist"), syncActionList );
4077 
4078 
4079 
4080  QList< QAction* > actionList;
4081 
4082  QAction *action = mAkonadiStandardActionManager->action( Akonadi::StandardActionManager::CreateCollection );
4083  if ( action && action->isEnabled() ) {
4084  actionList << action;
4085  }
4086 
4087  action = mAkonadiStandardActionManager->action( Akonadi::StandardActionManager::MoveCollectionToMenu );
4088  if ( action && action->isEnabled() ) {
4089  actionList <<action;
4090  }
4091 
4092  action = mAkonadiStandardActionManager->action( Akonadi::StandardActionManager::CopyCollectionToMenu);
4093  if ( action && action->isEnabled() ) {
4094  actionList <<action;
4095  }
4096  mGUIClient->unplugActionList( QLatin1String("akonadi_collection_move_copy_menu_actionlist") );
4097  mGUIClient->plugActionList( QLatin1String("akonadi_collection_move_copy_menu_actionlist"), actionList );
4098 
4099 
4100 }
4101 
4102 void KMMainWidget::updateHtmlMenuEntry()
4103 {
4104  if (mPreferHtmlAction && mPreferHtmlLoadExtAction) {
4105  bool multiFolder = false;
4106  if ( mFolderTreeWidget ) {
4107  multiFolder = mFolderTreeWidget->selectedCollections().count() > 1;
4108  }
4109  // the visual ones only make sense if we are showing a message list
4110  mPreferHtmlAction->setEnabled( mFolderTreeWidget &&
4111  mFolderTreeWidget->folderTreeView()->currentFolder().isValid() &&
4112  !multiFolder );
4113  mPreferHtmlLoadExtAction->setEnabled( mFolderTreeWidget &&
4114  mFolderTreeWidget->folderTreeView()->currentFolder().isValid() &&
4115  !multiFolder &&
4116  (mHtmlPref ? !mFolderHtmlPref : mFolderHtmlPref) ? true : false );
4117  mPreferHtmlAction->setChecked( !multiFolder && ( mHtmlPref ? !mFolderHtmlPref : mFolderHtmlPref ) );
4118  mPreferHtmlLoadExtAction->setChecked( !multiFolder && ( mHtmlLoadExtPref ? !mFolderHtmlLoadExtPref : mFolderHtmlLoadExtPref ) );
4119  }
4120 }
4121 
4122 //-----------------------------------------------------------------------------
4123 void KMMainWidget::updateFolderMenu()
4124 {
4125  if (!CommonKernel->outboxCollectionFolder().isValid()) {
4126  QTimer::singleShot(1000,this,SLOT(updateFolderMenu()));
4127  return;
4128  }
4129 
4130  const bool folderWithContent = mCurrentFolder && !mCurrentFolder->isStructural();
4131  bool multiFolder = false;
4132  if ( mFolderTreeWidget ) {
4133  multiFolder = mFolderTreeWidget->selectedCollections().count() > 1;
4134  }
4135  mFolderMailingListPropertiesAction->setEnabled( folderWithContent &&
4136  !multiFolder &&
4137  !mCurrentFolder->isSystemFolder() );
4138 
4139  QList< QAction* > actionlist;
4140  if ( mCurrentFolder && mCurrentFolder->collection().id() == CommonKernel->outboxCollectionFolder().id() && (mCurrentFolder->collection()).statistics().count() > 0) {
4141  kDebug() << "Enabling send queued";
4142  mSendQueued->setEnabled(true);
4143  actionlist << mSendQueued;
4144  }
4145 // if ( mCurrentFolder && mCurrentFolder->collection().id() != CommonKernel->trashCollectionFolder().id() ) {
4146 // actionlist << mTrashAction;
4147 // }
4148  mGUIClient->unplugActionList( QLatin1String( "outbox_folder_actionlist" ) );
4149  mGUIClient->plugActionList( QLatin1String( "outbox_folder_actionlist" ), actionlist );
4150  actionlist.clear();
4151 
4152  const bool isASearchFolder = mCurrentFolder && mCurrentFolder->collection().resource() == QLatin1String( "akonadi_search_resource" );
4153  if (isASearchFolder)
4154  mAkonadiStandardActionManager->action( Akonadi::StandardActionManager::DeleteCollections )->setText( i18n("&Delete Search") );
4155 
4156  mArchiveFolderAction->setEnabled( mCurrentFolder && !multiFolder && folderWithContent );
4157 
4158  bool isInTrashFolder = (mCurrentFolder && CommonKernel->folderIsTrash(mCurrentFolder->collection()));
4159  akonadiStandardAction( Akonadi::StandardMailActionManager::MoveToTrash )->setText( isInTrashFolder ? i18nc("@action Hard delete, bypassing trash", "&Delete"): i18n("&Move to Trash") );
4160 
4161  mTrashThreadAction->setText(isInTrashFolder ?i18n("Delete T&hread"): i18n("M&ove Thread to Trash"));
4162 
4163 
4164 
4165  mExpireConfigAction->setEnabled( mCurrentFolder &&
4166  !mCurrentFolder->isStructural() &&
4167  !multiFolder &&
4168  mCurrentFolder->canDeleteMessages() &&
4169  folderWithContent &&
4170  !MailCommon::Util::isVirtualCollection( mCurrentFolder->collection() ) );
4171 
4172  updateHtmlMenuEntry();
4173 
4174  mShowFolderShortcutDialogAction->setEnabled( !multiFolder && folderWithContent );
4175 
4176  actionlist << akonadiStandardAction( Akonadi::StandardActionManager::ManageLocalSubscriptions );
4177  bool imapFolderIsOnline = false;
4178  if (mCurrentFolder && kmkernel->isImapFolder( mCurrentFolder->collection(),imapFolderIsOnline )) {
4179  if (imapFolderIsOnline) {
4180  actionlist << mServerSideSubscription;
4181  }
4182  }
4183 
4184  mGUIClient->unplugActionList( QLatin1String( "collectionview_actionlist" ) );
4185  mGUIClient->plugActionList( QLatin1String( "collectionview_actionlist" ), actionlist );
4186 
4187 }
4188 
4189 //-----------------------------------------------------------------------------
4190 void KMMainWidget::slotIntro()
4191 {
4192  if ( !mMsgView )
4193  return;
4194 
4195  mMsgView->clear( true );
4196 
4197  // hide widgets that are in the way:
4198  if ( mMessagePane && mLongFolderList )
4199  mMessagePane->hide();
4200  mMsgView->displayAboutPage();
4201 
4202  mCurrentFolder.clear();
4203 }
4204 
4205 void KMMainWidget::slotShowStartupFolder()
4206 {
4207  connect( MailCommon::FilterManager::instance(), SIGNAL(filtersChanged()),
4208  this, SLOT(initializeFilterActions()) );
4209  // Plug various action lists. This can't be done in the constructor, as that is called before
4210  // the main window or Kontact calls createGUI().
4211  // This function however is called with a single shot timer.
4212  checkAkonadiServerManagerState();
4213  mFolderShortcutActionManager->createActions();
4214  mTagActionManager->createActions();
4215  messageActions()->setupForwardingActionsList( mGUIClient );
4216 
4217  QString newFeaturesMD5 = KMReaderWin::newFeaturesMD5();
4218  if ( kmkernel->firstStart() ||
4219  GlobalSettings::self()->previousNewFeaturesMD5() != newFeaturesMD5 ) {
4220  GlobalSettings::self()->setPreviousNewFeaturesMD5( newFeaturesMD5 );
4221  slotIntro();
4222  return;
4223  }
4224 }
4225 
4226 void KMMainWidget::checkAkonadiServerManagerState()
4227 {
4228  Akonadi::ServerManager::State state = Akonadi::ServerManager::self()->state();
4229  if (state == Akonadi::ServerManager::Running) {
4230  initializeFilterActions();
4231  } else {
4232  connect( Akonadi::ServerManager::self(), SIGNAL(stateChanged(Akonadi::ServerManager::State)),
4233  SLOT(slotServerStateChanged(Akonadi::ServerManager::State)) );
4234  }
4235 }
4236 
4237 void KMMainWidget::slotServerStateChanged(Akonadi::ServerManager::State state)
4238 {
4239  if (state == Akonadi::ServerManager::Running) {
4240  initializeFilterActions();
4241  disconnect( Akonadi::ServerManager::self(), SIGNAL(stateChanged(Akonadi::ServerManager::State)));
4242  }
4243 }
4244 
4245 
4246 void KMMainWidget::slotShowTip()
4247 {
4248  KTipDialog::showTip( this, QString(), true );
4249 }
4250 
4251 QList<KActionCollection*> KMMainWidget::actionCollections() const {
4252  return QList<KActionCollection*>() << actionCollection();
4253 }
4254 
4255 //-----------------------------------------------------------------------------
4256 void KMMainWidget::slotUpdateUndo()
4257 {
4258  if ( actionCollection()->action( QLatin1String("kmail_undo") ) ) {
4259  actionCollection()->action( QLatin1String("kmail_undo") )->setEnabled( kmkernel->undoStack()->size()>0 );
4260  }
4261 }
4262 
4263 //-----------------------------------------------------------------------------
4264 void KMMainWidget::clearFilterActions()
4265 {
4266  if ( !mFilterTBarActions.isEmpty() )
4267  if ( mGUIClient->factory() )
4268  mGUIClient->unplugActionList( QLatin1String("toolbar_filter_actions") );
4269 
4270  if ( !mFilterMenuActions.isEmpty() )
4271  if ( mGUIClient->factory() )
4272  mGUIClient->unplugActionList( QLatin1String("menu_filter_actions") );
4273 
4274  foreach ( QAction *a, mFilterMenuActions )
4275  actionCollection()->removeAction( a );
4276 
4277  mApplyFilterActionsMenu->menu()->clear();
4278  mFilterTBarActions.clear();
4279  mFilterMenuActions.clear();
4280 
4281  qDeleteAll( mFilterCommands );
4282  mFilterCommands.clear();
4283 }
4284 
4285 //-----------------------------------------------------------------------------
4286 void KMMainWidget::initializeFilterActions()
4287 {
4288  clearFilterActions();
4289  mApplyFilterActionsMenu->menu()->addAction( mApplyAllFiltersAction );
4290  bool addedSeparator = false;
4291 
4292  foreach ( MailFilter *filter, MailCommon::FilterManager::instance()->filters() ) {
4293  if ( !filter->isEmpty() && filter->configureShortcut() && filter->isEnabled() ) {
4294  QString filterName = QString::fromLatin1( "Filter %1").arg( filter->name() );
4295  QString normalizedName = filterName.replace(QLatin1Char(' '), QLatin1Char('_'));
4296  if ( action( normalizedName ) ) {
4297  continue;
4298  }
4299  KMMetaFilterActionCommand *filterCommand = new KMMetaFilterActionCommand( filter->identifier(), this );
4300  mFilterCommands.append( filterCommand );
4301  QString displayText = i18n( "Filter %1", filter->name() );
4302  QString icon = filter->icon();
4303  if ( icon.isEmpty() ) {
4304  icon = QLatin1String("system-run");
4305  }
4306  KAction *filterAction = new KAction( KIcon( icon ), displayText, actionCollection() );
4307  filterAction->setIconText( filter->toolbarName() );
4308 
4309  // The shortcut configuration is done in the filter dialog.
4310  // The shortcut set in the shortcut dialog would not be saved back to
4311  // the filter settings correctly.
4312  filterAction->setShortcutConfigurable( false );
4313  actionCollection()->addAction( normalizedName,
4314  filterAction );
4315  connect( filterAction, SIGNAL(triggered(bool)),
4316  filterCommand, SLOT(start()) );
4317  filterAction->setShortcuts( filter->shortcut() );
4318  if ( !addedSeparator ) {
4319  QAction *a = mApplyFilterActionsMenu->menu()->addSeparator();
4320  mFilterMenuActions.append( a );
4321  addedSeparator = true;
4322  }
4323  mApplyFilterActionsMenu->menu()->addAction( filterAction );
4324  mFilterMenuActions.append( filterAction );
4325  if ( filter->configureToolbar() ) {
4326  mFilterTBarActions.append( filterAction );
4327  }
4328  }
4329  }
4330  if ( !mFilterMenuActions.isEmpty() && mGUIClient->factory() )
4331  mGUIClient->plugActionList( QLatin1String("menu_filter_actions"), mFilterMenuActions );
4332  if ( !mFilterTBarActions.isEmpty() && mGUIClient->factory() ) {
4333  mFilterTBarActions.prepend( mToolbarActionSeparator );
4334  mGUIClient->plugActionList( QLatin1String("toolbar_filter_actions"), mFilterTBarActions );
4335  }
4336 
4337  // Our filters have changed, now enable/disable them
4338  updateMessageActions();
4339 }
4340 
4341 //-----------------------------------------------------------------------------
4342 void KMMainWidget::slotAntiSpamWizard()
4343 {
4344  AntiSpamWizard wiz( AntiSpamWizard::AntiSpam, this );
4345  wiz.exec();
4346 }
4347 
4348 //-----------------------------------------------------------------------------
4349 void KMMainWidget::slotAntiVirusWizard()
4350 {
4351  AntiSpamWizard wiz( AntiSpamWizard::AntiVirus, this);
4352  wiz.exec();
4353 }
4354 //-----------------------------------------------------------------------------
4355 void KMMainWidget::slotAccountWizard()
4356 {
4357  KMail::Util::launchAccountWizard( this );
4358 }
4359 
4360 void KMMainWidget::slotImportWizard()
4361 {
4362  const QString path = KStandardDirs::findExe( QLatin1String("importwizard" ) );
4363  if ( !QProcess::startDetached( path ) )
4364  KMessageBox::error( this, i18n( "Could not start the import wizard. "
4365  "Please check your installation." ),
4366  i18n( "Unable to start import wizard" ) );
4367 }
4368 
4369 //-----------------------------------------------------------------------------
4370 void KMMainWidget::slotFilterLogViewer()
4371 {
4372  MailCommon::FilterManager::instance()->showFilterLogDialog( (qlonglong)winId() );
4373 }
4374 
4375 //-----------------------------------------------------------------------------
4376 void KMMainWidget::updateFileMenu()
4377 {
4378  const bool isEmpty = MailCommon::Util::agentInstances().isEmpty();
4379  actionCollection()->action(QLatin1String("check_mail"))->setEnabled( !isEmpty );
4380  actionCollection()->action(QLatin1String("check_mail_in"))->setEnabled( !isEmpty );
4381 }
4382 
4383 //-----------------------------------------------------------------------------
4384 const KMMainWidget::PtrList * KMMainWidget::mainWidgetList()
4385 {
4386  // better safe than sorry; check whether the global static has already been destroyed
4387  if ( theMainWidgetList.isDestroyed() )
4388  {
4389  return 0;
4390  }
4391  return theMainWidgetList;
4392 }
4393 
4394 QSharedPointer<FolderCollection> KMMainWidget::currentFolder() const
4395 {
4396  return mCurrentFolder;
4397 }
4398 
4399 //-----------------------------------------------------------------------------
4400 QString KMMainWidget::overrideEncoding() const
4401 {
4402  if ( mMsgView )
4403  return mMsgView->overrideEncoding();
4404  else
4405  return MessageCore::GlobalSettings::self()->overrideCharacterEncoding();
4406 }
4407 
4408 void KMMainWidget::showEvent( QShowEvent *event )
4409 {
4410  QWidget::showEvent( event );
4411  mWasEverShown = true;
4412 }
4413 
4414 void KMMainWidget::slotRequestFullSearchFromQuickSearch()
4415 {
4416  // First, open the search window. If we are currently on a search folder,
4417  // the search associated with that will be loaded.
4418  if ( !slotSearch() )
4419  return;
4420 
4421  assert( mSearchWin );
4422 
4423  // Now we look at the current state of the quick search, and if there's
4424  // something in there, we add the criteria to the existing search for
4425  // the search folder, if applicable, or make a new one from it.
4426  SearchPattern pattern;
4427  const QString searchString = mMessagePane->currentFilterSearchString();
4428  if ( !searchString.isEmpty() )
4429  pattern.append( SearchRule::createInstance( "<message>", SearchRule::FuncContains, searchString ) );
4430  MessageStatus status = mMessagePane->currentFilterStatus();
4431  if ( status.hasAttachment() ) {
4432  pattern.append( SearchRule::createInstance( "<message>", SearchRule::FuncHasAttachment ) );
4433  status.setHasAttachment( false );
4434  }
4435 
4436  if ( !status.isOfUnknownStatus() ) {
4437  pattern.append( SearchRule::Ptr( new SearchRuleStatus( status ) ) );
4438  }
4439 
4440  if ( !pattern.isEmpty() )
4441  mSearchWin->addRulesToSearchPattern( pattern );
4442 }
4443 
4444 void KMMainWidget::updateVacationScriptStatus( bool active, const QString &serverName )
4445 {
4446  mVacationIndicatorActive = active;
4447  if ( active ) {
4448  mVacationScriptIndicator->setText( i18n("Out of office reply active on server \"%1\"", serverName) );
4449  mVacationScriptIndicator->setBackgroundColor( Qt::yellow );
4450  mVacationScriptIndicator->setCursor( QCursor( Qt::PointingHandCursor ) );
4451  mVacationScriptIndicator->show();
4452  } else {
4453  mVacationScriptIndicator->hide();
4454  }
4455 }
4456 
4457 QLabel * KMMainWidget::vacationScriptIndicator() const
4458 {
4459  return mVacationScriptIndicator;
4460 }
4461 
4462 void KMMainWidget::slotMessageSelected(const Akonadi::Item &item)
4463 {
4464  delete mShowBusySplashTimer;
4465  mShowBusySplashTimer = 0;
4466  if ( mMsgView ) {
4467  // The current selection was cleared, so we'll remove the previously
4468  // selected message from the preview pane
4469  if ( !item.isValid() ) {
4470  mMsgView->clear();
4471  } else {
4472  mShowBusySplashTimer = new QTimer( this );
4473  mShowBusySplashTimer->setSingleShot( true );
4474  connect( mShowBusySplashTimer, SIGNAL(timeout()), this, SLOT(slotShowBusySplash()) );
4475  mShowBusySplashTimer->start( GlobalSettings::self()->folderLoadingTimeout() ); //TODO: check if we need a different timeout setting for this
4476 
4477  Akonadi::ItemFetchJob *itemFetchJob = MessageViewer::Viewer::createFetchJob( item );
4478  const QString resource = mCurrentFolder->collection().resource();
4479  itemFetchJob->setProperty( "_resource", QVariant::fromValue(resource) );
4480  connect( itemFetchJob, SIGNAL(itemsReceived(Akonadi::Item::List)),
4481  SLOT(itemsReceived(Akonadi::Item::List)) );
4482  connect( itemFetchJob, SIGNAL(result(KJob*)), SLOT(itemsFetchDone(KJob*)) );
4483  }
4484  }
4485 }
4486 
4487 void KMMainWidget::itemsReceived(const Akonadi::Item::List &list )
4488 {
4489  Q_ASSERT( list.size() == 1 );
4490  delete mShowBusySplashTimer;
4491  mShowBusySplashTimer = 0;
4492 
4493  if ( !mMsgView )
4494  return;
4495 
4496  Item item = list.first();
4497 
4498  if ( mMessagePane ) {
4499  mMessagePane->show();
4500 
4501  if ( mMessagePane->currentItem() != item ) {
4502  // The user has selected another email already, so don't render this one.
4503  // Mark it as read, though, if the user settings say so.
4504  if ( MessageViewer::GlobalSettings::self()->delayedMarkAsRead() &&
4505  MessageViewer::GlobalSettings::self()->delayedMarkTime() == 0 ) {
4506  item.setFlag( Akonadi::MessageFlags::Seen );
4507  Akonadi::ItemModifyJob *modifyJob = new Akonadi::ItemModifyJob( item, this );
4508  modifyJob->disableRevisionCheck();
4509  modifyJob->setIgnorePayload( true );
4510  }
4511  return;
4512  }
4513  }
4514 
4515  mMsgView->setMessage( item );
4516  // reset HTML override to the folder setting
4517  mMsgView->setHtmlOverride(mFolderHtmlPref);
4518  mMsgView->setHtmlLoadExtOverride(mFolderHtmlLoadExtPref);
4519  mMsgView->setDecryptMessageOverwrite( false );
4520  mMsgActions->setCurrentMessage( item );
4521 }
4522 
4523 void KMMainWidget::itemsFetchDone( KJob *job )
4524 {
4525  delete mShowBusySplashTimer;
4526  mShowBusySplashTimer = 0;
4527  if ( job->error() ) {
4528  // Unfortunately job->error() is Job::Unknown in many cases.
4529  // (see JobPrivate::handleResponse in akonadi/job.cpp)
4530  // So we show the "offline" page after checking the resource status.
4531  kDebug() << job->error() << job->errorString();
4532 
4533  const QString resource = job->property("_resource").toString();
4534  const Akonadi::AgentInstance agentInstance = Akonadi::AgentManager::self()->instance( resource );
4535  if ( !agentInstance.isOnline() ) {
4536  // The resource is offline
4537  if ( mMsgView ) {
4538  mMsgView->viewer()->enableMessageDisplay();
4539  mMsgView->clear( true );
4540  }
4541  mMessagePane->show();
4542 
4543  if (kmkernel->isOffline())
4544  showOfflinePage();
4545  else
4546  showResourceOfflinePage();
4547  } else {
4548  // Some other error
4549  BroadcastStatus::instance()->setStatusMsg( job->errorString() );
4550  }
4551  }
4552 }
4553 
4554 KAction *KMMainWidget::akonadiStandardAction( Akonadi::StandardActionManager::Type type )
4555 {
4556  return mAkonadiStandardActionManager->action( type );
4557 }
4558 
4559 KAction *KMMainWidget::akonadiStandardAction( Akonadi::StandardMailActionManager::Type type )
4560 {
4561  return mAkonadiStandardActionManager->action( type );
4562 }
4563 
4564 void KMMainWidget::slotCollectionProperties()
4565 {
4566  showCollectionProperties( QString() );
4567 }
4568 
4569 void KMMainWidget::showCollectionProperties( const QString &pageToShow )
4570 {
4571  if ( !mCurrentFolder )
4572  return;
4573 
4574  if ( Solid::Networking::status() == Solid::Networking::Unconnected ) {
4575  KMessageBox::information(
4576  this,
4577  i18n( "Network is unconnected. Folder information cannot be updated." ) );
4578  showCollectionPropertiesContinued( pageToShow, QPointer<KPIM::ProgressItem>() );
4579  } else {
4580  const Akonadi::AgentInstance agentInstance = Akonadi::AgentManager::self()->instance( mCurrentFolder->collection().resource() );
4581  bool isOnline = agentInstance.isOnline();
4582  if (!isOnline) {
4583  showCollectionPropertiesContinued( pageToShow, QPointer<KPIM::ProgressItem>() );
4584  } else {
4585  QPointer<KPIM::ProgressItem> progressItem( KPIM::ProgressManager::createProgressItem( i18n( "Retrieving folder properties" ) ) );
4586  progressItem->setUsesBusyIndicator( true );
4587 
4588  Akonadi::CollectionAttributesSynchronizationJob *sync
4589  = new Akonadi::CollectionAttributesSynchronizationJob( mCurrentFolder->collection() );
4590  sync->setProperty( "collectionId", mCurrentFolder->collection().id() );
4591  sync->setProperty( "pageToShow", pageToShow ); // note for dialog later
4592  sync->setProperty( "progressItem", QVariant::fromValue( progressItem ) );
4593  connect( sync, SIGNAL(result(KJob*)),
4594  this, SLOT(slotCollectionPropertiesContinued(KJob*)) );
4595  connect( progressItem, SIGNAL(progressItemCanceled(KPIM::ProgressItem*)),
4596  sync, SLOT(kill()) );
4597  connect( progressItem, SIGNAL(progressItemCanceled(KPIM::ProgressItem*)),
4598  KPIM::ProgressManager::instance(), SLOT(slotStandardCancelHandler(KPIM::ProgressItem*)) );
4599  sync->start();
4600  }
4601  }
4602 }
4603 
4604 void KMMainWidget::slotCollectionPropertiesContinued( KJob* job )
4605 {
4606  QString pageToShow;
4607  QPointer<KPIM::ProgressItem> progressItem;
4608 
4609  if ( job ) {
4610  Akonadi::CollectionAttributesSynchronizationJob *sync
4611  = dynamic_cast<Akonadi::CollectionAttributesSynchronizationJob *>( job );
4612  Q_ASSERT( sync );
4613  if ( sync->property( "collectionId" ) != mCurrentFolder->collection().id() )
4614  return;
4615  pageToShow = sync->property( "pageToShow" ).toString();
4616  progressItem = sync->property( "progressItem" ).value< QPointer<KPIM::ProgressItem> >();
4617  if ( progressItem ) {
4618  disconnect( progressItem, SIGNAL(progressItemCanceled(KPIM::ProgressItem*)),
4619  sync, SLOT(kill()) );
4620  } else {
4621  // progressItem does not exist anymore, operation has been canceled
4622  return;
4623  }
4624  }
4625 
4626  showCollectionPropertiesContinued( pageToShow, progressItem );
4627 }
4628 
4629 void KMMainWidget::showCollectionPropertiesContinued( const QString &pageToShow, QPointer<KPIM::ProgressItem> progressItem )
4630 {
4631  if ( !progressItem ) {
4632  progressItem = KPIM::ProgressManager::createProgressItem( i18n( "Retrieving folder properties" ) );
4633  progressItem->setUsesBusyIndicator( true );
4634  connect( progressItem, SIGNAL(progressItemCanceled(KPIM::ProgressItem*)),
4635  KPIM::ProgressManager::instance(), SLOT(slotStandardCancelHandler(KPIM::ProgressItem*)) );
4636  }
4637 
4638  Akonadi::CollectionFetchJob *fetch = new Akonadi::CollectionFetchJob( mCurrentFolder->collection(),
4639  Akonadi::CollectionFetchJob::Base );
4640  connect( progressItem, SIGNAL(progressItemCanceled(KPIM::ProgressItem*)), fetch, SLOT(kill()) );
4641  fetch->fetchScope().setIncludeStatistics( true );
4642  fetch->setProperty( "pageToShow", pageToShow );
4643  fetch->setProperty( "progressItem", QVariant::fromValue( progressItem ) );
4644  connect( fetch, SIGNAL(result(KJob*)),
4645  this, SLOT(slotCollectionPropertiesFinished(KJob*)) );
4646  connect( progressItem, SIGNAL(progressItemCanceled(KPIM::ProgressItem*)),
4647  fetch, SLOT(kill()) );
4648 }
4649 
4650 void KMMainWidget::slotCollectionPropertiesFinished( KJob *job )
4651 {
4652  if ( !job )
4653  return;
4654 
4655  QPointer<KPIM::ProgressItem> progressItem = job->property( "progressItem" ).value< QPointer<KPIM::ProgressItem> >();
4656  // progressItem does not exist anymore, operation has been canceled
4657  if ( !progressItem ) {
4658  return;
4659  }
4660 
4661  progressItem->setComplete();
4662  progressItem->setStatus( i18n( "Done" ) );
4663 
4664  Akonadi::CollectionFetchJob *fetch = dynamic_cast<Akonadi::CollectionFetchJob *>( job );
4665  Q_ASSERT( fetch );
4666  if ( fetch->collections().isEmpty() )
4667  {
4668  kWarning() << "no collection";
4669  return;
4670  }
4671 
4672  const Akonadi::Collection collection = fetch->collections().first();
4673 
4674  const QStringList pages = QStringList() << QLatin1String( "MailCommon::CollectionGeneralPage" )
4675  << QLatin1String( "KMail::CollectionViewPage" )
4676  << QLatin1String( "Akonadi::CachePolicyPage" )
4677  << QLatin1String( "KMail::CollectionTemplatesPage" )
4678  << QLatin1String( "MailCommon::CollectionExpiryPage" )
4679  << QLatin1String( "PimCommon::CollectionAclPage" )
4680  << QLatin1String( "KMail::CollectionMailingListPage" )
4681  << QLatin1String( "KMail::CollectionQuotaPage" )
4682  << QLatin1String( "KMail::CollectionShortcutPage" )
4683  << QLatin1String( "KMail::CollectionMaintenancePage" );
4684 
4685  Akonadi::CollectionPropertiesDialog *dlg = new Akonadi::CollectionPropertiesDialog( collection, pages, this );
4686  dlg->setCaption( i18nc( "@title:window", "Properties of Folder %1", collection.name() ) );
4687 
4688 
4689  const QString pageToShow = fetch->property( "pageToShow" ).toString();
4690  if ( !pageToShow.isEmpty() ) { // show a specific page
4691  dlg->setCurrentPage( pageToShow );
4692  }
4693  dlg->show();
4694 }
4695 
4696 void KMMainWidget::slotRemoveDuplicates()
4697 {
4698  KPIM::ProgressItem *item = KPIM::ProgressManager::createProgressItem( i18n( "Removing duplicates" ) );
4699  item->setUsesBusyIndicator( true );
4700 
4701  QItemSelectionModel *selectionModel = mFolderTreeWidget->folderTreeView()->selectionModel();
4702  QModelIndexList indexes = selectionModel->selectedIndexes();
4703  Akonadi::Collection::List collections;
4704 
4705  Q_FOREACH (const QModelIndex &index, indexes) {
4706  Akonadi::Collection collection = index.data(Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
4707  if ( collection.isValid() ) {
4708  collections << collection;
4709  }
4710  }
4711 
4712  Akonadi::RemoveDuplicatesJob *job = new RemoveDuplicatesJob( collections, this );
4713  job->setProperty( "ProgressItem", QVariant::fromValue ( item ) );
4714  item->setProperty( "RemoveDuplicatesJob", QVariant::fromValue( qobject_cast<Akonadi::Job*>( job ) ) );
4715  connect( job, SIGNAL(finished(KJob*)), this, SLOT(slotRemoveDuplicatesDone(KJob*)) );
4716  connect( job, SIGNAL(description(KJob*,QString,QPair<QString,QString>,QPair<QString,QString>)), this, SLOT(slotRemoveDuplicatesUpdate(KJob*,QString)) );
4717  connect( item, SIGNAL(progressItemCanceled(KPIM::ProgressItem*)), this, SLOT(slotRemoveDuplicatesCanceled(KPIM::ProgressItem*)) );
4718 }
4719 
4720 void KMMainWidget::slotRemoveDuplicatesDone( KJob *job )
4721 {
4722  if ( job->error() && job->error() != KJob::KilledJobError ) {
4723  KMessageBox::error( this, job->errorText(), i18n( "Error while removing duplicates" ) );
4724  }
4725 
4726  KPIM::ProgressItem *item = job->property( "ProgressItem" ).value<KPIM::ProgressItem*>();
4727  if ( item ) {
4728  item->setComplete();
4729  item->setStatus( i18n( "Done" ) );
4730  item = 0;
4731  }
4732 }
4733 
4734 void KMMainWidget::slotRemoveDuplicatesCanceled( KPIM::ProgressItem *item )
4735 {
4736  Akonadi::Job *job = item->property( "RemoveDuplicatesJob" ).value<Akonadi::Job*>();
4737  if ( job ) {
4738  job->kill( KJob::Quietly );
4739  }
4740 
4741  item->setComplete();
4742  item = 0;
4743 }
4744 
4745 void KMMainWidget::slotRemoveDuplicatesUpdate( KJob* job, const QString& description )
4746 {
4747  KPIM::ProgressItem *item = job->property( "ProgressItem" ).value<KPIM::ProgressItem*>();
4748  if ( item ) {
4749  item->setStatus( description );
4750  }
4751 }
4752 
4753 
4754 void KMMainWidget::slotServerSideSubscription()
4755 {
4756  if ( !mCurrentFolder )
4757  return;
4758  bool isImapOnline = false;
4759  if ( kmkernel->isImapFolder( mCurrentFolder->collection(), isImapOnline ) ) {
4760  QDBusInterface iface(
4761  QLatin1String( "org.freedesktop.Akonadi.Resource.")+mCurrentFolder->collection().resource(),
4762  QLatin1String( "/" ), QLatin1String( "org.kde.Akonadi.Imap.Resource" ),
4763  DBusConnectionPool::threadConnection(), this );
4764  if ( !iface.isValid() ) {
4765  kDebug()<<"Cannot create imap dbus interface";
4766  return;
4767  }
4768  QDBusPendingCall call = iface.asyncCall( QLatin1String( "configureSubscription" ), (qlonglong)winId() );
4769  QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
4770  connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(slotConfigureSubscriptionFinished(QDBusPendingCallWatcher*)));
4771  }
4772 }
4773 
4774 void KMMainWidget::slotConfigureSubscriptionFinished(QDBusPendingCallWatcher* watcher)
4775 {
4776  QDBusPendingReply<int> reply = *watcher;
4777  if ( !reply.isValid() ) {
4778  return;
4779  }
4780  if (reply == -2 ){
4781  KMessageBox::error(this,i18n("IMAP server not configured yet. Please configure the server in the IMAP account before setting up server-side subscription."));
4782  } else if (reply == -1) {
4783  KMessageBox::error(this,i18n("Log in failed, please configure the IMAP account before setting up server-side subscription."));
4784  }
4785  watcher->deleteLater();
4786 }
4787 
4788 void KMMainWidget::savePaneSelection()
4789 {
4790  if (mMessagePane) {
4791  mMessagePane->saveCurrentSelection();
4792  }
4793 }
4794 
4795 void KMMainWidget::slotConfigureAutomaticArchiving()
4796 {
4797  OrgFreedesktopAkonadiArchiveMailAgentInterface archiveMailInterface(QLatin1String("org.freedesktop.Akonadi.ArchiveMailAgent"), QLatin1String("/ArchiveMailAgent"),QDBusConnection::sessionBus(), this);
4798  if (archiveMailInterface.isValid()) {
4799  archiveMailInterface.showConfigureDialog( (qlonglong)winId() );
4800  } else {
4801  KMessageBox::error(this,i18n("Archive Mail Agent was not registered."));
4802  }
4803 }
4804 
4805 void KMMainWidget::slotConfigureSendLater()
4806 {
4807  OrgFreedesktopAkonadiSendLaterAgentInterface sendLaterInterface(QLatin1String("org.freedesktop.Akonadi.SendLaterAgent"), QLatin1String("/SendLaterAgent"),QDBusConnection::sessionBus(), this);
4808  if (sendLaterInterface.isValid()) {
4809  sendLaterInterface.showConfigureDialog( (qlonglong)winId() );
4810  } else {
4811  KMessageBox::error(this,i18n("Send Later Agent was not registered."));
4812  }
4813 }
4814 
4815 void KMMainWidget::slotConfigureFolderArchiving()
4816 {
4817  OrgFreedesktopAkonadiFolderArchiveAgentInterface folderArchiveInterface(QLatin1String("org.freedesktop.Akonadi.FolderArchiveAgent"), QLatin1String("/FolderArchiveAgent"),QDBusConnection::sessionBus(), this);
4818  if (folderArchiveInterface.isValid()) {
4819  folderArchiveInterface.showConfigureDialog( (qlonglong)winId() );
4820  } else {
4821  KMessageBox::error(this,i18n("Archive Folder Agent was not registered."));
4822  }
4823 }
4824 
4825 void KMMainWidget::updatePaneTagComboBox()
4826 {
4827  if (mMessagePane) {
4828  mMessagePane->updateTagComboBox();
4829  }
4830 }
4831 
4832 
4833 void KMMainWidget::slotExportData()
4834 {
4835  const QString path = KStandardDirs::findExe( QLatin1String("pimsettingexporter" ) );
4836  if ( !QProcess::startDetached( path ) )
4837  KMessageBox::error( this, i18n( "Could not start \"PIM Setting Exporter\" program. "
4838  "Please check your installation." ),
4839  i18n( "Unable to start \"PIM Setting Exporter\" program" ) );
4840 }
4841 
4842 void KMMainWidget::slotCreateAddressBookContact()
4843 {
4844  CreateNewContactJob *job = new CreateNewContactJob( this, this );
4845  job->start();
4846 }
4847 
4848 void KMMainWidget::slotOpenRecentMsg(const KUrl& url)
4849 {
4850  KMOpenMsgCommand *openCommand = new KMOpenMsgCommand( this, url, overrideEncoding(), this );
4851  openCommand->start();
4852 }
4853 
4854 void KMMainWidget::addRecentFile(const KUrl& mUrl)
4855 {
4856  mOpenRecentAction->addUrl(mUrl);
4857  KConfigGroup grp = mConfig->group(QLatin1String("Recent Files"));
4858  mOpenRecentAction->saveEntries(grp);
4859  grp.sync();
4860 }
4861 
4862 void KMMainWidget::slotMoveMessageToTrash()
4863 {
4864  if (messageView() && messageView()->viewer()) {
4865  KMTrashMsgCommand *command = new KMTrashMsgCommand( mCurrentFolder->collection(), messageView()->viewer()->messageItem(), -1 );
4866  command->start();
4867  }
4868 }
4869 
4870 void KMMainWidget::slotArchiveMails()
4871 {
4872  OrgFreedesktopAkonadiFolderArchiveAgentInterface folderArchiveInterface(QLatin1String("org.freedesktop.Akonadi.FolderArchiveAgent"), QLatin1String("/FolderArchiveAgent"),QDBusConnection::sessionBus(), this);
4873  if (folderArchiveInterface.isValid()) {
4874  const QList<Akonadi::Item::Id> selectedMessages = mMessagePane->selectionAsListMessageId();
4875  if (mCurrentFolder) {
4876  folderArchiveInterface.archiveItems(selectedMessages, mCurrentFolder->collection().resource());
4877  }
4878  } else {
4879  KMessageBox::error(this,i18n("Archive Folder Agent was not registered."));
4880  }
4881 }
KMMainWidget::readPreConfig
void readPreConfig()
Read configuration options before widgets are created.
Definition: kmmainwidget.cpp:544
KMMainWidget::slotConfigChanged
void slotConfigChanged()
Definition: kmmainwidget.cpp:2390
KMReplyCommand
Definition: kmcommands.h:312
KMMainWidget::slotUpdateUndo
void slotUpdateUndo()
Update the undo action.
Definition: kmmainwidget.cpp:4256
KMMainWidget::slotSendQueuedVia
void slotSendQueuedVia(QAction *item)
Definition: kmmainwidget.cpp:2477
KMMainWidget::slotCreateAddressBookContact
void slotCreateAddressBookContact()
Definition: kmmainwidget.cpp:4842
globalsettings.h
KPIM::ProgressManager::instance
static ProgressManager * instance()
KMMainWidget::slotCollectionChanged
void slotCollectionChanged(const Akonadi::Collection &, const QSet< QByteArray > &)
Definition: kmmainwidget.cpp:1195
KMMainWidget::slotConfigureAutomaticArchiving
void slotConfigureAutomaticArchiving()
Definition: kmmainwidget.cpp:4795
KMMainWidget::vacationScriptIndicator
QLabel * vacationScriptIndicator() const
Definition: kmmainwidget.cpp:4457
KMMainWidget::slotSetThreadStatusUnread
void slotSetThreadStatusUnread()
Definition: kmmainwidget.cpp:2124
KMMainWidget::slotDelayedRemoveFolder
void slotDelayedRemoveFolder(KJob *)
Definition: kmmainwidget.cpp:1601
collectionshortcutpage.h
QSharedPointer
Definition: collectionmailinglistpage.h:34
antispamwizard.h
KPIM::ProgressManager::createProgressItem
static ProgressItem * createProgressItem(const QString &label)
KMReaderMainWin::showMessage
void showMessage(const QString &encoding, const Akonadi::Item &msg, const Akonadi::Collection &parentCollection=Akonadi::Collection())
take ownership of and show
Definition: kmreadermainwin.cpp:137
KMMainWidget::slotItemAdded
void slotItemAdded(const Akonadi::Item &, const Akonadi::Collection &col)
Definition: kmmainwidget.cpp:1220
KMail::Util::mailingListPost
bool mailingListPost(const QSharedPointer< MailCommon::FolderCollection > &fd)
Definition: util.cpp:165
KMMainWidget::slotRemoveDuplicatesCanceled
void slotRemoveDuplicatesCanceled(KPIM::ProgressItem *)
Definition: kmmainwidget.cpp:4734
KMMainWidget::slotToFilter
void slotToFilter()
Definition: kmmainwidget.cpp:2264
KMMainWidget::slotConfigureSendLater
void slotConfigureSendLater()
Definition: kmmainwidget.cpp:4805
KMMainWidget::slotFilterLogViewer
void slotFilterLogViewer()
Definition: kmmainwidget.cpp:4370
KMMainWidget::slotManageSieveScripts
void slotManageSieveScripts()
Definition: kmmainwidget.cpp:1303
KXMLGUIClient
KMMainWidget::akonadiStandardAction
KAction * akonadiStandardAction(Akonadi::StandardActionManager::Type type)
Definition: kmmainwidget.cpp:4554
KMMainWidget::slotExpandAllThreads
void slotExpandAllThreads()
Definition: kmmainwidget.cpp:3780
KMMainWidget::slotSetThreadStatusWatched
void slotSetThreadStatusWatched()
Definition: kmmainwidget.cpp:2144
KMReaderWin
This class implements a "reader window", that is a window used for reading or viewing messages...
Definition: kmreaderwin.h:50
KMMainWidget::slotFolderMailingListProperties
void slotFolderMailingListProperties()
Definition: kmmainwidget.cpp:1484
KMTrashMsgCommand
Definition: kmcommands.h:540
KMail::KMKnotify
Definition: kmknotify.h:37
KMMainWidget::slotUseTemplate
void slotUseTemplate()
Definition: kmmainwidget.cpp:1797
KMMainWidget::slotDelayedShowNewFromTemplate
void slotDelayedShowNewFromTemplate(KJob *)
Definition: kmmainwidget.cpp:1421
KMMainWidget::slotReplaceMsgByUnencryptedVersion
void slotReplaceMsgByUnencryptedVersion()
Definition: kmmainwidget.cpp:2511
KMMainWidget::slotSetThreadStatusImportant
void slotSetThreadStatusImportant()
Definition: kmmainwidget.cpp:2129
text
virtual QByteArray text(quint32 serialNumber) const =0
KMMainWidget::layoutSplitters
void layoutSplitters()
Definition: kmmainwidget.cpp:585
KMMainWidget::slotCheckMail
void slotCheckMail()
Definition: kmmainwidget.cpp:1330
email
const QString email
Definition: identitydialog.cpp:611
tagactionmanager.h
KMMainWidget::slotFromFilter
void slotFromFilter()
Definition: kmmainwidget.cpp:2250
KMMainWidget::slotCheckOneAccount
void slotCheckOneAccount(QAction *)
Definition: kmmainwidget.cpp:1342
KMUseTemplateCommand
Definition: kmcommands.h:244
KMSetTagCommand
This command is used to set or toggle a tag for a list of messages.
Definition: kmcommands.h:429
KMail::Util::launchAccountWizard
void launchAccountWizard(QWidget *)
Definition: util.cpp:89
QWidget
KMail::MessageActions
Manages common actions that can be performed on one or more messages.
Definition: messageactions.h:59
KMMainWidget::slotMessagePopup
void slotMessagePopup(const Akonadi::Item &, const KUrl &, const KUrl &imageUrl, const QPoint &)
Definition: kmmainwidget.cpp:2773
KMMainWidget::~KMMainWidget
virtual ~KMMainWidget()
Definition: kmmainwidget.cpp:375
KMMainWidget::slotUpdateMessageTagList
void slotUpdateMessageTagList(const QString &aLabel)
Adds if not existing/removes if existing the tag identified by aLabel in all selected messages...
Definition: kmmainwidget.cpp:2088
collectionmailinglistpage.h
KMMainWidget::slotMessageSelected
void slotMessageSelected(const Akonadi::Item &)
Opens mail in the internal viewer.
Definition: kmmainwidget.cpp:4462
KMMainWidget::slotOverrideHtmlLoadExt
void slotOverrideHtmlLoadExt()
Definition: kmmainwidget.cpp:1725
KMMainWidget::slotSetThreadStatusToAct
void slotSetThreadStatusToAct()
Definition: kmmainwidget.cpp:2139
KMMainWidget::slotCompose
void slotCompose()
Definition: kmmainwidget.cpp:1360
KMMainWidget::slotFocusQuickSearch
void slotFocusQuickSearch()
Definition: kmmainwidget.cpp:1246
KMMoveCommand
Definition: kmcommands.h:511
KMMainWidget::slotMessageActivated
void slotMessageActivated(const Akonadi::Item &)
Open a separate viewer window containing the specified message.
Definition: kmmainwidget.cpp:2698
kmknotify.h
KMMainWidget::slotCustomReplyAllToMsg
void slotCustomReplyAllToMsg(const QString &tmpl)
Definition: kmmainwidget.cpp:2191
KMMainWidget::slotFilter
void slotFilter()
Definition: kmmainwidget.cpp:1298
KMMainWidget::writeReaderConfig
void writeReaderConfig()
Definition: kmmainwidget.cpp:921
KMMainWidget::slotAddrBook
void slotAddrBook()
Definition: kmmainwidget.cpp:1317
KMMainWidget::refreshMessageListSelection
void refreshMessageListSelection()
Definition: kmmainwidget.cpp:2097
KMMainWidget::slotEmptyFolder
void slotEmptyFolder()
Definition: kmmainwidget.cpp:1537
kmmainwin.h
undostack.h
KMMainWidget::copySelectedMessagesToFolder
void copySelectedMessagesToFolder(const Akonadi::Collection &dest)
Definition: kmmainwidget.cpp:1993
KMMainWidget::currentFolder
QSharedPointer< MailCommon::FolderCollection > currentFolder() const
Definition: kmmainwidget.cpp:4394
KMMainWidget::slotExpireFolder
void slotExpireFolder()
Definition: kmmainwidget.cpp:1496
KMMainWidget::slotShowStartupFolder
void slotShowStartupFolder()
Definition: kmmainwidget.cpp:4205
from
QString from() const
KMMainWidget::slotSelectMoreMessageTagList
void slotSelectMoreMessageTagList()
Definition: kmmainwidget.cpp:2072
KMMainWidget::slotShowNewFromTemplate
void slotShowNewFromTemplate()
Definition: kmmainwidget.cpp:1398
KMMainWidget::slotDeleteThread
void slotDeleteThread(bool confirmDelete=true)
Definition: kmmainwidget.cpp:1898
collectionmaintenancepage.h
KMMainWidget::slotDebugSieve
void slotDebugSieve()
Definition: kmmainwidget.cpp:2357
KMail::Composer
Definition: composer.h:37
KMMainWidget::destruct
void destruct()
Definition: kmmainwidget.cpp:385
KMKernel::self
static KMKernel * self()
normal control stuff
Definition: kmkernel.cpp:1451
vacationmanager.h
searchwindow.h
KMCommand::result
Result result() const
Returns the result of the command.
Definition: kmcommands.cpp:207
KMMoveCommand::destFolder
Akonadi::Collection destFolder() const
Definition: kmcommands.h:518
KMMainWidget::slotOverrideHtml
void slotOverrideHtml()
Definition: kmmainwidget.cpp:1696
KMMainWidget::slotExportData
void slotExportData()
Definition: kmmainwidget.cpp:4833
KMKernel::config
KSharedConfig::Ptr config()
Definition: kmkernel.cpp:1456
KMail::TagActionManager
Creates actions related to the existing Nepomuk tags and plugs them into the GUI. ...
Definition: tagactionmanager.h:66
KMMainWidget::deleteWidgets
void deleteWidgets()
Definition: kmmainwidget.cpp:931
KMMainWidget::slotExtendSelectionToPreviousMessage
void slotExtendSelectionToPreviousMessage()
Definition: kmmainwidget.cpp:2659
KMMainWidget::updateFileMenu
void updateFileMenu()
Definition: kmmainwidget.cpp:4376
KMMainWidget::slotAntiSpamWizard
void slotAntiSpamWizard()
Definition: kmmainwidget.cpp:4342
KMSetTagCommand::Toggle
Definition: kmcommands.h:434
createnewcontactjob.h
KMMainWidget::showEvent
virtual void showEvent(QShowEvent *event)
Definition: kmmainwidget.cpp:4408
KMMainWidget::slotJumpToFolder
void slotJumpToFolder()
Definition: kmmainwidget.cpp:2282
TagSelectDialog
Definition: tagselectdialog.h:37
KMMainWidget::slotFocusOnPrevMessage
void slotFocusOnPrevMessage()
Definition: kmmainwidget.cpp:2583
KMMetaFilterActionCommand
Definition: kmcommands.h:464
KMSaveAttachmentsCommand
Definition: kmcommands.h:292
KMMainWidget::slotUpdateOnlineStatus
void slotUpdateOnlineStatus(GlobalSettings::EnumNetworkState::type)
Definition: kmmainwidget.cpp:2452
KMail::StatusBarLabel
Slightly extended QLabel for embedding into the status bar, providing mouse click signals and support...
Definition: statusbarlabel.h:31
KMMainWidget::startUpdateMessageActionsTimer
void startUpdateMessageActionsTimer()
Start a timer to update message actions.
Definition: kmmainwidget.cpp:3804
statusbarlabel.h
tagselectdialog.h
KMMainWidget::slotSubjectFilter
void slotSubjectFilter()
Definition: kmmainwidget.cpp:2240
KMMainWidget::slotMessageStatusChangeRequest
void slotMessageStatusChangeRequest(const Akonadi::Item &, const Akonadi::MessageStatus &, const Akonadi::MessageStatus &)
Definition: kmmainwidget.cpp:2748
KMMainWidget::readConfig
void readConfig()
Read configuration options after widgets are created.
Definition: kmmainwidget.cpp:790
KMMainWidget::slotStartCheckMail
void slotStartCheckMail()
Definition: kmmainwidget.cpp:408
KMCommand
Small helper structure which encapsulates the KMMessage created when creating a reply, and.
Definition: kmcommands.h:44
KMMainWidget::slotShowSelectedFolderInPane
void slotShowSelectedFolderInPane()
Definition: kmmainwidget.cpp:528
KPIM::ProgressManager
KMMainWidget::slotArchiveFolder
void slotArchiveFolder()
Definition: kmmainwidget.cpp:1578
KMMainWidget::updateFolderMenu
void updateFolderMenu()
Update html and threaded messages preferences in Folder menu.
Definition: kmmainwidget.cpp:4123
KMMainWidget::slotCheckMailOnStartup
void slotCheckMailOnStartup()
Definition: kmmainwidget.cpp:1336
KMMainWidget::slotSelectNextMessage
void slotSelectNextMessage()
Message navigation.
Definition: kmmainwidget.cpp:2603
KMMainWidget::slotSelectPreviousUnreadMessage
void slotSelectPreviousUnreadMessage()
Definition: kmmainwidget.cpp:2669
KPIM::ProgressItem::setComplete
void setComplete()
KMMainWidget::slotAkonadiStandardActionUpdated
void slotAkonadiStandardActionUpdated()
Definition: kmmainwidget.cpp:4011
KMMainWidget::slotAccountWizard
void slotAccountWizard()
Definition: kmmainwidget.cpp:4355
KMMainWidget::moveSelectedMessagesToFolder
void moveSelectedMessagesToFolder(const Akonadi::Collection &dest)
Definition: kmmainwidget.cpp:1940
KMMoveCommand::refSet
MessageList::Core::MessageItemSetReference refSet() const
Definition: kmcommands.h:520
KMMainWidget::slotDeleteMsg
void slotDeleteMsg(bool confirmDelete=true)
Definition: kmmainwidget.cpp:1890
KMMainWidget::slotShowBusySplash
void slotShowBusySplash()
Show a splash screen for the longer-lasting operation.
Definition: kmmainwidget.cpp:2488
KMMainWidget::getTransportMenu
void getTransportMenu()
Definition: kmmainwidget.cpp:2970
KMMainWidget::slotItemMoved
void slotItemMoved(const Akonadi::Item &item, const Akonadi::Collection &from, const Akonadi::Collection &to)
Definition: kmmainwidget.cpp:1237
KMMainWidget::slotCreateNewTab
void slotCreateNewTab(bool)
Definition: kmmainwidget.cpp:1190
KMMainWidget::slotItemsFetchedForActivation
void slotItemsFetchedForActivation(const Akonadi::Item::List &list)
Definition: kmmainwidget.cpp:2723
KMMainWidget::slotSendQueued
void slotSendQueued()
Definition: kmmainwidget.cpp:2469
KMMainWidget::updatePaneTagComboBox
void updatePaneTagComboBox()
Definition: kmmainwidget.cpp:4825
KMMainWidget::slotImportWizard
void slotImportWizard()
Definition: kmmainwidget.cpp:4360
KMail::AntiSpamWizard
KMail anti-spam wizard.
Definition: antispamwizard.h:105
progressmanager.h
collectionpane.h
KMCommand::start
void start()
Definition: kmcommands.cpp:234
KMMainWidget::slotTrashThread
void slotTrashThread()
Definition: kmmainwidget.cpp:2051
to
QString to() const
KMail::ArchiveFolderDialog
Definition: archivefolderdialog.h:41
KMMainWidget::slotRedirectMsg
void slotRedirectMsg()
Definition: kmmainwidget.cpp:2159
KMMainWidget::slotStartCertManager
void slotStartCertManager()
Definition: kmmainwidget.cpp:2370
kmsystemtray.h
collectionviewpage.h
KMMainWidget::savePaneSelection
void savePaneSelection()
Definition: kmmainwidget.cpp:4788
KMMainWidget::slotCollectionProperties
void slotCollectionProperties()
Definition: kmmainwidget.cpp:4564
KMMainWidget::slotEndCheckMail
void slotEndCheckMail()
Definition: kmmainwidget.cpp:414
KMMainWidget
Definition: kmmainwidget.h:83
KMMainWidget::newFromTemplate
void newFromTemplate(const Akonadi::Item &)
Definition: kmmainwidget.cpp:1463
KMMainWidget::slotApplyFilters
void slotApplyFilters()
Definition: kmmainwidget.cpp:2302
KMMainWidget::slotPrevUnreadFolder
void slotPrevUnreadFolder()
Definition: kmmainwidget.cpp:3761
KMMainWidget::slotItemRemoved
void slotItemRemoved(const Akonadi::Item &)
Definition: kmmainwidget.cpp:1230
KMMainWidget::slotAddFavoriteFolder
void slotAddFavoriteFolder()
Definition: kmmainwidget.cpp:3714
KMMainWidget::slotSelectPreviousMessage
void slotSelectPreviousMessage()
Definition: kmmainwidget.cpp:2652
KMMainWidget::slotExtendSelectionToNextMessage
void slotExtendSelectionToNextMessage()
Definition: kmmainwidget.cpp:2610
KMMainWidget::slotRemoveFolder
void slotRemoveFolder()
Definition: kmmainwidget.cpp:1588
KMMainWidget::showResourceOfflinePage
void showResourceOfflinePage()
Definition: kmmainwidget.cpp:2502
util.h
KMail::ArchiveFolderDialog::setFolder
void setFolder(const Akonadi::Collection &defaultCollection)
Definition: archivefolderdialog.cpp:162
KMMainWidget::slotMoveSelectedMessageToFolder
void slotMoveSelectedMessageToFolder()
This will ask for a destination folder and move the currently selected messages (in MessageListView) ...
Definition: kmmainwidget.cpp:1928
KMMainWidget::slotRemoveDuplicatesDone
void slotRemoveDuplicatesDone(KJob *)
Definition: kmmainwidget.cpp:4720
kmkernel
#define kmkernel
Definition: kmkernel.h:22
KMMainWidget::slotExpandThread
void slotExpandThread()
Definition: kmmainwidget.cpp:3770
KMMainWidget::slotSaveAttachments
void slotSaveAttachments()
Definition: kmmainwidget.cpp:2416
collectionquotapage.h
KMCommand::OK
Definition: kmcommands.h:49
KMMainWidget::mainWidgetList
static const PtrList * mainWidgetList()
Returns a list of all KMMainWidgets.
Definition: kmmainwidget.cpp:4384
KMMainWidget::initializeFilterActions
void initializeFilterActions()
Definition: kmmainwidget.cpp:4286
KMMainWidget::slotConfigureFolderArchiving
void slotConfigureFolderArchiving()
Definition: kmmainwidget.cpp:4815
KMForwardAttachedCommand
Definition: kmcommands.h:348
KMOpenMsgCommand
Definition: kmcommands.h:267
KMMainWidget::slotTrashSelectedMessages
void slotTrashSelectedMessages()
Implements the "move to trash" action.
Definition: kmmainwidget.cpp:2043
KMMainWidget::slotSelectFocusedMessage
void slotSelectFocusedMessage()
Definition: kmmainwidget.cpp:2598
KMMainWidget::slotForwardInlineMsg
void slotForwardInlineMsg()
Definition: kmmainwidget.cpp:1761
CreateNewContactJob
The CreateNewContactJob class The job will check if there is address book folder to store new contact...
Definition: createnewcontactjob.h:32
KMMainWidget::slotSelectCollectionFolder
void slotSelectCollectionFolder(const Akonadi::Collection &col)
Definition: kmmainwidget.cpp:2294
KMMainWidget::slotPostToML
void slotPostToML()
Definition: kmmainwidget.cpp:1473
KMSetTagCommand::CleanExistingAndAddNew
Definition: kmcommands.h:434
KMMainWidget::readFolderConfig
void readFolderConfig()
Read configuration for current folder.
Definition: kmmainwidget.cpp:559
archivefolderdialog.h
KMMainWidget::slotOpenMsg
void slotOpenMsg()
Definition: kmmainwidget.cpp:2408
KMReaderWin::newFeaturesMD5
static QString newFeaturesMD5()
Returns the MD5 hash for the list of new features.
Definition: kmreaderwin.cpp:313
KMMainWidget::writeConfig
void writeConfig(bool force=true)
Write configuration options.
Definition: kmmainwidget.cpp:864
KMForwardCommand
Definition: kmcommands.h:329
set
void set(quint32, const QString &, const QString &, const QString &, const QString &, time_t)
KMMainWidget::slotSaveMsg
void slotSaveMsg()
Definition: kmmainwidget.cpp:2398
KPIM::ProgressItem::setUsesBusyIndicator
void setUsesBusyIndicator(bool useBusyIndicator)
KMMainWidget::actionCollections
QList< KActionCollection * > actionCollections() const
Convenience function to get the action collection in a list.
Definition: kmmainwidget.cpp:4251
GlobalSettings::self
static GlobalSettings * self()
Definition: globalsettings.cpp:30
KMMainWidget::slotForwardAttachedMsg
void slotForwardAttachedMsg()
Definition: kmmainwidget.cpp:1779
KMMainWidget::slotShowFolderShortcutDialog
void slotShowFolderShortcutDialog()
Definition: kmmainwidget.cpp:1490
KMMainWidget::showOfflinePage
void showOfflinePage()
Show a message screen explaining that we are currently offline, when an online folder is selected...
Definition: kmmainwidget.cpp:2495
KMMainWidget::slotSetThreadStatusIgnored
void slotSetThreadStatusIgnored()
Definition: kmmainwidget.cpp:2151
KMMainWidget::updateMessageActions
void updateMessageActions(bool fast=false)
Update message actions.
Definition: kmmainwidget.cpp:3814
KPIM::BroadcastStatus
KMMainWidget::slotReadOn
void slotReadOn()
Definition: kmmainwidget.cpp:3741
KMMainWidget::slotResendMsg
void slotResendMsg()
Definition: kmmainwidget.cpp:1804
KMMainWidget::slotCollapseAllThreads
void slotCollapseAllThreads()
Definition: kmmainwidget.cpp:3789
KMMainWidget::slotCheckVacation
void slotCheckVacation()
Definition: kmmainwidget.cpp:2336
KMMainWidget::slotAntiVirusWizard
void slotAntiVirusWizard()
Definition: kmmainwidget.cpp:4349
KMMainWidget::slotHelp
void slotHelp()
Definition: kmmainwidget.cpp:1291
KMMainWidget::slotOnlineStatus
void slotOnlineStatus()
Definition: kmmainwidget.cpp:2439
KMMainWidget::slotShowTip
void slotShowTip()
Show tip-of-the-day, forced.
Definition: kmmainwidget.cpp:4246
KMMainWidget::slotContactSearchJobForMessagePopupDone
void slotContactSearchJobForMessagePopupDone(KJob *job)
Definition: kmmainwidget.cpp:2792
KMSetStatusCommand
Definition: kmcommands.h:408
KMMainWidget::slotUpdateActionsAfterMailChecking
void slotUpdateActionsAfterMailChecking()
Definition: kmmainwidget.cpp:420
KMMainWidget::slotShowExpiryProperties
void slotShowExpiryProperties()
Definition: kmmainwidget.cpp:3735
foldershortcutactionmanager.h
composer.h
KMMainWidget::slotCopySelectedMessagesToFolder
void slotCopySelectedMessagesToFolder()
This will ask for a destination folder and copy the currently selected messages (in MessageListView) ...
Definition: kmmainwidget.cpp:1980
KMMainWidget::clearViewer
void clearViewer()
Definition: kmmainwidget.cpp:535
QLabel
KMMainWidget::folderSelected
void folderSelected(const Akonadi::Collection &col)
Select the given folder If the folder is 0 the intro is shown.
Definition: kmmainwidget.cpp:459
KPIM::ProgressItem
KMMainWidget::slotMessageQueuedOrDrafted
void slotMessageQueuedOrDrafted()
Definition: kmmainwidget.cpp:1751
KMMainWidget::clearFilterActions
void clearFilterActions()
Clear and create actions for marked filters.
Definition: kmmainwidget.cpp:4264
KMReaderMainWin
Definition: kmreadermainwin.h:32
KMail::VacationManager
Definition: vacationmanager.h:29
KMMainWidget::restoreCollectionFolderViewConfig
void restoreCollectionFolderViewConfig(Akonadi::Collection::Id id=-1)
Definition: kmmainwidget.cpp:351
KMMainWidget::updateVacationScriptStatus
void updateVacationScriptStatus()
Definition: kmmainwidget.h:138
KMail::FolderShortcutActionManager
Definition: foldershortcutactionmanager.h:61
KMCommand::Failed
Definition: kmcommands.h:49
KMMainWidget::slotSetThreadStatusRead
void slotSetThreadStatusRead()
Definition: kmmainwidget.cpp:2134
KMMainWidget::updateMessageActionsDelayed
void updateMessageActionsDelayed()
Definition: kmmainwidget.cpp:3834
KMail::Composer::setFocusToEditor
virtual void setFocusToEditor()=0
Sets the focus to the edit-widget and the cursor below the "On ... you wrote" line when hasMessage is...
KMMainWidget::slotCustomReplyToMsg
void slotCustomReplyToMsg(const QString &tmpl)
Slot to reply to a message.
Definition: kmmainwidget.cpp:2171
CollectionPane
Definition: collectionpane.h:25
KMMainWidget::slotFocusOnNextMessage
void slotFocusOnNextMessage()
Definition: kmmainwidget.cpp:2578
KMMainWidget::slotSelectLastMessage
void slotSelectLastMessage()
Definition: kmmainwidget.cpp:2593
KMMainWidget::slotUndo
void slotUndo()
Definition: kmmainwidget.cpp:2273
KMMainWidget::slotCollapseThread
void slotCollapseThread()
Definition: kmmainwidget.cpp:3775
KMMainWidget::slotSearch
bool slotSearch()
Definition: kmmainwidget.cpp:1252
KMMainWidget::addRecentFile
void addRecentFile(const KUrl &mUrl)
Definition: kmmainwidget.cpp:4854
KMMainWidget::slotApplyFiltersOnFolder
void slotApplyFiltersOnFolder()
Definition: kmmainwidget.cpp:2310
KMail::Composer::New
Definition: composer.h:44
kmreadermainwin.h
CreateNewContactJob::start
void start()
start the job
Definition: createnewcontactjob.cpp:49
KMReaderMainWin::setUseFixedFont
void setUseFixedFont(bool useFixedFont)
Definition: kmreadermainwin.cpp:132
kmcommands.h
KMMainWidget::slotRemoveDuplicatesUpdate
void slotRemoveDuplicatesUpdate(KJob *, const QString &)
Definition: kmmainwidget.cpp:4745
KMMainWidget::slotDisplayCurrentMessage
void slotDisplayCurrentMessage()
etc.
Definition: kmmainwidget.cpp:2691
collectiontemplatespage.h
KMMainWidget::createWidgets
void createWidgets()
Definition: kmmainwidget.cpp:950
KMail::Composer::setCollectionForNewMessage
virtual void setCollectionForNewMessage(const Akonadi::Collection &folder)=0
KMMainWidget::slotMarkAll
void slotMarkAll()
Definition: kmmainwidget.cpp:2767
KMMainWidget::slotEditNotifications
void slotEditNotifications()
Settings menu.
Definition: kmmainwidget.cpp:3729
KMSaveMsgCommand
Definition: kmcommands.h:255
KMMainWidget::slotImport
void slotImport()
Definition: kmmainwidget.cpp:1324
KMMainWidget::writeFolderConfig
void writeFolderConfig()
Write configuration for current folder.
Definition: kmmainwidget.cpp:574
KMResendMessageCommand
Definition: kmcommands.h:553
broadcaststatus.h
KMMainWidget::slotSelectFirstMessage
void slotSelectFirstMessage()
Definition: kmmainwidget.cpp:2588
KMMainWidget::setupActions
void setupActions()
Definition: kmmainwidget.cpp:2984
KMRedirectCommand
Definition: kmcommands.h:365
KMMainWidget::slotCustomForwardMsg
void slotCustomForwardMsg(const QString &tmpl)
Definition: kmmainwidget.cpp:2214
KMMainWidget::slotOpenRecentMsg
void slotOpenRecentMsg(const KUrl &url)
Definition: kmmainwidget.cpp:4848
KJob
KMMainWidget::slotExpireAll
void slotExpireAll()
Definition: kmmainwidget.cpp:1680
KMMainWidget::slotCollectionStatisticsChanged
void slotCollectionStatisticsChanged(const Akonadi::Collection::Id, const Akonadi::CollectionStatistics &)
Definition: kmmainwidget.cpp:1177
KMMainWidget::slotStartWatchGnuPG
void slotStartWatchGnuPG()
Definition: kmmainwidget.cpp:2381
KMail::SearchWindow::activateFolder
void activateFolder(const Akonadi::Collection &folder)
Changes the base folder for search operations to a different folder.
Definition: searchwindow.cpp:388
KMMainWidget::slotEditVacation
void slotEditVacation()
Trigger the dialog for editing out-of-office scripts.
Definition: kmmainwidget.cpp:2347
KMMainWidget::slotNewFromTemplate
void slotNewFromTemplate(QAction *)
Definition: kmmainwidget.cpp:1452
KMMainWidget::updateMessageMenu
void updateMessageMenu()
Update message menu.
Definition: kmmainwidget.cpp:3799
KMCopyCommand
Definition: kmcommands.h:492
KMMainWidget::getAccountMenu
void getAccountMenu()
Definition: kmmainwidget.cpp:2956
KMail::SearchWindow
Definition: searchwindow.h:65
KMMainWidget::slotSelectNextUnreadMessage
void slotSelectNextUnreadMessage()
Definition: kmmainwidget.cpp:2620
KPIM::ProgressItem::setStatus
void setStatus(const QString &v)
QList
KMMainWidget::slotRemoveDuplicates
void slotRemoveDuplicates()
Definition: kmmainwidget.cpp:4696
KMMainWidget::slotNextUnreadFolder
void slotNextUnreadFolder()
Definition: kmmainwidget.cpp:3752
KMMainWidget::slotIntro
void slotIntro()
Definition: kmmainwidget.cpp:4190
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