29
29
#include "messagecomposer/globalpart.h"
30
30
#include "messageviewer/editorwatcher.h"
31
31
#include "messageviewer/nodehelper.h"
32
#include "messageviewer/util.h"
33
34
#include <akonadi/itemfetchjob.h>
34
35
#include <kio/jobuidelegate.h>
86
89
void attachPublicKeyJobResult( KJob *job ); // slot
87
90
void slotAttachmentContentCreated( KJob *job ); // slot
88
91
void addAttachmentPart( AttachmentPart::Ptr part );
92
void selectedAllAttachment();
93
void createOpenWithMenu( QMenu *topMenu, AttachmentPart::Ptr part );
90
95
AttachmentControllerBase *const q;
91
96
bool encryptEnabled;
95
100
QHash<MessageViewer::EditorWatcher*,AttachmentPart::Ptr> editorPart;
96
101
QHash<MessageViewer::EditorWatcher*,KTemporaryFile*> editorTempFile;
99
103
AttachmentPart::List selectedParts;
100
104
KActionCollection *mActionCollection;
101
105
QAction *attachPublicKeyAction;
112
116
QAction *propertiesContextAction;
113
117
QAction *addAction;
114
118
QAction *addContextAction;
119
QAction *selectAllAction;
120
KActionMenu *attachmentMenu;
121
QAction *addOwnVcardAction;
116
123
// If part p is compressed, uncompressedParts[p] is the uncompressed part.
117
124
QHash<AttachmentPart::Ptr, AttachmentPart::Ptr> uncompressedParts;
289
298
// The watcher deletes itself.
302
void AttachmentControllerBase::Private::createOpenWithMenu( QMenu *topMenu, AttachmentPart::Ptr part )
304
const QString contentTypeStr = QString::fromLatin1(part->mimeType());
305
const KService::List offers = KFileItemActions::associatedApplications(QStringList()<<contentTypeStr, QString() );
306
if (!offers.isEmpty()) {
307
QMenu* menu = topMenu;
308
QActionGroup *actionGroup = new QActionGroup( menu );
309
connect( actionGroup, SIGNAL(triggered(QAction*)), q, SLOT(slotOpenWithAction(QAction*)) );
311
if (offers.count() > 1) { // submenu 'open with'
312
menu = new QMenu(i18nc("@title:menu", "&Open With"), topMenu);
313
menu->menuAction()->setObjectName(QLatin1String("openWith_submenu")); // for the unittest
314
topMenu->addMenu(menu);
316
//kDebug() << offers.count() << "offers" << topMenu << menu;
318
KService::List::ConstIterator it = offers.constBegin();
319
KService::List::ConstIterator end = offers.constEnd();
320
for(; it != end; ++it) {
321
KAction* act = MessageViewer::Util::createAppAction(*it,
322
// no submenu -> prefix single offer
323
menu == topMenu, actionGroup,menu);
324
menu->addAction(act);
327
QString openWithActionName;
328
if (menu != topMenu) { // submenu
329
menu->addSeparator();
330
openWithActionName = i18nc("@action:inmenu Open With", "&Other...");
332
openWithActionName = i18nc("@title:menu", "&Open With...");
334
KAction *openWithAct = new KAction(menu);
335
openWithAct->setText(openWithActionName);
336
QObject::connect(openWithAct, SIGNAL(triggered()), q, SLOT(slotOpenWithDialog()));
337
menu->addAction(openWithAct);
339
else { // no app offers -> Open With...
340
KAction *act = new KAction(topMenu);
341
act->setText(i18nc("@title:menu", "&Open With..."));
342
QObject::connect(act, SIGNAL(triggered()), q, SLOT(slotOpenWithDialog()));
343
topMenu->addAction(act);
292
349
void AttachmentControllerBase::exportPublicKey( const QString &fingerprint )
294
351
if( fingerprint.isEmpty() || !Kleo::CryptoBackendFactory::instance()->openpgp() ) {
369
427
d->attachMyPublicKeyAction = new KAction( i18n( "Attach &My Public Key" ), this );
370
428
connect( d->attachMyPublicKeyAction, SIGNAL(triggered(bool)), this, SLOT(attachMyPublicKey()) );
430
d->attachmentMenu = new KActionMenu(i18n("Attach"),this);
431
d->attachmentMenu->setDelayed(false);
372
433
d->addAction = new KAction( KIcon( QLatin1String( "mail-attachment" ) ), i18n( "&Attach File..." ), this );
373
434
d->addAction->setIconText( i18n( "Attach" ) );
374
435
d->addContextAction = new KAction( KIcon( QLatin1String( "mail-attachment" ) ),
376
437
connect( d->addAction, SIGNAL(triggered(bool)), this, SLOT(showAddAttachmentDialog()) );
377
438
connect( d->addContextAction, SIGNAL(triggered(bool)), this, SLOT(showAddAttachmentDialog()) );
440
d->addOwnVcardAction = new KAction( i18n("Attach Own Vcard"),this );
441
d->addOwnVcardAction->setIconText( i18n( "Own Vcard" ) );
442
d->addOwnVcardAction->setCheckable(true);
443
connect(d->addOwnVcardAction, SIGNAL(triggered(bool)), this, SIGNAL(addOwnVcard(bool)));
445
d->attachmentMenu->addAction(d->addAction);
446
d->attachmentMenu->addSeparator();
447
d->attachmentMenu->addAction(d->addOwnVcardAction);
379
449
d->removeAction = new KAction( KIcon(QLatin1String("edit-delete")), i18n( "&Remove Attachment" ), this );
380
450
d->removeContextAction = new KAction( KIcon(QLatin1String("edit-delete")), i18n( "Remove" ), this ); // FIXME need two texts. is there a better way?
381
451
connect( d->removeAction, SIGNAL(triggered(bool)), this, SLOT(removeSelectedAttachments()) );
402
472
connect( d->saveAsContextAction, SIGNAL(triggered(bool)),
403
473
this, SLOT(saveSelectedAttachmentAs()) );
405
d->propertiesAction = new KAction( i18n( "Attachment Pr&operties" ), this ); // TODO why no '...'?
475
d->propertiesAction = new KAction( i18n( "Attachment Pr&operties..." ), this );
406
476
d->propertiesContextAction = new KAction( i18n( "Properties" ), this );
407
477
connect( d->propertiesAction, SIGNAL(triggered(bool)),
408
478
this, SLOT(selectedAttachmentProperties()) );
409
479
connect( d->propertiesContextAction, SIGNAL(triggered(bool)),
410
480
this, SLOT(selectedAttachmentProperties()) );
412
// Create a context menu for the attachment view.
413
Q_ASSERT( d->contextMenu == 0 ); // Not called twice.
414
d->contextMenu = new QMenu( d->wParent );
415
d->contextMenu->addAction( d->openContextAction );
416
d->contextMenu->addAction( d->viewContextAction );
417
d->contextMenu->addAction( d->editContextAction );
418
d->contextMenu->addAction( d->editWithContextAction );
419
d->contextMenu->addAction( d->removeContextAction );
420
d->contextMenu->addAction( d->saveAsContextAction );
421
d->contextMenu->addAction( d->propertiesContextAction );
422
d->contextMenu->addSeparator();
423
d->contextMenu->addAction( d->addContextAction );
482
d->selectAllAction = new KAction( i18n("Select All"), this);
483
connect( d->selectAllAction, SIGNAL(triggered(bool)),
484
this, SIGNAL(selectedAllAttachment()) );
425
486
// Insert the actions into the composer window's menu.
426
487
KActionCollection *collection = d->mActionCollection;
430
491
collection->addAction( QLatin1String( "remove" ), d->removeAction );
431
492
collection->addAction( QLatin1String( "attach_save" ), d->saveAsAction );
432
493
collection->addAction( QLatin1String( "attach_properties" ), d->propertiesAction );
494
collection->addAction( QLatin1String( "select_all_attachment"), d->selectAllAction);
495
collection->addAction( QLatin1String( "attach_menu"), d->attachmentMenu );
496
collection->addAction( QLatin1String( "attach_own_vcard"), d->addOwnVcardAction );
435
498
setSelectedParts( AttachmentPart::List());
436
499
emit actionsCreated();
469
532
void AttachmentControllerBase::showContextMenu()
471
534
emit refreshSelection();
472
d->contextMenu->popup( QCursor::pos() );
537
const int numberOfParts(d->selectedParts.count());
538
QMenu *menu = new QMenu;
540
const bool enableEditAction = (numberOfParts == 1) &&
541
( !d->selectedParts.first()->isMessageOrMessageCollection() );
543
if(numberOfParts>0) {
544
if(numberOfParts == 1)
545
d->createOpenWithMenu(menu, d->selectedParts.first());
547
menu->addAction(d->openContextAction);
548
menu->addAction(d->viewContextAction);
550
if(enableEditAction) {
551
menu->addAction(d->editWithContextAction);
552
menu->addAction(d->editContextAction);
554
if(numberOfParts>0) {
555
menu->addAction(d->removeContextAction);
557
if(numberOfParts == 1) {
558
menu->addAction(d->saveAsContextAction);
559
menu->addAction(d->propertiesContextAction);
562
menu->addSeparator();
563
menu->addAction(d->selectAllAction);
564
menu->addSeparator();
565
menu->addAction(d->addContextAction);
567
menu->exec( QCursor::pos() );
571
void AttachmentControllerBase::slotOpenWithDialog()
576
void AttachmentControllerBase::slotOpenWithAction(QAction*act)
578
KService::Ptr app = act->data().value<KService::Ptr>();
579
Q_ASSERT( d->selectedParts.count() == 1 );
584
void AttachmentControllerBase::openWith(KService::Ptr offer)
586
KTemporaryFile *tempFile = dumpAttachmentToTempFile( d->selectedParts.first() );
588
KMessageBox::sorry( d->wParent,
589
i18n( "KMail was unable to write the attachment to a temporary file." ),
590
i18n( "Unable to open attachment" ) );
594
KUrl url = KUrl::fromPath(tempFile->fileName());
598
result = KRun::run( *offer, lst, d->wParent, false );
600
result = KRun::displayOpenWithDialog( lst, d->wParent, false );
606
// The file was opened. Delete it only when the composer is closed
607
// (and this object is destroyed).
608
tempFile->setParent( this ); // Manages lifetime.
475
612
void AttachmentControllerBase::openAttachment( AttachmentPart::Ptr part )
477
614
KTemporaryFile *tempFile = dumpAttachmentToTempFile( part );
478
615
if( !tempFile ) {
479
616
KMessageBox::sorry( d->wParent,
480
i18n( "KMail was unable to write the attachment to a temporary file." ),
481
i18n( "Unable to open attachment" ) );
617
i18n( "KMail was unable to write the attachment to a temporary file." ),
618
i18n( "Unable to open attachment" ) );
670
807
part->setSigned( d->model->isSignSelected() );
671
808
d->model->addAttachment( part );
673
// TODO I can't find this setting in the config dialog. Has it been removed?
674
810
if( MessageComposer::MessageComposerSettings::self()->showMessagePartDialogOnAttach() ) {
675
811
attachmentProperties( part );
679
void AttachmentControllerBase::addAttachment( const KUrl &url )
815
MessageCore::AttachmentFromUrlBaseJob * AttachmentControllerBase::createAttachmentJob(const KUrl &url)
681
AttachmentFromUrlBaseJob *ajob = 0;
817
MessageCore::AttachmentFromUrlBaseJob *ajob = 0;
682
818
if( KMimeType::findByUrl( url )->name() == QLatin1String( "inode/directory" ) ) {
683
819
kDebug() << "Creating attachment from folder";
684
ajob = new AttachmentFromFolderJob ( url, this );
820
ajob = new AttachmentFromFolderJob ( url, this );
687
822
ajob = new AttachmentFromUrlJob( url, this );
688
823
kDebug() << "Creating attachment from file";
690
825
if( MessageComposer::MessageComposerSettings::maximumAttachmentSize() > 0 ) {
691
ajob->setMaximumAllowedSize( MessageComposer::MessageComposerSettings::maximumAttachmentSize() * 1024 * 1024 );
826
ajob->setMaximumAllowedSize( MessageComposer::MessageComposerSettings::maximumAttachmentSize() );
831
void AttachmentControllerBase::addAttachmentUrlSync(const KUrl &url)
833
MessageCore::AttachmentFromUrlBaseJob *ajob = createAttachmentJob(url);
835
AttachmentPart::Ptr part = ajob->attachmentPart();
836
addAttachment( part );
838
if( ajob->error() ) {
839
KMessageBox::sorry( d->wParent, ajob->errorString(), i18n( "Failed to attach file" ) );
844
void AttachmentControllerBase::addAttachment( const KUrl &url )
846
MessageCore::AttachmentFromUrlBaseJob *ajob = createAttachmentJob(url);
693
847
connect( ajob, SIGNAL(result(KJob*)), this, SLOT(loadJobResult(KJob*)) );
729
883
d->attachMyPublicKeyAction->setEnabled( enable );
886
void AttachmentControllerBase::setAttachOwnVcard(bool attachVcard)
888
d->addOwnVcardAction->setChecked(attachVcard);
891
bool AttachmentControllerBase::attachOwnVcard() const
893
return d->addOwnVcardAction->isChecked();
896
void AttachmentControllerBase::setIdentityHasOwnVcard(bool state)
898
d->addOwnVcardAction->setEnabled(state);
732
901
#include "attachmentcontrollerbase.moc"