fix Messages.sh after yesterday change in extract-messages.sh
[kdepim.git] / kmail / kmreadermainwin.cpp
blob3e26d034b87ca454dbe729c0e088ce1cfe458501
1 /*
2 This file is part of KMail, the KDE mail client.
3 Copyright (c) 2002 Don Sanders <sanders@kde.org>
5 KMail is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License, version 2, as
7 published by the Free Software Foundation.
9 KMail is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 // A toplevel KMainWindow derived class for displaying
20 // single messages or single message parts.
22 // Could be extended to include support for normal main window
23 // widgets like a toolbar.
25 #include "kmreadermainwin.h"
26 #include "kmreaderwin.h"
28 #include <kicon.h>
29 #include <kactionmenu.h>
30 #include <kedittoolbar.h>
31 #include <klocale.h>
32 #include <kstandardshortcut.h>
33 #include <kwindowsystem.h>
34 #include <kaction.h>
35 #include <kfontaction.h>
36 #include <kiconloader.h>
37 #include <kstandardaction.h>
38 #include <ktoggleaction.h>
39 #include <ktoolbar.h>
40 #include <kdebug.h>
41 #include <KFontAction>
42 #include <KFontSizeAction>
43 #include <kstatusbar.h>
44 #include <kwebview.h>
45 #include "kmcommands.h"
46 #include "kmenubar.h"
47 #include "kmenu.h"
48 #include "kmmainwidget.h"
49 #include "messageviewer/csshelper.h"
50 #include "customtemplatesmenu.h"
51 #include "messageactions.h"
52 #include "util.h"
53 #include "foldercollection.h"
55 #include <akonadi/contact/contactsearchjob.h>
56 #include <kpimutils/email.h>
57 #include <kmime/kmime_message.h>
59 #include <messageviewer/viewer.h>
60 #include <akonadi/item.h>
62 #include "messagecore/messagehelpers.h"
64 KMReaderMainWin::KMReaderMainWin( bool htmlOverride, bool htmlLoadExtOverride,
65 char *name )
66 : KMail::SecondaryWindow( name ? name : "readerwindow#" )
68 mReaderWin = new KMReaderWin( this, this, actionCollection() );
69 //mReaderWin->setShowCompleteMessage( true );
70 mReaderWin->setHtmlOverride( htmlOverride );
71 mReaderWin->setHtmlLoadExtOverride( htmlLoadExtOverride );
72 mReaderWin->setDecryptMessageOverwrite( true );
73 initKMReaderMainWin();
77 //-----------------------------------------------------------------------------
78 KMReaderMainWin::KMReaderMainWin( char *name )
79 : KMail::SecondaryWindow( name ? name : "readerwindow#" )
81 mReaderWin = new KMReaderWin( this, this, actionCollection() );
82 initKMReaderMainWin();
86 //-----------------------------------------------------------------------------
87 KMReaderMainWin::KMReaderMainWin(KMime::Content* aMsgPart, bool aHTML, const QString & encoding, char *name )
88 : KMail::SecondaryWindow( name ? name : "readerwindow#" )
90 mReaderWin = new KMReaderWin( this, this, actionCollection() );
91 mReaderWin->setOverrideEncoding( encoding );
92 mReaderWin->setHtmlOverride( aHTML );
93 mReaderWin->setMsgPart( aMsgPart );
94 initKMReaderMainWin();
97 //-----------------------------------------------------------------------------
98 void KMReaderMainWin::initKMReaderMainWin()
100 setCentralWidget( mReaderWin );
101 setupAccel();
102 setupGUI( Keys | StatusBar | Create, "kmreadermainwin.rc" );
103 mMsgActions->setupForwardingActionsList( this );
104 applyMainWindowSettings( KMKernel::config()->group( "Separate Reader Window" ) );
105 if( ! mReaderWin->message().isValid() ) {
106 menuBar()->hide();
107 toolBar( "mainToolBar" )->hide();
110 connect( kmkernel, SIGNAL( configChanged() ),
111 this, SLOT( slotConfigChanged() ) );
112 connect( mReaderWin, SIGNAL( showStatusBarMessage( const QString & ) ),
113 statusBar(), SLOT( showMessage( const QString & ) ) );
116 //-----------------------------------------------------------------------------
117 KMReaderMainWin::~KMReaderMainWin()
119 saveMainWindowSettings( KMKernel::config()->group( "Separate Reader Window" ) );
122 //-----------------------------------------------------------------------------
123 void KMReaderMainWin::setUseFixedFont( bool useFixedFont )
125 mReaderWin->setUseFixedFont( useFixedFont );
128 void KMReaderMainWin::showMessage( const QString & encoding, const Akonadi::Item &msg )
130 mReaderWin->setOverrideEncoding( encoding );
131 mReaderWin->setMessage( msg, MessageViewer::Viewer::Force );
132 KMime::Message::Ptr message = MessageCore::Util::message( msg );
133 if ( message )
134 setCaption( message->subject()->asUnicodeString() );
135 mReaderWin->slotTouchMessage();
136 mMsg = msg;
137 mMsgActions->setCurrentMessage( msg );
139 const Akonadi::Collection parent = msg.parentCollection();
140 const bool canChange = parent.isValid() ? !( parent.rights() & Akonadi::Collection::ReadOnly ) : false;
141 mTrashAction->setEnabled( canChange );
143 menuBar()->show();
144 toolBar( "mainToolBar" )->show();
147 void KMReaderMainWin::showMessage( const QString& encoding, KMime::Message::Ptr message )
149 mReaderWin->setOverrideEncoding( encoding );
150 mReaderWin->setMessage( message );
151 if ( message )
152 setCaption( message->subject()->asUnicodeString() );
153 mReaderWin->slotTouchMessage();
155 mTrashAction->setEnabled( false );
157 menuBar()->show();
158 toolBar( "mainToolBar" )->show();
162 void KMReaderMainWin::slotReplyOrForwardFinished()
164 if ( GlobalSettings::self()->closeAfterReplyOrForward() ) {
165 close();
169 //-----------------------------------------------------------------------------
170 void KMReaderMainWin::slotTrashMsg()
172 if ( !mMsg.isValid() )
173 return;
174 KMTrashMsgCommand *command = new KMTrashMsgCommand( mMsg.parentCollection(), mMsg, -1 );
175 command->start();
176 close();
179 //-----------------------------------------------------------------------------
180 void KMReaderMainWin::slotForwardInlineMsg()
182 KMCommand *command = 0;
183 if ( mReaderWin->message().isValid() && mReaderWin->message().parentCollection().isValid() ) {
184 QSharedPointer<FolderCollection> fd = FolderCollection::forCollection( mReaderWin->message().parentCollection() );
185 if ( fd )
186 command = new KMForwardCommand( this, mReaderWin->message(),
187 fd->identity() );
188 else
189 command = new KMForwardCommand( this, mReaderWin->message() );
190 } else {
191 command = new KMForwardCommand( this, mReaderWin->message() );
193 connect( command, SIGNAL( completed( KMCommand * ) ),
194 this, SLOT( slotReplyOrForwardFinished() ) );
195 command->start();
198 //-----------------------------------------------------------------------------
199 void KMReaderMainWin::slotForwardAttachedMsg()
201 KMCommand *command = 0;
202 if ( mReaderWin->message().isValid() && mReaderWin->message().parentCollection().isValid() ) {
203 QSharedPointer<FolderCollection> fd = FolderCollection::forCollection( mReaderWin->message().parentCollection() );
204 if ( fd )
205 command = new KMForwardAttachedCommand( this, mReaderWin->message(),
206 fd->identity() );
207 else
208 command = new KMForwardAttachedCommand( this, mReaderWin->message() );
209 } else {
210 command = new KMForwardAttachedCommand( this, mReaderWin->message() );
212 connect( command, SIGNAL( completed( KMCommand * ) ),
213 this, SLOT( slotReplyOrForwardFinished() ) );
214 command->start();
217 //-----------------------------------------------------------------------------
218 void KMReaderMainWin::slotRedirectMsg()
220 KMCommand *command = new KMRedirectCommand( this, mReaderWin->message() );
221 connect( command, SIGNAL( completed( KMCommand * ) ),
222 this, SLOT( slotReplyOrForwardFinished() ) );
223 command->start();
226 //-----------------------------------------------------------------------------
227 void KMReaderMainWin::slotCustomReplyToMsg( const QString &tmpl )
229 KMCommand *command = new KMCustomReplyToCommand( this,
230 mReaderWin->message(),
231 mReaderWin->copyText(),
232 tmpl );
233 connect( command, SIGNAL( completed( KMCommand * ) ),
234 this, SLOT( slotReplyOrForwardFinished() ) );
235 command->start();
238 //-----------------------------------------------------------------------------
239 void KMReaderMainWin::slotCustomReplyAllToMsg( const QString &tmpl )
241 KMCommand *command = new KMCustomReplyAllToCommand( this,
242 mReaderWin->message(),
243 mReaderWin->copyText(),
244 tmpl );
245 command->start();
248 //-----------------------------------------------------------------------------
249 void KMReaderMainWin::slotCustomForwardMsg( const QString &tmpl)
251 KMCommand *command = new KMCustomForwardCommand( this,
252 mReaderWin->message(),
253 0, tmpl );
254 command->start();
257 //-----------------------------------------------------------------------------
258 void KMReaderMainWin::slotConfigChanged()
260 //readConfig();
261 mMsgActions->setupForwardActions();
262 mMsgActions->setupForwardingActionsList( this );
265 void KMReaderMainWin::setupAccel()
267 if ( kmkernel->xmlGuiInstance().isValid() )
268 setComponentData( kmkernel->xmlGuiInstance() );
270 mMsgActions = new KMail::MessageActions( actionCollection(), this );
271 mMsgActions->setMessageView( mReaderWin );
272 connect( mMsgActions, SIGNAL( replyActionFinished() ),
273 this, SLOT( slotReplyOrForwardFinished() ) );
275 //----- File Menu
276 mSaveAsAction = KStandardAction::saveAs( mReaderWin->viewer(), SLOT( slotSaveMessage() ),
277 actionCollection() );
278 mSaveAsAction->setShortcut( KStandardShortcut::shortcut( KStandardShortcut::Save ) );
280 mSaveAtmAction = new KAction(KIcon("mail-attachment"), i18n("Save A&ttachments..."), actionCollection() );
281 connect( mSaveAtmAction, SIGNAL(triggered(bool)), mReaderWin->viewer(), SLOT(slotAttachmentSaveAs()) );
283 mTrashAction = new KAction( KIcon( "user-trash" ), i18n("&Move to Trash"), this );
284 mTrashAction->setIconText( i18nc( "@action:intoolbar Move to Trash", "Trash" ) );
285 mTrashAction->setHelpText( i18n( "Move message to trashcan" ) );
286 mTrashAction->setShortcut( QKeySequence( Qt::Key_Delete ) );
287 actionCollection()->addAction( "move_to_trash", mTrashAction );
288 connect( mTrashAction, SIGNAL(triggered()), this, SLOT(slotTrashMsg()) );
290 KAction *closeAction = KStandardAction::close( this, SLOT( close() ), actionCollection() );
291 KShortcut closeShortcut = KShortcut(closeAction->shortcuts());
292 closeShortcut.setAlternate( QKeySequence(Qt::Key_Escape));
293 closeAction->setShortcuts(closeShortcut);
295 //----- View Menu
296 mViewSourceAction = new KAction(i18n("&View Source"), this);
297 actionCollection()->addAction("view_source", mViewSourceAction );
298 connect(mViewSourceAction, SIGNAL(triggered(bool) ), mReaderWin->viewer(), SLOT(slotShowMessageSource()));
299 mViewSourceAction->setShortcut(QKeySequence(Qt::Key_V));
301 //----- Message Menu
303 fontAction = new KFontAction( i18n("Select Font"), this );
304 actionCollection()->addAction( "text_font", fontAction );
305 fontAction->setFont( mReaderWin->cssHelper()->bodyFont().family() );
306 connect( fontAction, SIGNAL( triggered( const QString& ) ),
307 SLOT( slotFontAction( const QString& ) ) );
308 fontSizeAction = new KFontSizeAction( i18n( "Select Size" ), this );
309 fontSizeAction->setFontSize( mReaderWin->cssHelper()->bodyFont().pointSize() );
310 actionCollection()->addAction( "text_size", fontSizeAction );
311 connect( fontSizeAction, SIGNAL( fontSizeChanged( int ) ),
312 SLOT( slotSizeAction( int ) ) );
314 updateCustomTemplateMenus();
316 connect( mReaderWin->viewer(), SIGNAL( popupMenu(const Akonadi::Item&,const KUrl&,const QPoint&) ),
317 this, SLOT( slotMessagePopup(const Akonadi::Item&,const KUrl&,const QPoint&) ) );
319 setStandardToolBarMenuEnabled(true);
320 KStandardAction::configureToolbars(this, SLOT(slotEditToolbars()), actionCollection());
324 //-----------------------------------------------------------------------------
325 void KMReaderMainWin::updateCustomTemplateMenus()
327 if ( !mCustomTemplateMenus ) {
328 mCustomTemplateMenus.reset( new CustomTemplatesMenu( this, actionCollection() ) );
329 connect( mCustomTemplateMenus.get(), SIGNAL(replyTemplateSelected( const QString& )),
330 this, SLOT(slotCustomReplyToMsg( const QString& )) );
331 connect( mCustomTemplateMenus.get(), SIGNAL(replyAllTemplateSelected( const QString& )),
332 this, SLOT(slotCustomReplyAllToMsg( const QString& )) );
333 connect( mCustomTemplateMenus.get(), SIGNAL(forwardTemplateSelected( const QString& )),
334 this, SLOT(slotCustomForwardMsg( const QString& )) );
335 connect( KMKernel::self(), SIGNAL(customTemplatesChanged()), mCustomTemplateMenus.get(), SLOT(update()) );
338 mMsgActions->forwardMenu()->addSeparator();
339 mMsgActions->forwardMenu()->addAction( mCustomTemplateMenus->forwardActionMenu() );
341 mMsgActions->replyMenu()->addSeparator();
342 mMsgActions->replyMenu()->addAction( mCustomTemplateMenus->replyActionMenu() );
343 mMsgActions->replyMenu()->addAction( mCustomTemplateMenus->replyAllActionMenu() );
347 //-----------------------------------------------------------------------------
348 KAction *KMReaderMainWin::copyActionMenu()
350 KMMainWidget* mainwin = kmkernel->getKMMainWidget();
351 if ( mainwin )
352 return mainwin->akonadiStandardAction( Akonadi::StandardActionManager::CopyItemToMenu );
353 return 0;
356 void KMReaderMainWin::slotMessagePopup(const Akonadi::Item&aMsg ,const KUrl&aUrl,const QPoint& aPoint)
358 mUrl = aUrl;
359 mMsg = aMsg;
361 const QString email = KPIMUtils::firstEmailAddress( aUrl.path() );
362 Akonadi::ContactSearchJob *job = new Akonadi::ContactSearchJob( this );
363 job->setLimit( 1 );
364 job->setQuery( Akonadi::ContactSearchJob::Email, email, Akonadi::ContactSearchJob::ExactMatch );
365 job->setProperty( "point", aPoint );
366 connect( job, SIGNAL( result( KJob* ) ), SLOT( slotDelayedMessagePopup( KJob* ) ) );
369 void KMReaderMainWin::slotDelayedMessagePopup( KJob *job )
371 const Akonadi::ContactSearchJob *searchJob = qobject_cast<Akonadi::ContactSearchJob*>( job );
372 const bool contactAlreadyExists = !searchJob->contacts().isEmpty();
374 const QPoint aPoint = job->property( "point" ).toPoint();
376 KMenu *menu = new KMenu;
378 bool urlMenuAdded = false;
379 bool copyAdded = false;
380 if ( !mUrl.isEmpty() ) {
381 if ( mUrl.protocol() == "mailto" ) {
382 // popup on a mailto URL
383 menu->addAction( mReaderWin->mailToComposeAction() );
384 if ( mMsg.isValid() ) {
385 menu->addAction( mReaderWin->mailToReplyAction() );
386 menu->addAction( mReaderWin->mailToForwardAction() );
387 menu->addSeparator();
390 if ( contactAlreadyExists ) {
391 menu->addAction( mReaderWin->openAddrBookAction() );
392 } else {
393 menu->addAction( mReaderWin->addAddrBookAction() );
396 menu->addAction( mReaderWin->copyURLAction() );
397 copyAdded = true;
398 } else {
399 // popup on a not-mailto URL
400 menu->addAction( mReaderWin->urlOpenAction() );
401 menu->addAction( mReaderWin->addBookmarksAction() );
402 menu->addAction( mReaderWin->urlSaveAsAction() );
403 menu->addAction( mReaderWin->copyURLAction() );
405 urlMenuAdded = true;
407 if ( !mReaderWin->copyText().isEmpty() ) {
408 if ( urlMenuAdded ) {
409 menu->addSeparator();
411 menu->addAction( mMsgActions->replyMenu() );
412 menu->addSeparator();
413 if( !copyAdded )
414 menu->addAction( mReaderWin->copyAction() );
415 menu->addAction( mReaderWin->selectAllAction() );
416 } else if ( !urlMenuAdded ) {
417 // popup somewhere else (i.e., not a URL) on the message
418 if (!mMsg.isValid()) {
419 // no message
420 delete menu;
421 return;
423 if ( mMsg.parentCollection().isValid() ) {
424 Akonadi::Collection col = mMsg.parentCollection();
425 if ( ! ( KMKernel::self()->folderIsSentMailFolder( col ) ||
426 KMKernel::self()->folderIsDrafts( col ) ||
427 KMKernel::self()->folderIsTemplates( col ) ) ) {
428 // add the reply and forward actions only if we are not in a sent-mail,
429 // templates or drafts folder
431 // FIXME: needs custom templates added to menu
432 // (see KMMainWidget::updateCustomTemplateMenus)
433 menu->addAction( mMsgActions->replyMenu() );
434 menu->addAction( mMsgActions->forwardMenu() );
435 menu->addSeparator();
438 menu->addAction( copyActionMenu() );
440 menu->addSeparator();
441 menu->addAction( mViewSourceAction );
442 menu->addAction( mReaderWin->toggleFixFontAction() );
443 menu->addAction( mReaderWin->toggleMimePartTreeAction() );
444 menu->addSeparator();
445 menu->addAction( mMsgActions->printAction() );
446 menu->addAction( mSaveAsAction );
447 menu->addAction( mSaveAtmAction );
448 menu->addSeparator();
449 menu->addAction( mMsgActions->createTodoAction() );
451 menu->exec( aPoint, 0 );
452 delete menu;
455 void KMReaderMainWin::slotFontAction( const QString& font)
457 QFont f( mReaderWin->cssHelper()->bodyFont() );
458 f.setFamily( font );
459 mReaderWin->cssHelper()->setBodyFont( f );
460 mReaderWin->cssHelper()->setPrintFont( f );
461 mReaderWin->update();
464 void KMReaderMainWin::slotSizeAction( int size )
466 QFont f( mReaderWin->cssHelper()->bodyFont() );
467 f.setPointSize( size );
468 mReaderWin->cssHelper()->setBodyFont( f );
469 mReaderWin->cssHelper()->setPrintFont( f );
470 mReaderWin->update();
473 void KMReaderMainWin::slotCreateTodo()
475 if ( !mReaderWin->message().isValid() )
476 return;
477 KMCommand *command = new CreateTodoCommand( this, mReaderWin->message() );
478 command->start();
481 void KMReaderMainWin::slotEditToolbars()
483 saveMainWindowSettings( KConfigGroup(KMKernel::config(), "ReaderWindow") );
484 KEditToolBar dlg( guiFactory(), this );
485 connect( &dlg, SIGNAL(newToolbarConfig()), SLOT(slotUpdateToolbars()) );
486 dlg.exec();
489 void KMReaderMainWin::slotUpdateToolbars()
491 createGUI("kmreadermainwin.rc");
492 applyMainWindowSettings( KConfigGroup(KMKernel::config(), "ReaderWindow") );
495 #include "kmreadermainwin.moc"