diff --git a/CMakeLists.txt b/CMakeLists.txt index 5bd4a5ac4..597c06daf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -196,7 +196,10 @@ set(kmailprivate_LIB_SRCS editorwatcher.cpp ) -qt4_add_dbus_interfaces(kmailprivate_LIB_SRCS ${CMAKE_SOURCE_DIR}/kmail/org.kde.kmail.kmail.xml) +qt4_add_dbus_interfaces(kmailprivate_LIB_SRCS + ${CMAKE_SOURCE_DIR}/kmail/org.kde.kmail.kmail.xml + ${CMAKE_SOURCE_DIR}/korganizer/org.kde.Korganizer.Calendar.xml +) qt4_add_dbus_adaptor( kmailprivate_LIB_SRCS ${CMAKE_SOURCE_DIR}/libkdepim/interfaces/org.kde.mailtransport.service.xml mailserviceimpl.h KMail::MailServiceImpl) diff --git a/kmail_part.rc b/kmail_part.rc index 7e78c527c..f85ecfc35 100644 --- a/kmail_part.rc +++ b/kmail_part.rc @@ -2,7 +2,7 @@ the same menu entries at the same place in KMail and Kontact --> - + &File @@ -147,6 +147,8 @@ + + &Tools diff --git a/kmcommands.cpp b/kmcommands.cpp index 47f19ab61..735a5f85f 100644 --- a/kmcommands.cpp +++ b/kmcommands.cpp @@ -61,6 +61,7 @@ #include #include +#include #include #include #include @@ -120,6 +121,7 @@ using KMail::TemplateParser; #include "globalsettings.h" #include +#include "calendarinterface.h" #include "progressmanager.h" using KPIM::ProgressManager; @@ -3400,4 +3402,58 @@ void KMEditAttachmentCommand::editDone(KMail::EditorWatcher * watcher) storeChangedMessage( newMsg ); } + +CreateTodoCommand::CreateTodoCommand(QWidget * parent, KMMessage * msg) + : KMCommand( parent, msg ) +{ +} + +KMCommand::Result CreateTodoCommand::execute() +{ + KMMessage *msg = retrievedMessage(); + if ( !msg || !msg->codec() ) { + return Failed; + } + + // korganizer starting code taken from the ical bpf plugin + QString error; + QString dbusService; + int result = KDBusServiceStarter::self()->findServiceFor( "DBUS/Organizer", + QString::null, &error, &dbusService ); + if ( result == 0 ) { +#warning Port me! +#if 0 + // OK, so korganizer (or kontact) is running. Now ensure the object we want is available + // [that's not the case when kontact was already running, but korganizer not loaded into it...] + static const char* const dcopObjectId = "KOrganizerIface"; + QCString dummy; + if ( !kapp->dcopClient()->findObject( dcopService, dcopObjectId, "", QByteArray(), dummy, dummy ) ) { + DCOPRef ref( dcopService, dcopService ); // talk to the KUniqueApplication or its kontact wrapper + DCOPReply reply = ref.call( "load()" ); + if ( reply.isValid() && (bool)reply ) { + kdDebug() << "Loaded " << dcopService << " successfully" << endl; + Q_ASSERT( kapp->dcopClient()->findObject( dcopService, dcopObjectId, "", QByteArray(), dummy, dummy ) ); + } else + kdWarning() << "Error loading " << dcopService << endl; + } +#endif + } + + QString txt = i18n("From: %1\nTo: %2\nSubject: %3").arg( msg->from() ) + .arg( msg->to() ).arg( msg->subject() ); + + KTemporaryFile tf; + tf.setAutoRemove( true ); + QString uri = "kmail:" + QString::number( msg->getMsgSerNum() ) + "/" + msg->msgId(); + tf.write( msg->asDwString().c_str(), msg->asDwString().length() ); + + OrgKdeKorganizerCalendarInterface *iface = new OrgKdeKorganizerCalendarInterface( "org.kde.korganizer", "/Calendar", QDBusConnection::sessionBus(), this ); + iface->openTodoEditor( i18n("Mail: %1").arg( msg->subject() ), txt, + uri, tf.name(), QStringList(), "message/rfc822" ); + delete iface; + tf.close(); + + return OK; +} + #include "kmcommands.moc" diff --git a/kmcommands.h b/kmcommands.h index ad628b39a..16886ff50 100644 --- a/kmcommands.h +++ b/kmcommands.h @@ -1051,4 +1051,14 @@ class KDE_EXPORT KMEditAttachmentCommand : public AttachmentModifyCommand KTemporaryFile mTempFile; }; +class KDE_EXPORT CreateTodoCommand : public KMCommand +{ + Q_OBJECT + public: + CreateTodoCommand( QWidget *parent, KMMessage *msg ); + + private: + Result execute(); +}; + #endif /*KMCommands_h*/ diff --git a/kmheaders.cpp b/kmheaders.cpp index 8fad58078..626dbca57 100644 --- a/kmheaders.cpp +++ b/kmheaders.cpp @@ -1192,7 +1192,7 @@ void KMHeaders::msgHeaderChanged(KMFolder*, int msgId) //----------------------------------------------------------------------------- // TODO: Use KMCommand class -void KMHeaders::setMessageTagList( const QString &taglabel ) +void KMHeaders::setMessageTagList( const QString &taglabel ) { for ( Q3ListViewItemIterator it(this); it.current(); ++it ) if ( it.current()->isSelected() && it.current()->isVisible() ) { @@ -2434,6 +2434,9 @@ void KMHeaders::slotRMB() if ( mOwner->trashThreadAction()->isEnabled() ) menu->addAction( mOwner->trashThreadAction() ); } + menu->insertSeparator(); + menu->addAction( mOwner->createTodoAction() ); + KAcceleratorManager::manage(menu); kmkernel->setContextMenuShown( true ); menu->exec(QCursor::pos(), 0); diff --git a/kmmainwidget.cpp b/kmmainwidget.cpp index 73e75c5fa..02648f060 100644 --- a/kmmainwidget.cpp +++ b/kmmainwidget.cpp @@ -428,7 +428,7 @@ void KMMainWidget::readConfig(void) mFolderTree->addTotalColumn( i18n("Total"), 70 ); else if (sizeColumn == 2) mFolderTree->addSizeColumn( i18n("Size"), 70 ); - + if (unreadColumn == 3) mFolderTree->addUnreadColumn( i18n("Unread"), 70 ); else if (totalColumn == 3) @@ -743,7 +743,7 @@ void KMMainWidget::createWidgets(void) mAccel->connectItem( mAccel->insertItem( Qt::ALT+Qt::Key_Space ), mHeaders, SLOT( selectCurrentMessage() ) ); } - + connect( kmkernel->outboxFolder(), SIGNAL( msgRemoved(int, const QString&) ), SLOT( startUpdateMessageActionsTimer() ) ); connect( kmkernel->outboxFolder(), SIGNAL( msgAdded(int) ), @@ -1037,7 +1037,7 @@ void KMMainWidget::slotShowNewFromTemplate() KMMsgBase *mb = mTemplateFolder->getMsgBase( idx ); QString subj = mb->subject(); - if ( subj.isEmpty() ) + if ( subj.isEmpty() ) subj = i18n("No Subject"); QAction *templateAction = mTemplateMenu->menu()->addAction( @@ -2821,19 +2821,19 @@ void KMMainWidget::setupActions() actionCollection()->addAction("antiSpamWizard", action ); connect(action, SIGNAL(triggered(bool) ), SLOT(slotAntiSpamWizard())); } - { + { QAction *action = new KAction(i18n("&Anti-Virus Wizard..."), this); actionCollection()->addAction("antiVirusWizard", action ); connect(action, SIGNAL(triggered(bool) ), SLOT(slotAntiVirusWizard())); } - if ( GlobalSettings::allowOutOfOfficeSettings() ) + if ( GlobalSettings::allowOutOfOfficeSettings() ) { QAction *action = new KAction( i18n("Edit \"Out of Office\" Replies..."), this ); actionCollection()->addAction( "tools_edit_vacation", action ); connect( action, SIGNAL(triggered("bool")), SLOT(slotEditVacation()) ); } - + { QAction *action = new KAction( i18n("Filter &Log Viewer..."), this ); actionCollection()->addAction( "filter_log_viewer", action ); @@ -3256,6 +3256,10 @@ void KMMainWidget::setupActions() mApplyFilterActionsMenu = new KActionMenu(i18n("A&pply Filter"), this); actionCollection()->addAction("apply_filter_actions", mApplyFilterActionsMenu ); + mCreateTodoAction = new KAction( KIcon( "mail_todo" ), i18n("Create Task..."), this ); + connect( mCreateTodoAction, SIGNAL(triggered()), SLOT(slotCreateTodo()) ); + actionCollection()->addAction( "create_todo", mCreateTodoAction ); + //----- View Menu // Unread Submenu KActionMenu * unreadMenu = new KActionMenu(i18nc("View->", "&Unread Count"), this); @@ -3681,6 +3685,7 @@ void KMMainWidget::updateMessageActions() printAction()->setEnabled( single_actions ); viewSourceAction()->setEnabled( single_actions ); + createTodoAction()->setEnabled( single_actions ); mSendAgainAction->setEnabled( single_actions && ( mHeaders->currentMsg() && mHeaders->currentMsg()->status().isSent() ) @@ -3798,7 +3803,7 @@ void KMMainWidget::slotShowStartupFolder() this, SLOT( initializeFilterActions() )); connect(kmkernel->msgTagMgr(), SIGNAL( msgTagListChanged() ), - this, SLOT( initializeMessageTagActions() ) ); + this, SLOT( initializeMessageTagActions() ) ); // plug shortcut filter actions now initializeFilterActions(); @@ -3839,34 +3844,34 @@ void KMMainWidget::updateMessageTagActions( const int count ) if ( 1 == count ) { KMMessageTagList *aTagList = mHeaders->currentMsg()->tagList(); for ( QList::ConstIterator it = - mMessageTagMenuActions.constBegin(); + mMessageTagMenuActions.constBegin(); it != mMessageTagMenuActions.constEnd(); ++it ) { bool list_present = false; if ( aTagList ) - list_present = + list_present = aTagList->find( QString((*it).second->name() ) ) != aTagList->end(); aToggler = static_cast( (*it).second ); aToggler->setChecked( list_present ); } } else if ( count > 1 ) { for ( QList::ConstIterator it = - mMessageTagMenuActions.constBegin(); + mMessageTagMenuActions.constBegin(); it != mMessageTagMenuActions.constEnd(); ++it ) { aToggler = static_cast( (*it).second ); aToggler->setChecked( false ); aToggler->setText( i18n("Toggle Message Tag %1", (*it).first->name() ) ); } - } + } else { for ( QList::ConstIterator it = - mMessageTagMenuActions.constBegin(); + mMessageTagMenuActions.constBegin(); it != mMessageTagMenuActions.constEnd(); ++it ) { aToggler = static_cast( (*it).second ); aToggler->setEnabled( false ); } } } -void KMMainWidget::slotUpdateMessageTagList( const QString &name ) +void KMMainWidget::slotUpdateMessageTagList( const QString &name ) { mHeaders->setMessageTagList( name ); } @@ -3880,7 +3885,7 @@ void KMMainWidget::clearMessageTagActions() mGUIClient->unplugActionList( "toolbar_messagetag_actions" ); } for ( QList::ConstIterator it = - mMessageTagMenuActions.constBegin(); + mMessageTagMenuActions.constBegin(); it != mMessageTagMenuActions.constEnd(); ++it ) { mStatusMenu->remove( (*it).second ); delete (*it).second; @@ -3890,7 +3895,7 @@ void KMMainWidget::clearMessageTagActions() mMessageTagToggleMapper = 0; } -void KMMainWidget::initializeMessageTagActions() +void KMMainWidget::initializeMessageTagActions() { clearMessageTagActions(); const QHash *tagDict = kmkernel->msgTagMgr()->msgTagDict(); @@ -3900,7 +3905,7 @@ void KMMainWidget::initializeMessageTagActions() mMessageTagToggleMapper = new QSignalMapper( this ); connect( mMessageTagToggleMapper, SIGNAL( mapped( const QString& ) ), this, SLOT( slotUpdateMessageTagList( const QString& ) ) ); - + //TODO: No need to do this anymore, just use the ordered list const int numTags = tagDict->count(); if ( !numTags ) return; @@ -3909,14 +3914,14 @@ void KMMainWidget::initializeMessageTagActions() } KAction *tagAction = 0; - QHashIterator it( *tagDict ); + QHashIterator it( *tagDict ); while( it.hasNext() ) { it.next(); if ( ! it.value() || it.value()->isEmpty() ) continue; QString cleanName = i18n("Message Tag %1", it.value()->name() ); cleanName.replace("&","&&"); - tagAction = new KToggleAction( KIcon(it.value()->toolbarIconName()), + tagAction = new KToggleAction( KIcon(it.value()->toolbarIconName()), cleanName, this ); tagAction->setShortcut( it.value()->shortcut() ); actionCollection()->addAction(it.value()->label().local8Bit(), tagAction); @@ -3939,9 +3944,9 @@ void KMMainWidget::initializeMessageTagActions() if ( !mMessageTagTBarActions.isEmpty() && mGUIClient->factory() ) { //Separator doesn't work //mMessageTagTBarActions.prepend( mMessageTagToolbarActionSeparator ); - mGUIClient->plugActionList( "toolbar_messagetag_actions", + mGUIClient->plugActionList( "toolbar_messagetag_actions", mMessageTagTBarActions ); - } + } } //----------------------------------------------------------------------------- @@ -4350,3 +4355,12 @@ QString KMMainWidget::overrideEncoding() const else return GlobalSettings::self()->overrideCharacterEncoding(); } + +void KMMainWidget::slotCreateTodo() +{ + KMMessage *msg = mHeaders->currentMsg(); + if ( !msg ) + return; + KMCommand *command = new CreateTodoCommand( this, msg ); + command->start(); +} diff --git a/kmmainwidget.h b/kmmainwidget.h index f24db98b5..4ae82a623 100644 --- a/kmmainwidget.h +++ b/kmmainwidget.h @@ -142,6 +142,7 @@ class KMAIL_EXPORT KMMainWidget : public QWidget KAction *saveAttachmentsAction() const { return mSaveAttachmentsAction; } KAction *openAction() const { return mOpenAction; } KAction *viewSourceAction() { return mViewSourceAction; } + KAction *createTodoAction() { return mCreateTodoAction; } KActionMenu *statusMenu() const{ return mStatusMenu; } KActionMenu *threadStatusMenu() const { return mThreadStatusMenu; } @@ -252,10 +253,10 @@ class KMAIL_EXPORT KMMainWidget : public QWidget /**Clear and create actions for message tag toggling*/ void clearMessageTagActions(); void initializeMessageTagActions(); - /**Adds if not existing/removes if existing the tag identified by @p aLabel + /**Adds if not existing/removes if existing the tag identified by @p aLabel in all selected messages*/ void slotUpdateMessageTagList( const QString &aLabel ); - /**If @p aCount is 0, disables all tag related actions in menus. + /**If @p aCount is 0, disables all tag related actions in menus. If @p aCount is 1, Checks/unchecks according to the selected message's tag list. If @p aCount is >1, changes labels of the actions to "Toggle " @param aCount Number of selected messages*/ @@ -410,6 +411,7 @@ class KMAIL_EXPORT KMMainWidget : public QWidget /** Settings menu */ void slotToggleShowQuickSearch(); + void slotCreateTodo(); /** XML-GUI stuff */ void slotEditNotifications(); @@ -475,7 +477,8 @@ class KMAIL_EXPORT KMMainWidget : public QWidget KAction *mTrashAction, *mDeleteAction, *mTrashThreadAction, *mDeleteThreadAction, *mSaveAsAction, *mEditAction, *mUseAction, *mSendAgainAction, *mApplyAllFiltersAction, *mFindInMessageAction, - *mSaveAttachmentsAction, *mOpenAction, *mViewSourceAction; + *mSaveAttachmentsAction, *mOpenAction, *mViewSourceAction, + *mCreateTodoAction; // Composition actions KAction *mPrintAction, @@ -572,7 +575,7 @@ class KMAIL_EXPORT KMMainWidget : public QWidget QHash mFolderShortcutCommands; QPointer mJob; - QList mMessageTagMenuActions; + QList mMessageTagMenuActions; QList mMessageTagTBarActions; QSignalMapper *mMessageTagToggleMapper; diff --git a/kmmainwin.rc b/kmmainwin.rc index e88116d1e..90aec4fe1 100644 --- a/kmmainwin.rc +++ b/kmmainwin.rc @@ -2,7 +2,7 @@ the same menu entries at the same place in KMail and Kontact --> - + &File @@ -150,6 +150,8 @@ + + &Tools