summaryrefslogtreecommitdiffstats
path: root/plugins/kmail
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/kmail')
-rw-r--r--plugins/kmail/Makefile.am1
-rw-r--r--plugins/kmail/bodypartformatter/Makefile.am52
-rw-r--r--plugins/kmail/bodypartformatter/attendeeselector.cpp82
-rw-r--r--plugins/kmail/bodypartformatter/attendeeselector.h49
-rw-r--r--plugins/kmail/bodypartformatter/delegateselector.cpp54
-rw-r--r--plugins/kmail/bodypartformatter/delegateselector.h49
-rw-r--r--plugins/kmail/bodypartformatter/text_calendar.cpp715
-rw-r--r--plugins/kmail/bodypartformatter/text_calendar.desktop86
-rw-r--r--plugins/kmail/bodypartformatter/text_vcard.cpp167
-rw-r--r--plugins/kmail/bodypartformatter/text_vcard.desktop87
-rw-r--r--plugins/kmail/bodypartformatter/text_xdiff.cpp152
-rw-r--r--plugins/kmail/bodypartformatter/text_xdiff.desktop83
-rw-r--r--plugins/kmail/bodypartformatter/ui_attendeeselector.ui88
13 files changed, 1665 insertions, 0 deletions
diff --git a/plugins/kmail/Makefile.am b/plugins/kmail/Makefile.am
new file mode 100644
index 000000000..b0b9e942b
--- /dev/null
+++ b/plugins/kmail/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = bodypartformatter
diff --git a/plugins/kmail/bodypartformatter/Makefile.am b/plugins/kmail/bodypartformatter/Makefile.am
new file mode 100644
index 000000000..b476d1ba0
--- /dev/null
+++ b/plugins/kmail/bodypartformatter/Makefile.am
@@ -0,0 +1,52 @@
+KDE_OPTIONS = nofinal
+KDE_CXXFLAGS = $(USE_RTTI)
+
+INCLUDES = -I$(top_srcdir)/kmail \
+ -I$(top_srcdir)/libkdepim \
+ -I$(top_srcdir)/libkmime \
+ -I$(top_srcdir)/mimelib \
+ -I$(top_srcdir)/libemailfunctions \
+ -I$(top_srcdir) \
+ -I$(top_builddir)/libkdepim \
+ -I$(top_srcdir)/korganizer \
+ $(all_includes)
+
+kde_module_LTLIBRARIES = libkmail_bodypartformatter_text_vcard.la \
+ libkmail_bodypartformatter_text_calendar.la \
+ libkmail_bodypartformatter_text_xdiff.la
+
+libkmail_bodypartformatter_text_vcard_la_SOURCES = text_vcard.cpp
+libkmail_bodypartformatter_text_vcard_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) -no-undefined
+libkmail_bodypartformatter_text_vcard_la_LIBADD = $(LIB_QT) $(LIB_KABC) \
+ ../../../libkdepim/libkdepim.la \
+ ../../../libkmime/libkmime.la \
+ ../../../libemailfunctions/libemailfunctions.la
+
+libkmail_bodypartformatter_text_calendar_la_SOURCES = \
+ text_calendar.cpp \
+ delegateselector.cpp \
+ attendeeselector.cpp \
+ ui_attendeeselector.ui \
+ kcalendariface.stub
+libkmail_bodypartformatter_text_calendar_la_LDFLAGS = \
+ $(all_libraries) -module $(KDE_PLUGIN) -no-undefined
+libkmail_bodypartformatter_text_calendar_la_LIBADD = $(LIB_QT) $(LIB_KABC) \
+ $(top_builddir)/libkcal/libkcal.la $(top_builddir)/kmail/libkmailprivate.la
+
+kcalendariface_DIR = $(top_srcdir)/korganizer
+
+libkmail_bodypartformatter_text_xdiff_la_SOURCES = text_xdiff.cpp
+libkmail_bodypartformatter_text_xdiff_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
+libkmail_bodypartformatter_text_xdiff_la_LIBADD = $(LIB_QT)
+
+
+linkdir = $(kde_datadir)/kmail/plugins/bodypartformatter
+link_DATA = text_vcard.desktop text_calendar.desktop text_xdiff.desktop
+
+METASOURCES = AUTO
+
+messages:
+ $(EXTRACTRC) ui_attendeeselector.ui >> ui_attendeeselector.rc.cpp
+ $(XGETTEXT) text_vcard.cpp -o $(podir)/kmail_text_vcard_plugin.pot
+ $(XGETTEXT) text_calendar.cpp delegateselector.cpp attendeeselector.cpp ui_attendeeselector.rc.cpp -o $(podir)/kmail_text_calendar_plugin.pot
+ $(XGETTEXT) text_xdiff.cpp -o $(podir)/kmail_text_xdiff_plugin.pot
diff --git a/plugins/kmail/bodypartformatter/attendeeselector.cpp b/plugins/kmail/bodypartformatter/attendeeselector.cpp
new file mode 100644
index 000000000..ac8059dc9
--- /dev/null
+++ b/plugins/kmail/bodypartformatter/attendeeselector.cpp
@@ -0,0 +1,82 @@
+/*
+ Copyright (c) a2007 Volker Krause <vkrause@kde.org>
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This library is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+*/
+
+#include "attendeeselector.h"
+#include "ui_attendeeselector.h"
+
+#include <libkdepim/addresseelineedit.h>
+
+#include <klocale.h>
+#include <kpushbutton.h>
+
+#include <qlayout.h>
+
+AttendeeSelector::AttendeeSelector(QWidget * parent)
+ : KDialogBase( parent, 0, true, i18n("Select Attendees"), Ok|Cancel, NoDefault, true )
+{
+ ui = new AttendeeSelectorWidget( this );
+ setMainWidget( ui );
+
+ QGridLayout *layout = static_cast<QGridLayout*>( ui->layout() );
+ layout->setMargin( 0 );
+
+ ui->addButton->setGuiItem( KStdGuiItem::add() );
+ connect( ui->addButton, SIGNAL(clicked()), SLOT(addClicked()) );
+ ui->removeButton->setGuiItem( KStdGuiItem::remove() );
+ connect( ui->removeButton, SIGNAL(clicked()), SLOT(removeClicked()) );
+
+ ui->attendeeEdit->setClickMessage( i18n("Click to add a new attendee") );
+ connect( ui->attendeeEdit, SIGNAL(textChanged(const QString&)), SLOT(textChanged(const QString&)) );
+ connect( ui->attendeeEdit, SIGNAL(returnPressed(const QString&)), SLOT(addClicked()) );
+
+ connect( ui->attendeeList, SIGNAL(selectionChanged()), SLOT(selectionChanged()) );
+}
+
+QStringList AttendeeSelector::attendees() const
+{
+ QStringList rv;
+ for ( uint i = 0; i < ui->attendeeList->count(); ++i )
+ rv << ui->attendeeList->item( i )->text();
+ return rv;
+}
+
+void AttendeeSelector::addClicked()
+{
+ if ( !ui->attendeeEdit->text().isEmpty() )
+ ui->attendeeList->insertItem( ui->attendeeEdit->text() );
+ ui->attendeeEdit->clear();
+}
+
+void AttendeeSelector::removeClicked()
+{
+ if ( ui->attendeeList->currentItem() >= 0 )
+ ui->attendeeList->removeItem( ui->attendeeList->currentItem() );
+}
+
+void AttendeeSelector::textChanged( const QString &text )
+{
+ ui->addButton->setEnabled( !text.isEmpty() );
+}
+
+void AttendeeSelector::selectionChanged()
+{
+ ui->removeButton->setEnabled( ui->attendeeList->currentItem() >= 0 );
+}
+
+#include "attendeeselector.moc"
diff --git a/plugins/kmail/bodypartformatter/attendeeselector.h b/plugins/kmail/bodypartformatter/attendeeselector.h
new file mode 100644
index 000000000..83dbe689e
--- /dev/null
+++ b/plugins/kmail/bodypartformatter/attendeeselector.h
@@ -0,0 +1,49 @@
+/*
+ Copyright (c) a2007 Volker Krause <vkrause@kde.org>
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This library is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+*/
+
+#ifndef ATTENDEESELECTOR_H_H
+#define ATTENDEESELECTOR_H_H
+
+#include <kdialogbase.h>
+
+class AttendeeSelectorWidget;
+
+/**
+ Dialog to select a set off attendees.
+*/
+class AttendeeSelector : public KDialogBase
+{
+ Q_OBJECT
+ public:
+ AttendeeSelector( QWidget *parent = 0 );
+
+ QStringList attendees() const;
+
+ private slots:
+ void addClicked();
+ void removeClicked();
+ void textChanged( const QString &text );
+ void selectionChanged();
+
+ private:
+ AttendeeSelectorWidget *ui;
+};
+
+
+#endif
diff --git a/plugins/kmail/bodypartformatter/delegateselector.cpp b/plugins/kmail/bodypartformatter/delegateselector.cpp
new file mode 100644
index 000000000..79d46a65b
--- /dev/null
+++ b/plugins/kmail/bodypartformatter/delegateselector.cpp
@@ -0,0 +1,54 @@
+/*
+ Copyright (c) 2007 Volker Krause <vkrause@kde.org>
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This library is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+*/
+
+#include "delegateselector.h"
+
+#include <libkdepim/addresseelineedit.h>
+
+#include <klocale.h>
+
+#include <qcheckbox.h>
+#include <qhbox.h>
+#include <qlabel.h>
+#include <qvbox.h>
+
+DelegateSelector::DelegateSelector(QWidget * parent)
+ : KDialogBase( parent, 0, true, i18n("Select delegate"), Ok|Cancel, Ok, true )
+{
+ QVBox *page = makeVBoxMainWidget();
+
+ QHBox *delegateBox = new QHBox( page );
+ new QLabel( i18n("Delegate:"), delegateBox );
+ mDelegate = new KPIM::AddresseeLineEdit( delegateBox );
+
+ mRsvp = new QCheckBox( i18n("Keep me informed about status changes of this incidence."), page );
+ mRsvp->setChecked( true );
+}
+
+QString DelegateSelector::delegate() const
+{
+ return mDelegate->text();
+}
+
+bool DelegateSelector::rsvp() const
+{
+ return mRsvp->isChecked();
+}
+
+#include "delegateselector.moc"
diff --git a/plugins/kmail/bodypartformatter/delegateselector.h b/plugins/kmail/bodypartformatter/delegateselector.h
new file mode 100644
index 000000000..8a01323d7
--- /dev/null
+++ b/plugins/kmail/bodypartformatter/delegateselector.h
@@ -0,0 +1,49 @@
+/*
+ Copyright (c) 2007 Volker Krause <vkrause@kde.org>
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This library is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+*/
+
+#ifndef DELEGATESELECTOR_H
+#define DELEGATESELECTOR_H
+
+#include <kdialogbase.h>
+
+namespace KPIM {
+ class AddresseeLineEdit;
+}
+
+class QCheckBox;
+
+/**
+ Selection dialog for a delegate.
+*/
+class DelegateSelector : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ DelegateSelector( QWidget *parent = 0 );
+
+ QString delegate() const;
+ bool rsvp() const;
+
+ private:
+ KPIM::AddresseeLineEdit *mDelegate;
+ QCheckBox *mRsvp;
+};
+
+#endif
diff --git a/plugins/kmail/bodypartformatter/text_calendar.cpp b/plugins/kmail/bodypartformatter/text_calendar.cpp
new file mode 100644
index 000000000..ba9b16eb0
--- /dev/null
+++ b/plugins/kmail/bodypartformatter/text_calendar.cpp
@@ -0,0 +1,715 @@
+/*
+ This file is part of kdepim.
+
+ Copyright (c) 2004 Cornelius Schumacher <schumacher@kde.org>
+ Copyright (c) 2007 Volker Krause <vkrause@kde.org>
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#include "attendeeselector.h"
+#include "delegateselector.h"
+
+#include <interfaces/bodypartformatter.h>
+#include <interfaces/bodypart.h>
+#include <interfaces/bodyparturlhandler.h>
+#include <khtmlparthtmlwriter.h>
+
+#include <libkcal/calendarlocal.h>
+#include <libkcal/calendarresources.h>
+#include <libkcal/icalformat.h>
+#include <libkcal/attendee.h>
+#include <libkcal/incidence.h>
+#include <libkcal/incidenceformatter.h>
+
+#include <kpimprefs.h> // for the timezone
+
+#include <kmail/callback.h>
+#include <kmail/kmmessage.h>
+#include <kmail/kmcommands.h>
+
+#include <email.h>
+
+#include <kglobal.h>
+#include <kinputdialog.h>
+#include <klocale.h>
+#include <kstringhandler.h>
+#include <kglobalsettings.h>
+#include <kiconloader.h>
+#include <kdebug.h>
+#include <kdcopservicestarter.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <kapplication.h>
+#include <ktempfile.h>
+
+#include <qurl.h>
+#include <qdir.h>
+#include <qtextstream.h>
+
+#include <kdepimmacros.h>
+
+#include <dcopclient.h>
+#include <dcopref.h>
+
+#include "kcalendariface_stub.h"
+
+using namespace KCal;
+
+namespace {
+
+class CalendarManager
+{
+ public:
+ CalendarManager();
+ ~CalendarManager();
+ static KCal::Calendar* calendar();
+
+ private:
+ KCal::CalendarResources* mCalendar;
+ static CalendarManager* mSelf;
+};
+
+static KStaticDeleter<CalendarManager> sCalendarDeleter;
+CalendarManager* CalendarManager::mSelf = 0;
+
+CalendarManager::CalendarManager()
+{
+ mCalendar = new CalendarResources( KPimPrefs::timezone() );
+ mCalendar->readConfig();
+ mCalendar->load();
+ bool multipleKolabResources = false;
+ CalendarResourceManager *mgr = mCalendar->resourceManager();
+ for ( CalendarResourceManager::ActiveIterator it = mgr->activeBegin(); it != mgr->activeEnd(); ++it ) {
+ if ( (*it)->type() == "imap" || (*it)->type() == "kolab" ) {
+ const QStringList subResources = (*it)->subresources();
+ QMap<QString, int> prefixSet; // KDE4: QSet
+ for ( QStringList::ConstIterator subIt = subResources.begin(); subIt != subResources.end(); ++subIt ) {
+ if ( !(*subIt).contains( "/.INBOX.directory/" ) )
+ // we don't care about shared folders
+ continue;
+ prefixSet.insert( (*subIt).left( (*subIt).find( "/.INBOX.directory/" ) ), 0 );
+ }
+ if ( prefixSet.count() > 1 )
+ multipleKolabResources = true;
+ }
+ }
+ if ( multipleKolabResources ) {
+ kdDebug() << k_funcinfo << "disabling calendar lookup because multiple active Kolab resources" << endl;
+ delete mCalendar;
+ mCalendar = 0;
+ }
+}
+
+CalendarManager::~CalendarManager()
+{
+ delete mCalendar;
+ mSelf = 0;
+}
+
+KCal::Calendar* CalendarManager::calendar()
+{
+ if ( !mSelf ) {
+ sCalendarDeleter.setObject( mSelf, new CalendarManager() );
+ }
+ return mSelf->mCalendar;
+}
+
+
+class KMInvitationFormatterHelper : public KCal::InvitationFormatterHelper
+{
+ public:
+ KMInvitationFormatterHelper( KMail::Interface::BodyPart *bodyPart ) : mBodyPart( bodyPart ) {}
+ virtual QString generateLinkURL( const QString &id ) { return mBodyPart->makeLink( id ); }
+ KCal::Calendar* calendar() const { return CalendarManager::calendar(); }
+ private:
+ KMail::Interface::BodyPart *mBodyPart;
+};
+
+class Formatter : public KMail::Interface::BodyPartFormatter
+{
+ public:
+ Result format( KMail::Interface::BodyPart *bodyPart,
+ KMail::HtmlWriter *writer ) const
+ {
+ if ( !writer )
+ // Guard against crashes in createReply()
+ return Ok;
+ CalendarLocal cl( KPimPrefs::timezone() );
+ KMInvitationFormatterHelper helper( bodyPart );
+ QString source;
+ /* If the bodypart does not have a charset specified, we need to fall back to
+ utf8, not the KMail fallback encoding, so get the contents as binary and decode
+ explicitely. */
+ if ( bodyPart->contentTypeParameter( "charset").isEmpty() ) {
+ const QByteArray &ba = bodyPart->asBinary();
+ source = QString::fromUtf8(ba);
+ } else {
+ source = bodyPart->asText();
+ }
+ QString html = IncidenceFormatter::formatICalInvitation( source, &cl, &helper );
+
+ if ( html.isEmpty() ) return AsIcon;
+ writer->queue( html );
+
+ return Ok;
+ }
+};
+
+static QString directoryForStatus( Attendee::PartStat status )
+{
+ QString dir;
+ switch ( status ) {
+ case Attendee::Accepted:
+ dir = "accepted";
+ break;
+ case Attendee::Tentative:
+ dir = "tentative";
+ break;
+ case Attendee::Declined:
+ dir = "cancel";
+ break;
+ case Attendee::Delegated:
+ dir = "delegated";
+ break;
+ default:
+ break;
+ }
+ return dir;
+}
+
+class UrlHandler : public KMail::Interface::BodyPartURLHandler
+{
+ public:
+ UrlHandler()
+ {
+ kdDebug() << "UrlHandler() (iCalendar)" << endl;
+ }
+
+ Incidence* icalToString( const QString& iCal ) const
+ {
+ CalendarLocal calendar( KPimPrefs::timezone() ) ;
+ ICalFormat format;
+ ScheduleMessage *message =
+ format.parseScheduleMessage( &calendar, iCal );
+ if ( !message )
+ //TODO: Error message?
+ return 0;
+ return dynamic_cast<Incidence*>( message->event() );
+ }
+
+
+ Attendee *findMyself( Incidence* incidence, const QString& receiver ) const
+ {
+ Attendee::List attendees = incidence->attendees();
+ Attendee::List::ConstIterator it;
+ Attendee* myself = 0;
+ // Find myself. There will always be all attendees listed, even if
+ // only I need to answer it.
+ for ( it = attendees.begin(); it != attendees.end(); ++it ) {
+ // match only the email part, not the name
+ if( KPIM::compareEmail( (*it)->email(), receiver, false ) ) {
+ // We are the current one, and even the receiver, note
+ // this and quit searching.
+ myself = (*it);
+ break;
+ }
+ }
+ return myself;
+ }
+
+ static bool heuristicalRSVP( Incidence *incidence )
+ {
+ bool rsvp = true; // better send superfluously than not at all
+ Attendee::List attendees = incidence->attendees();
+ Attendee::List::ConstIterator it;
+ for ( it = attendees.begin(); it != attendees.end(); ++it ) {
+ if ( it == attendees.begin() ) {
+ rsvp = (*it)->RSVP(); // use what the first one has
+ } else {
+ if ( (*it)->RSVP() != rsvp ) {
+ rsvp = true; // they differ, default
+ break;
+ }
+ }
+ }
+ return rsvp;
+ }
+
+ static Attendee::Role heuristicalRole( Incidence *incidence )
+ {
+ Attendee::Role role = Attendee::OptParticipant;
+ Attendee::List attendees = incidence->attendees();
+ Attendee::List::ConstIterator it;
+ for ( it = attendees.begin(); it != attendees.end(); ++it ) {
+ if ( it == attendees.begin() ) {
+ role = (*it)->role(); // use what the first one has
+ } else {
+ if ( (*it)->role() != role ) {
+ role = Attendee::OptParticipant; // they differ, default
+ break;
+ }
+ }
+ }
+ return role;
+
+ }
+
+ Attendee* setStatusOnMyself( Incidence* incidence, Attendee* myself,
+ Attendee::PartStat status, const QString &receiver ) const
+ {
+ Attendee* newMyself = 0;
+ QString name;
+ QString email;
+ KPIM::getNameAndMail( receiver, name, email );
+ if ( name.isEmpty() && myself ) name = myself->name();
+ if ( email.isEmpty()&& myself ) email = myself->email();
+ Q_ASSERT( !email.isEmpty() ); // delivery must be possible
+ newMyself = new Attendee( name,
+ email,
+ true, // RSVP, otherwise we would not be here
+ status,
+ myself ? myself->role() : heuristicalRole( incidence ),
+ myself ? myself->uid() : QString::null );
+ if ( myself ) {
+ newMyself->setDelegate( myself->delegate() );
+ newMyself->setDelegator( myself->delegator() );
+ }
+
+ // Make sure only ourselves is in the event
+ incidence->clearAttendees();
+ if( newMyself )
+ incidence->addAttendee( newMyself );
+ return newMyself;
+ }
+
+ enum MailType {
+ Answer,
+ Delegation,
+ Forward,
+ DeclineCounter
+ };
+
+ bool mail( Incidence* incidence, KMail::Callback& callback,
+ Attendee::PartStat status,
+ Scheduler::Method method = Scheduler::Reply,
+ const QString &to = QString::null, MailType type = Answer ) const
+ {
+ ICalFormat format;
+ format.setTimeZone( KPimPrefs::timezone(), false );
+ QString msg = format.createScheduleMessage( incidence, method );
+ QString summary = incidence->summary();
+ if ( summary.isEmpty() )
+ summary = i18n( "Incidence with no summary" );
+ QString subject;
+ switch ( type ) {
+ case Answer:
+ subject = i18n( "Answer: %1" ).arg( summary );
+ break;
+ case Delegation:
+ subject = i18n( "Delegated: %1" ).arg( summary );
+ break;
+ case Forward:
+ subject = i18n( "Forwarded: %1" ).arg( summary );
+ break;
+ case DeclineCounter:
+ // ### string freeze
+ //subject = i18n( "Declined Counter Proposal: %1" ).arg( summary );
+ subject = i18n( "Answer: %1" ).arg( summary );
+ break;
+ }
+
+ QString recv = to;
+ if ( recv.isEmpty() )
+ recv = incidence->organizer().fullName();
+ QString statusString = directoryForStatus( status ); //it happens to return the right strings
+ return callback.mailICal( recv, msg, subject, statusString, type != Forward );
+ }
+
+ void ensureKorganizerRunning() const
+ {
+ QString error;
+ QCString dcopService;
+ int result = KDCOPServiceStarter::self()->findServiceFor( "DCOP/Organizer", QString::null, QString::null, &error, &dcopService );
+ if ( result == 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;
+ }
+
+ // We don't do anything with it, we just need it to be running so that it handles
+ // the incoming directory.
+ }
+ else
+ kdWarning() << "Couldn't start DCOP/Organizer: " << dcopService << " " << error << endl;
+ }
+
+ bool saveFile( const QString& receiver, const QString& iCal,
+ const QString& type ) const
+ {
+ KTempFile file( locateLocal( "data", "korganizer/income." + type + '/',
+ true ) );
+ QTextStream* ts = file.textStream();
+ if ( !ts ) {
+ KMessageBox::error( 0, i18n("Could not save file to KOrganizer") );
+ return false;
+ }
+ ts->setEncoding( QTextStream::UnicodeUTF8 );
+ (*ts) << receiver << '\n' << iCal;
+ file.close();
+
+ // Now ensure that korganizer is running; otherwise start it, to prevent surprises
+ // (https://intevation.de/roundup/kolab/issue758)
+ ensureKorganizerRunning();
+
+ return true;
+ }
+
+ bool handleInvitation( const QString& iCal, Attendee::PartStat status,
+ KMail::Callback &callback ) const
+ {
+ bool ok = true;
+ const QString receiver = callback.receiver();
+
+ if ( receiver.isEmpty() )
+ // Must be some error. Still return true though, since we did handle it
+ return true;
+
+ // get comment for tentative acceptance
+ Incidence* incidence = icalToString( iCal );
+
+ if ( callback.askForComment( status ) ) {
+ bool ok = false;
+ QString comment = KInputDialog::getMultiLineText( i18n("Reaction to Invitation"),
+ i18n("Comment:"), QString(), &ok );
+ if ( !ok )
+ return true;
+ if ( !comment.isEmpty() )
+ incidence->addComment( comment );
+ }
+
+ // First, save it for KOrganizer to handle
+ QString dir = directoryForStatus( status );
+ if ( dir.isEmpty() )
+ return true; // unknown status
+ if ( status != Attendee::Delegated ) // we do that below for delegated incidences
+ saveFile( receiver, iCal, dir );
+
+ QString delegateString;
+ bool delegatorRSVP = false;
+ if ( status == Attendee::Delegated ) {
+ DelegateSelector dlg;
+ if ( dlg.exec() == QDialog::Rejected )
+ return true;
+ delegateString = dlg.delegate();
+ delegatorRSVP = dlg.rsvp();
+ if ( delegateString.isEmpty() )
+ return true;
+ if ( KPIM::compareEmail( delegateString, incidence->organizer().email(), false ) ) {
+ KMessageBox::sorry( 0, i18n("Delegation to organizer is not possible.") );
+ return true;
+ }
+ }
+
+ if( !incidence ) return false;
+ Attendee *myself = findMyself( incidence, receiver );
+
+ // find our delegator, we need to inform him as well
+ QString delegator;
+ if ( myself && !myself->delegator().isEmpty() ) {
+ Attendee::List attendees = incidence->attendees();
+ for ( Attendee::List::ConstIterator it = attendees.constBegin(); it != attendees.constEnd(); ++it ) {
+ if( KPIM::compareEmail( (*it)->fullName(), myself->delegator(), false ) && (*it)->status() == Attendee::Delegated ) {
+ delegator = (*it)->fullName();
+ delegatorRSVP = (*it)->RSVP();
+ break;
+ }
+ }
+ }
+
+ if ( ( myself && myself->RSVP() ) || heuristicalRSVP( incidence ) ) {
+ Attendee* newMyself = setStatusOnMyself( incidence, myself, status, receiver );
+ if ( newMyself && status == Attendee::Delegated ) {
+ newMyself->setDelegate( delegateString );
+ newMyself->setRSVP( delegatorRSVP );
+ }
+ ok = mail( incidence, callback, status );
+
+ // check if we need to inform our delegator about this as well
+ if ( newMyself && (status == Attendee::Accepted || status == Attendee::Declined)
+ && !delegator.isEmpty() ) {
+ if ( delegatorRSVP || status == Attendee::Declined )
+ ok = mail( incidence, callback, status, Scheduler::Reply, delegator );
+ }
+
+ } else if ( !myself && (status != Attendee::Declined) ) {
+ // forwarded invitation
+ Attendee* newMyself = 0;
+ QString name;
+ QString email;
+ KPIM::getNameAndMail( receiver, name, email );
+ if ( !email.isEmpty() ) {
+ newMyself = new Attendee( name,
+ email,
+ true, // RSVP, otherwise we would not be here
+ status,
+ heuristicalRole( incidence ),
+ QString::null );
+ incidence->clearAttendees();
+ incidence->addAttendee( newMyself );
+ ok = mail( incidence, callback, status, Scheduler::Reply );
+ }
+ } else {
+ if ( callback.deleteInvitationAfterReply() )
+ ( new KMDeleteMsgCommand( callback.getMsg()->getMsgSerNum() ) )->start();
+ }
+ delete incidence;
+
+ // create invitation for the delegate (same as the original invitation
+ // with the delegate as additional attendee), we also use that for updating
+ // our calendar
+ if ( status == Attendee::Delegated ) {
+ incidence = icalToString( iCal );
+ myself = findMyself( incidence, receiver );
+ myself->setStatus( status );
+ myself->setDelegate( delegateString );
+ QString name, email;
+ KPIM::getNameAndMail( delegateString, name, email );
+ Attendee *delegate = new Attendee( name, email, true );
+ delegate->setDelegator( receiver );
+ incidence->addAttendee( delegate );
+
+ ICalFormat format;
+ format.setTimeZone( KPimPrefs::timezone(), false );
+ QString iCal = format.createScheduleMessage( incidence, Scheduler::Request );
+ saveFile( receiver, iCal, dir );
+
+ ok = mail( incidence, callback, status, Scheduler::Request, delegateString, Delegation );
+ }
+ return ok;
+ }
+
+ void showCalendar( const QDate &date ) const
+ {
+ ensureKorganizerRunning();
+ // raise korganizer part in kontact or the korganizer app
+ kapp->dcopClient()->send( "korganizer", "korganizer", "newInstance()", QByteArray() );
+ QByteArray arg;
+ QDataStream s( arg, IO_WriteOnly );
+ s << QString( "kontact_korganizerplugin" );
+ kapp->dcopClient()->send( "kontact", "KontactIface", "selectPlugin(QString)", arg );
+
+ KCalendarIface_stub *iface = new KCalendarIface_stub( kapp->dcopClient(), "korganizer", "CalendarIface" );
+ iface->showEventView();
+ iface->showDate( date );
+ delete iface;
+ }
+
+ bool handleIgnore( const QString&, KMail::Callback& c ) const
+ {
+ // simply move the message to trash
+ ( new KMDeleteMsgCommand( c.getMsg()->getMsgSerNum() ) )->start();
+ return true;
+ }
+
+ bool handleDeclineCounter( const QString &iCal, KMail::Callback &callback ) const
+ {
+ const QString receiver = callback.receiver();
+ if ( receiver.isEmpty() )
+ return true;
+ Incidence* incidence = icalToString( iCal );
+ if ( callback.askForComment( Attendee::Declined ) ) {
+ bool ok = false;
+ // ### string freeze
+ QString comment = KInputDialog::getMultiLineText( i18n("Reaction to Invitation") /* i18n("Decline Counter Proposal") */,
+ i18n("Comment:"), QString(), &ok );
+ if ( !ok )
+ return true;
+ if ( !comment.isEmpty() )
+ incidence->addComment( comment );
+ }
+ return mail( incidence, callback, Attendee::NeedsAction, Scheduler::Declinecounter,
+ callback.sender(), DeclineCounter );
+ }
+
+ bool counterProposal( const QString &iCal, KMail::Callback &callback ) const
+ {
+ const QString receiver = callback.receiver();
+ if ( receiver.isEmpty() )
+ return true;
+ saveFile( receiver, iCal, "counter" );
+ // Don't delete the invitation here in any case, if the counter proposal
+ // is declined you might need it again.
+ return true;
+ }
+
+ bool handleClick( KMail::Interface::BodyPart *part,
+ const QString &path, KMail::Callback& c ) const
+ {
+ QString iCal;
+ /* If the bodypart does not have a charset specified, we need to fall back to
+ utf8, not the KMail fallback encoding, so get the contents as binary and decode
+ explicitely. */
+ if ( part->contentTypeParameter( "charset").isEmpty() ) {
+ const QByteArray &ba = part->asBinary();
+ iCal = QString::fromUtf8(ba);
+ } else {
+ iCal = part->asText();
+ }
+ bool result = false;
+ if ( path == "accept" )
+ result = handleInvitation( iCal, Attendee::Accepted, c );
+ if ( path == "accept_conditionally" )
+ result = handleInvitation( iCal, Attendee::Tentative, c );
+ if ( path == "counter" )
+ result = counterProposal( iCal, c );
+ if ( path == "ignore" )
+ result = handleIgnore( iCal, c );
+ if ( path == "decline" )
+ result = handleInvitation( iCal, Attendee::Declined, c );
+ if ( path == "decline_counter" ) {
+ result = handleDeclineCounter( iCal, c );
+ }
+ if ( path == "delegate" )
+ result = handleInvitation( iCal, Attendee::Delegated, c );
+ if ( path == "forward" ) {
+ Incidence* incidence = icalToString( iCal );
+ AttendeeSelector dlg;
+ if ( dlg.exec() == QDialog::Rejected )
+ return true;
+ QString fwdTo = dlg.attendees().join( ", " );
+ if ( fwdTo.isEmpty() )
+ return true;
+ result = mail( incidence, c, Attendee::Delegated /*### right ?*/,
+ Scheduler::Request, fwdTo, Forward );
+ }
+ if ( path == "check_calendar" ) {
+ Incidence* incidence = icalToString( iCal );
+ showCalendar( incidence->dtStart().date() );
+ }
+ if ( path == "reply" || path == "cancel" || path == "accept_counter" ) {
+ // These should just be saved with their type as the dir
+ const QString p = (path == "accept_counter" ? QString("reply") : path);
+ if ( saveFile( "Receiver Not Searched", iCal, p ) ) {
+ if ( c.deleteInvitationAfterReply() )
+ ( new KMDeleteMsgCommand( c.getMsg()->getMsgSerNum() ) )->start();
+ result = true;
+ }
+ }
+ if ( result )
+ c.closeIfSecondaryWindow();
+ return result;
+ }
+
+ bool handleContextMenuRequest( KMail::Interface::BodyPart *,
+ const QString &,
+ const QPoint & ) const
+ {
+ return false;
+ }
+
+ QString statusBarMessage( KMail::Interface::BodyPart *,
+ const QString &path ) const
+ {
+ if ( !path.isEmpty() ) {
+ if ( path == "accept" )
+ return i18n("Accept incidence");
+ if ( path == "accept_conditionally" )
+ return i18n( "Accept incidence conditionally" );
+// ### string freeze
+// if ( path == "accept_counter" )
+// return i18n( "Accept counter proposal" );
+ if ( path == "counter" )
+ return i18n( "Create a counter proposal..." );
+ if ( path == "ignore" )
+ return i18n( "Throw mail away" );
+ if ( path == "decline" )
+ return i18n( "Decline incidence" );
+// ### string freeze
+// if ( path == "decline_counter" )
+// return i18n( "Decline counter proposal" );
+ if ( path == "check_calendar" )
+ return i18n("Check my calendar..." );
+ if ( path == "reply" )
+ return i18n( "Enter incidence into my calendar" );
+ if ( path == "delegate" )
+ return i18n( "Delegate incidence" );
+ if ( path == "forward" )
+ return i18n( "Forward incidence" );
+ if ( path == "cancel" )
+ return i18n( "Remove incidence from my calendar" );
+ }
+
+ return QString::null;
+ }
+};
+
+class Plugin : public KMail::Interface::BodyPartFormatterPlugin
+{
+ public:
+ const KMail::Interface::BodyPartFormatter *bodyPartFormatter( int idx ) const
+ {
+ if ( idx == 0 ) return new Formatter();
+ else return 0;
+ }
+
+ const char *type( int idx ) const
+ {
+ if ( idx == 0 ) return "text";
+ else return 0;
+ }
+
+ const char *subtype( int idx ) const
+ {
+ if ( idx == 0 ) return "calendar";
+ else return 0;
+ }
+
+ const KMail::Interface::BodyPartURLHandler * urlHandler( int idx ) const
+ {
+ if ( idx == 0 ) return new UrlHandler();
+ else return 0;
+ }
+};
+
+}
+
+extern "C"
+KDE_EXPORT KMail::Interface::BodyPartFormatterPlugin *
+libkmail_bodypartformatter_text_calendar_create_bodypart_formatter_plugin()
+{
+ KGlobal::locale()->insertCatalogue( "kmail_text_calendar_plugin" );
+ return new Plugin();
+}
diff --git a/plugins/kmail/bodypartformatter/text_calendar.desktop b/plugins/kmail/bodypartformatter/text_calendar.desktop
new file mode 100644
index 000000000..cf2443d30
--- /dev/null
+++ b/plugins/kmail/bodypartformatter/text_calendar.desktop
@@ -0,0 +1,86 @@
+[Misc]
+Name=Application Octetstream
+Name[af]=Application/Octet-stream
+Name[ca]=Aplicació Octetstream
+Name[cs]=Aplikace octetstream
+Name[da]=Program oktetstrøm
+Name[eo]=Aplikaĵa Bitokfluo
+Name[es]=Aplicación en flujo de octetos
+Name[eu]=Aplikazioa/zortzikote-jarioa
+Name[fa]=Octetstream کاربرد
+Name[fi]=Octetstream-sovellus
+Name[fr]=Application (flux d'octets)
+Name[fy]=Applikaasje octetstream
+Name[gl]=Aplicación Octetstream
+Name[hu]=Alkalmazás-adatfolyam
+Name[ja]=アプリケーション オクテット ストリーム
+Name[ka]=რვადინებიანი პროგრამა
+Name[kk]=Қолданбаның бинарлы ағымы
+Name[km]=Octetstream កម្មវិធី
+Name[ms]=Aliran Oktet Aplikasi
+Name[nb]=Program Octetstrøm
+Name[ne]=अक्टेस्ट्रिम अनुप्रयोग
+Name[nl]=Applicatie octetstroom
+Name[nn]=Oktettstraum frå program
+Name[pl]=Dane binarne
+Name[pt]=Aplicação Sequência Binária
+Name[pt_BR]=Aplicativo Octetstream
+Name[ru]=Бинарный поток приложения
+Name[sl]=Programski Octetstream
+Name[sr]=Апликација Octetstream
+Name[sr@Latn]=Aplikacija Octetstream
+Name[sv]=Program-oktettström
+Name[ta]=பயன்பாட்டு எண்மம்
+Name[tg]=Миқдори зиёди бинарии барномот
+Name[tr]=Uygulama Sekizli Akışı
+Name[zh_CN]=应用程序 Octetstream
+Comment=A bodypart formatter plugin for text/calendar
+Comment[af]='n Data (boodskap lyf) formateer inprop module vir 'text/calendar'
+Comment[bg]=Редактор с поддръжка на форматиране за текст/календар
+Comment[bs]=Dodatak za formatiranje tijela poruke za text/calendar
+Comment[ca]=Un endollable formatador del cos per a text/calendar
+Comment[cs]=Formátovač těla emailu pro typ text/calendar
+Comment[da]=Et bodypart formateringsplugin for text/calendar
+Comment[de]=Ein Textinhalt-Formatierer für text/calendar
+Comment[el]=Ένα πρόσθετο μορφοποιητή για text/calendar
+Comment[es]=Un accesorio de formato para el cuerpo de text/calendar
+Comment[et]=Põhiosa vormindamisplugin (MIME tüübile text/calendar)
+Comment[eu]=Testu/egutegientzako gorputz-zati formateatzaile bat
+Comment[fa]=یک وصلۀ قالب دهندۀ جزء بدنه برای متن/تقویم
+Comment[fi]=Muokkausliitännäinen text/calendar-muodolle
+Comment[fr]=Module de formatage pour le text/calendar
+Comment[fy]=In opmaakplugin foar text/calendar
+Comment[gl]=Unha extensión para formatear o corpo do texto/calendario
+Comment[hu]=Formázómodul text/calendar adatfolyamok kezeléséhez
+Comment[is]=Sniðmátstól fyrir text/calendar
+Comment[it]=Un plugin per formattare il corpo di text/calendar
+Comment[ja]=text/calendar 用の Bodypart フォーマッタ プラグイン
+Comment[ka]=კომპონენტური დამფორმატებელი მოდული text/calendar
+Comment[kk]=Text/calendar бөлімін пішімдеу модулі
+Comment[km]=កម្មវិធី​ជំនួយ​កម្មវិធី​ធ្វើ​ទ្រង់ទ្រាយ​ផ្នែក​តួ សម្រាប់​អត្ថបទ/ប្រតិទិន
+Comment[lt]=text/calendar formatavimo priedas
+Comment[ms]=Plugin pemformat bahagian isi untuk teks/kalendar
+Comment[nb]=En formaterer for meldingstekster i tekst/kalender
+Comment[nds]=En Hööftdeel-Formateermoduul för text/calendar
+Comment[ne]=पाठ/क्यालेन्डरका लागि मुख्यभाग ढाँचाबद्ध गर्ने प्लगइन
+Comment[nl]=Een opmaakplugin voor text/calendar
+Comment[nn]=Eit programtillegg for meldingstekstformatering i tekst/kalender
+Comment[pl]=Wtyczka formatująca dla typu text/calendar
+Comment[pt]=Um 'plugin' de formatação para text/calendar
+Comment[pt_BR]=Um plug-in formatador de componente para o tipo text/calendar
+Comment[ru]=Форматирование text/calendar
+Comment[sk]=Modul pre formátovanie tela pre text/calendar
+Comment[sl]=Oblikovalni vstavek za text/calendar
+Comment[sr]=Прикључак за форматитање тела за text/calendar
+Comment[sr@Latn]=Priključak za formatitanje tela za text/calendar
+Comment[sv]=Ett insticksprogram för brevtextformatering av text/calendar
+Comment[ta]=உரை அல்லது நாள்காட்டிகான அங்க அமைப்பு சொருகி
+Comment[tg]=Модули ба андозадарории text/calendar
+Comment[tr]=text/calendar için bir gövde biçimleyici eklentisi
+Comment[uk]=Втулок форматування для text/calendar
+Comment[zh_CN]=text/calendar 的格式化插件
+Comment[zh_TW]=text/calendar 格式化外掛程式
+
+[Plugin]
+Type=text/calendar
+X-KDE-Library=libkmail_bodypartformatter_text_calendar
diff --git a/plugins/kmail/bodypartformatter/text_vcard.cpp b/plugins/kmail/bodypartformatter/text_vcard.cpp
new file mode 100644
index 000000000..577560e5c
--- /dev/null
+++ b/plugins/kmail/bodypartformatter/text_vcard.cpp
@@ -0,0 +1,167 @@
+/* -*- mode: C++; c-file-style: "gnu" -*-
+ text_vcard.cpp
+
+ This file is part of KMail, the KDE mail client.
+ Copyright (c) 2004 Till Adam <adam@kde.org>
+
+ KMail is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ KMail is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#include <qurl.h>
+
+#include <kapplication.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kstringhandler.h>
+#include <kglobalsettings.h>
+#include <kiconloader.h>
+
+#include <kaddrbook.h>
+
+#include "interfaces/bodypartformatter.h"
+#include "interfaces/bodypart.h"
+using KMail::Interface::BodyPart;
+#include "interfaces/bodyparturlhandler.h"
+#include "khtmlparthtmlwriter.h"
+#include <kimproxy.h>
+
+#include <kabc/vcardconverter.h>
+#include <kabc/addressee.h>
+using KABC::VCardConverter;
+using KABC::Addressee;
+
+#include "addresseeview.h"
+using KPIM::AddresseeView;
+
+#include <kdepimmacros.h>
+
+namespace {
+
+ class Formatter : public KMail::Interface::BodyPartFormatter {
+ public:
+ Formatter() {
+ // disabled pending resolution of how to share static objects when dlopening libraries
+ //mKIMProxy = ::KIMProxy::instance( kapp->dcopClient() );
+ }
+
+ Result format( BodyPart *bodyPart, KMail::HtmlWriter *writer ) const {
+
+ if ( !writer ) return AsIcon;
+
+ VCardConverter vcc;
+ const QString vCard = bodyPart->asText();
+ if ( vCard.isEmpty() ) return AsIcon;
+ Addressee::List al = vcc.parseVCards( vCard );
+ if ( al.empty() ) return AsIcon;
+
+ writer->queue (
+ "<div align=\"center\"><h2>" +
+ i18n( "Attached business cards" ) +
+ "</h2></div>"
+ );
+
+ QValueListIterator<KABC::Addressee> it = al.begin();
+ int count = 0;
+ for ( ; it != al.end(); ++it ) {
+ KABC::Addressee a = (*it);
+ if ( a.isEmpty() ) return AsIcon;
+
+ QString contact = AddresseeView::vCardAsHTML( a, 0L, AddresseeView::NoLinks, false, AddresseeView::DefaultFields );
+ writer->queue( contact );
+
+ QString addToLinkText = i18n( "[Add this contact to the addressbook]" );
+ QString op = QString::fromLatin1( "addToAddressBook:%1" ).arg( count );
+ writer->queue(
+ "<div align=\"center\"><a href=\"" +
+ bodyPart->makeLink( op ) +
+ "\">" +
+ addToLinkText +
+ "</a></div><br><br>" );
+ count++;
+ }
+
+ return Ok;
+ }
+ private:
+ //::KIMProxy *mKIMProxy;
+};
+
+ class UrlHandler : public KMail::Interface::BodyPartURLHandler {
+ public:
+ bool handleClick( BodyPart * bodyPart, const QString & path,
+ KMail::Callback& ) const {
+
+ const QString vCard = bodyPart->asText();
+ if ( vCard.isEmpty() ) return true;
+ VCardConverter vcc;
+ Addressee::List al = vcc.parseVCards( vCard );
+ int index = path.right( path.length() - path.findRev( ":" ) - 1 ).toInt();
+ if ( index == -1 ) return true;
+ KABC::Addressee a = al[index];
+ if ( a.isEmpty() ) return true;
+ KAddrBookExternal::addVCard( a, 0 );
+ return true;
+ }
+
+ bool handleContextMenuRequest( BodyPart *, const QString &, const QPoint & ) const {
+ return false;
+ }
+
+ QString statusBarMessage( BodyPart *, const QString & ) const {
+ return i18n("Add this contact to the address book.");
+ }
+ };
+
+ class Plugin : public KMail::Interface::BodyPartFormatterPlugin {
+ public:
+ const KMail::Interface::BodyPartFormatter * bodyPartFormatter( int idx ) const {
+ return validIndex( idx ) ? new Formatter() : 0 ;
+ }
+ const char * type( int idx ) const {
+ return validIndex( idx ) ? "text" : 0 ;
+ }
+ const char * subtype( int idx ) const {
+ return idx == 0 ? "x-vcard" : idx == 1 ? "vcard" : 0 ;
+ }
+
+ const KMail::Interface::BodyPartURLHandler * urlHandler( int idx ) const {
+ return validIndex( idx ) ? new UrlHandler() : 0 ;
+ }
+ private:
+ bool validIndex( int idx ) const {
+ return ( idx >= 0 && idx <= 1 );
+ }
+ };
+
+}
+
+extern "C"
+KDE_EXPORT KMail::Interface::BodyPartFormatterPlugin *
+libkmail_bodypartformatter_text_vcard_create_bodypart_formatter_plugin() {
+ KGlobal::locale()->insertCatalogue( "kmail_text_vcard_plugin" );
+ return new Plugin();
+}
+
diff --git a/plugins/kmail/bodypartformatter/text_vcard.desktop b/plugins/kmail/bodypartformatter/text_vcard.desktop
new file mode 100644
index 000000000..206d8462a
--- /dev/null
+++ b/plugins/kmail/bodypartformatter/text_vcard.desktop
@@ -0,0 +1,87 @@
+[Misc]
+Name=Application Octetstream
+Name[af]=Application/Octet-stream
+Name[ca]=Aplicació Octetstream
+Name[cs]=Aplikace octetstream
+Name[da]=Program oktetstrøm
+Name[eo]=Aplikaĵa Bitokfluo
+Name[es]=Aplicación en flujo de octetos
+Name[eu]=Aplikazioa/zortzikote-jarioa
+Name[fa]=Octetstream کاربرد
+Name[fi]=Octetstream-sovellus
+Name[fr]=Application (flux d'octets)
+Name[fy]=Applikaasje octetstream
+Name[gl]=Aplicación Octetstream
+Name[hu]=Alkalmazás-adatfolyam
+Name[ja]=アプリケーション オクテット ストリーム
+Name[ka]=რვადინებიანი პროგრამა
+Name[kk]=Қолданбаның бинарлы ағымы
+Name[km]=Octetstream កម្មវិធី
+Name[ms]=Aliran Oktet Aplikasi
+Name[nb]=Program Octetstrøm
+Name[ne]=अक्टेस्ट्रिम अनुप्रयोग
+Name[nl]=Applicatie octetstroom
+Name[nn]=Oktettstraum frå program
+Name[pl]=Dane binarne
+Name[pt]=Aplicação Sequência Binária
+Name[pt_BR]=Aplicativo Octetstream
+Name[ru]=Бинарный поток приложения
+Name[sl]=Programski Octetstream
+Name[sr]=Апликација Octetstream
+Name[sr@Latn]=Aplikacija Octetstream
+Name[sv]=Program-oktettström
+Name[ta]=பயன்பாட்டு எண்மம்
+Name[tg]=Миқдори зиёди бинарии барномот
+Name[tr]=Uygulama Sekizli Akışı
+Name[zh_CN]=应用程序 Octetstream
+Comment=A bodypart formatter plugin for text/vcard
+Comment[af]='n Data (boodskap lyf) formateer inprop module vir 'text/vcard'
+Comment[bg]=Редактор с поддръжка на форматиране за текст/vcard
+Comment[br]=Arload tresañ Xfig
+Comment[bs]=Dodatak za formatiranje tijela poruke za text/vcard
+Comment[ca]=Un endollable formatador del cos per a text/vcard
+Comment[cs]=Formátovač těla emailu pro typ text/vcard
+Comment[da]=Et bodypart formateringsplugin for text/vcard
+Comment[de]=Ein Textinhalt-Formatierer für text/vcard
+Comment[el]=Ένα πρόσθετο μορφοποιητή για text/vcard
+Comment[es]=Un accesorio de formato para el cuerpo de text/vcard
+Comment[et]=Põhiosa vormindamisplugin (MIME tüübile text/vcard)
+Comment[eu]=Testu/vcard-en gorputz-zati formateatzaile bat
+Comment[fa]=یک وصلۀ قالب دهندۀ جزء بدنه برای متن/vcard
+Comment[fi]=Muokkausliitännäinen text/vcard-muodolle
+Comment[fr]=Un formateur de partie de corps pour text/vcard
+Comment[fy]=In opmaakplugin foar text/vcard
+Comment[gl]=Unha extensión para formatear o corpo do texto/vcard
+Comment[hu]=Formázómodul text/vcard adatfolyamok kezeléséhez
+Comment[is]=Sniðmátstól fyrir text/vcard
+Comment[it]=Un plugin per formattare il corpo di text/vcard
+Comment[ja]=text/vcard 用の Bodypart フォーマッタ プラグイン
+Comment[ka]=კომპონენტური დამფორმატებელი მოდული text/vcard
+Comment[kk]=Text/vcard бөлімін пішімдеу модулі
+Comment[km]=កម្មវិធី​ជំនួយ​កម្មវិធី​ធ្វើ​ទ្រង់ទ្រាយ​ផ្នែក​តួ សម្រាប់​អត្ថបទ/vcard
+Comment[lt]= Teksto/vcard formatavimo priedas
+Comment[ms]=Plugin pemformat bahagian isi untuk teks/vcard
+Comment[nb]=Et programtillegg for text/vcard for brødtekst-formatering
+Comment[nds]=En Hööftdeel-Formateermoduul för text/vcard
+Comment[ne]=पाठ/भिकार्ड का लागि मुख्यभाग ढाँचाबद्ध गर्ने प्लगइन
+Comment[nl]=Een opmaakplugin voor text/vcard
+Comment[nn]=Eit programtillegg for brødtekstformatering i tekst/vCard
+Comment[pl]=Wtyczka formatująca dla typu text/vcard
+Comment[pt]=Um 'plugin' de formatação para text/vcard
+Comment[pt_BR]=Um plug-in formatador de componente para o tipo text/vcard
+Comment[ru]=Форматирование text/vcard
+Comment[sk]=Modul pre formátovanie tela pre text/vcard
+Comment[sl]=Oblikovalni vstavek za text/vcard
+Comment[sr]=Прикључак за форматитање тела за text/vcard
+Comment[sr@Latn]=Priključak za formatitanje tela za text/vcard
+Comment[sv]=Ett insticksprogram för brevtextformatering av text/vcard
+Comment[ta]=உரை அல்லது விஅட்டைக்கான அங்க அமைப்பு சொருகி
+Comment[tg]=Модули ба андозадарории text/vcard
+Comment[tr]=text/vcard için bir gövde biçimleyici eklentisi
+Comment[uk]=Втулок форматування для text/vcard
+Comment[zh_CN]=text/vcard 的格式化插件
+Comment[zh_TW]=text/vCard 格式化外掛程式
+
+[Plugin]
+Type=text/x-vcard
+X-KDE-Library=libkmail_bodypartformatter_text_vcard
diff --git a/plugins/kmail/bodypartformatter/text_xdiff.cpp b/plugins/kmail/bodypartformatter/text_xdiff.cpp
new file mode 100644
index 000000000..ada37be80
--- /dev/null
+++ b/plugins/kmail/bodypartformatter/text_xdiff.cpp
@@ -0,0 +1,152 @@
+/*
+ This file is part of kdepim.
+
+ Copyright (c) 2004 Till Adam <adam@kde.org>
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#include <interfaces/bodypartformatter.h>
+#include <interfaces/bodypart.h>
+#include <interfaces/bodyparturlhandler.h>
+#include <khtmlparthtmlwriter.h>
+
+#include <kmail/callback.h>
+#include <kmail/kmmessage.h>
+
+#include <kglobal.h>
+#include <klocale.h>
+#include <kstringhandler.h>
+#include <kglobalsettings.h>
+#include <kiconloader.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <kapplication.h>
+
+#include <qurl.h>
+#include <qfile.h>
+#include <qdir.h>
+#include <qstylesheet.h>
+
+namespace {
+
+ // TODO: Show filename header to make it possible to save the patch.
+ // FIXME: The box should only be as wide as necessary.
+
+ class Formatter : public KMail::Interface::BodyPartFormatter {
+ public:
+ Result format( KMail::Interface::BodyPart *bodyPart, KMail::HtmlWriter *writer ) const {
+
+ if ( !writer ) return Ok;
+
+ if ( bodyPart->defaultDisplay() == KMail::Interface::BodyPart::AsIcon )
+ return AsIcon;
+
+ const QString diff = bodyPart->asText();
+ if ( diff.isEmpty() ) return AsIcon;
+
+
+
+ QString addedLineStyle = QString::fromLatin1(
+ "style=\""
+ "color: green;\"");
+ QString fileAddStyle( "style=\"font-weight: bold; "
+ "color: green; \"" );
+
+ QString removedLineStyle = QString::fromLatin1(
+ "style=\""
+ "color: red;\"");
+ QString fileRemoveStyle( "style=\"font-weight: bold; "
+ "color: red ;\"" );
+
+ QString tableStyle = QString::fromLatin1(
+ "style=\""
+ "text-align: -khtml-auto; "
+ "border: solid black 1px; "
+ "padding: 0.5em; "
+ "margin: 0em;\"");
+
+ QString sepStyle( "style=\"color: black; font-weight: bold;\"" );
+ QString chunkStyle( "style=\"color: blue;\"" );
+
+ QString html = "<br><div align=\"center\">";
+ html += "<pre " + tableStyle + ">";
+
+ QStringList lines = QStringList::split( '\n', diff, true );
+ for ( QStringList::Iterator it = lines.begin(); it != lines.end(); ++it ) {
+ QString line( QStyleSheet::escape( *it ) );
+ QString style;
+ if ( line.length() > 0 ) {
+ if ( line.startsWith( "+++" ) ) {
+ style = fileAddStyle;
+ } else if ( line.startsWith( "---" ) ) {
+ style = fileRemoveStyle;
+ } else if ( line.startsWith( "+" ) || line.startsWith( ">" ) ) {
+ style = addedLineStyle;
+ } else if ( line.startsWith( "-" ) || line.startsWith( "<" ) ) {
+ style = removedLineStyle;
+ } else if ( line.startsWith( "==") ) {
+ style = sepStyle;
+ } else if ( line.startsWith( "@@" ) ) {
+ style = chunkStyle;
+ } else {
+ style = "";
+ }
+ }
+ html += "<span " + style + ">" + line + "</span><br/>";
+ }
+
+ html += "</pre></div>";
+ //qDebug( "%s", html.latin1() );
+ writer->queue( html );
+
+ return Ok;
+ }
+ };
+
+ class Plugin : public KMail::Interface::BodyPartFormatterPlugin {
+ public:
+ const KMail::Interface::BodyPartFormatter * bodyPartFormatter( int idx ) const {
+ return idx == 0 ? new Formatter() : 0 ;
+ }
+ const char * type( int idx ) const {
+ return idx == 0 ? "text" : 0 ;
+ }
+ const char * subtype( int idx ) const {
+ return idx == 0 ? "x-diff" : 0 ;
+ }
+
+ const KMail::Interface::BodyPartURLHandler * urlHandler( int ) const { return 0; }
+ };
+
+}
+
+extern "C"
+KMail::Interface::BodyPartFormatterPlugin *
+libkmail_bodypartformatter_text_xdiff_create_bodypart_formatter_plugin() {
+ return new Plugin();
+}
diff --git a/plugins/kmail/bodypartformatter/text_xdiff.desktop b/plugins/kmail/bodypartformatter/text_xdiff.desktop
new file mode 100644
index 000000000..a2c05f9cc
--- /dev/null
+++ b/plugins/kmail/bodypartformatter/text_xdiff.desktop
@@ -0,0 +1,83 @@
+[Misc]
+Name=Application Octetstream
+Name[af]=Application/Octet-stream
+Name[ca]=Aplicació Octetstream
+Name[cs]=Aplikace octetstream
+Name[da]=Program oktetstrøm
+Name[eo]=Aplikaĵa Bitokfluo
+Name[es]=Aplicación en flujo de octetos
+Name[eu]=Aplikazioa/zortzikote-jarioa
+Name[fa]=Octetstream کاربرد
+Name[fi]=Octetstream-sovellus
+Name[fr]=Application (flux d'octets)
+Name[fy]=Applikaasje octetstream
+Name[gl]=Aplicación Octetstream
+Name[hu]=Alkalmazás-adatfolyam
+Name[ja]=アプリケーション オクテット ストリーム
+Name[ka]=რვადინებიანი პროგრამა
+Name[kk]=Қолданбаның бинарлы ағымы
+Name[km]=Octetstream កម្មវិធី
+Name[ms]=Aliran Oktet Aplikasi
+Name[nb]=Program Octetstrøm
+Name[ne]=अक्टेस्ट्रिम अनुप्रयोग
+Name[nl]=Applicatie octetstroom
+Name[nn]=Oktettstraum frå program
+Name[pl]=Dane binarne
+Name[pt]=Aplicação Sequência Binária
+Name[pt_BR]=Aplicativo Octetstream
+Name[ru]=Бинарный поток приложения
+Name[sl]=Programski Octetstream
+Name[sr]=Апликација Octetstream
+Name[sr@Latn]=Aplikacija Octetstream
+Name[sv]=Program-oktettström
+Name[ta]=பயன்பாட்டு எண்மம்
+Name[tg]=Миқдори зиёди бинарии барномот
+Name[tr]=Uygulama Sekizli Akışı
+Name[zh_CN]=应用程序 Octetstream
+Comment=A bodypart formatter plugin for text/x-diff
+Comment[af]='n Data (boodskap lyf) formateer inprop module vir 'text/x-diff'
+Comment[bg]=Редактор с поддръжка на форматиране за текст/x-diff
+Comment[ca]=Un endollable formatador del cos per a text/x-diff
+Comment[cs]=Formátovač těla emailu pro typ text/x-diff
+Comment[da]=Et bodypart formateringsplugin for text/x-diff
+Comment[de]=Ein Bodypart-Formatierungsmodul für text/x-diff
+Comment[el]=Ένα πρόσθετο μορφοποιητή για text/x-diff
+Comment[es]=Una extensión de formato para el cuerpo de text/x-diff
+Comment[et]=Põhiosa vormindamisplugin (MIME tüübile text/x-diff)
+Comment[eu]=Testu/x-diff-en gorputz-zati formateatzaile bat
+Comment[fa]=یک وصلۀ قالب دهندۀ جزء بدنه برای متن/x-diff
+Comment[fi]=Muokkausliitännäinen text/x-diff-muodolle
+Comment[fr]=Un formateur de partie de corps pour text/x-diff
+Comment[fy]=In opmaakplugin foar text/x-diff
+Comment[gl]=Unha extensión para formatear o corpo do texto/x-diff
+Comment[hu]=Formázómodul text/x-diff adatok kezeléséhez
+Comment[is]=Sniðmátstól fyrir text/x-diff
+Comment[it]=Un plugin per formattare il corpo di text/x-diff
+Comment[ja]=text/x-diff 用の bodypart フォーマッタプラグイン
+Comment[ka]=კომპონენტური დამფორმატებელი მოდული text/x-diff
+Comment[kk]=Text/x-diff бөлімін пішімдеу модулі
+Comment[km]=កម្មវិធី​ជំនួយ​កម្មវិធី​ធ្វើ​ទ្រង់ទ្រាយ​ផ្នែក​តួ សម្រាប់​អត្ថបទ/x-diff
+Comment[lt]=text/x-diff formatavimo priedas
+Comment[ms]=Plugin pemformat bahagian untuk teks/x-diff
+Comment[nb]=Et programtillegg for text/x-diff for brødtekst-formatering
+Comment[nds]=En Hööftdeel-Formateermoduul för text/x-diff
+Comment[ne]=पाठ/x-diff का लागि मुख्यभाग ढाँचाबद्ध गर्ने प्लगइन
+Comment[nl]=Een opmaakplugin voor text/x-diff
+Comment[nn]=Eit programtilllegg for text/x-diff for brødtekstformatering
+Comment[pl]=Wtyczka formatująca dla text/x-diff
+Comment[pt]=Um 'plugin' de formatação para text/x-diff
+Comment[pt_BR]=Um plug-in formatador de componente para o tipo text/x-diff
+Comment[ru]=Форматирование text/x-diff
+Comment[sk]=Modul pre formátovanie tela pre text/x-diff
+Comment[sl]=Oblikovalni vstavek za text/x-diff
+Comment[sr]=Прикључак за форматитање тела за text/x-diff
+Comment[sr@Latn]=Priključak za formatitanje tela za text/x-diff
+Comment[sv]=Ett insticksprogram för brevtextformatering av text/x-diff
+Comment[ta]=text/x-diffக்கான ஒரு பகுதி வடிவமைப்பான் சொருகுப்பொருள்
+Comment[tr]=text/x-diff için bir gövde biçimleyici eklentisi
+Comment[uk]=Втулок форматування для text/x-diff
+Comment[zh_CN]=text/x-diff 的格式化插件
+Comment[zh_TW]=text/x-diff 格式化外掛程式
+[Plugin]
+Type=text/x-diff
+X-KDE-Library=libkmail_bodypartformatter_text_xdiff
diff --git a/plugins/kmail/bodypartformatter/ui_attendeeselector.ui b/plugins/kmail/bodypartformatter/ui_attendeeselector.ui
new file mode 100644
index 000000000..06873fe5e
--- /dev/null
+++ b/plugins/kmail/bodypartformatter/ui_attendeeselector.ui
@@ -0,0 +1,88 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>AttendeeSelectorWidget</class>
+<author>Volker Krause &lt;vkrause@kde.org&gt;</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>AttendeeSelectorWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>333</width>
+ <height>200</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KPushButton" row="0" column="1">
+ <property name="name">
+ <cstring>addButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Add</string>
+ </property>
+ </widget>
+ <widget class="KPushButton" row="1" column="1">
+ <property name="name">
+ <cstring>removeButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Remove</string>
+ </property>
+ </widget>
+ <widget class="KListBox" row="1" column="0" rowspan="2" colspan="1">
+ <property name="name">
+ <cstring>attendeeList</cstring>
+ </property>
+ </widget>
+ <widget class="KPIM::AddresseeLineEdit" row="0" column="0">
+ <property name="name">
+ <cstring>attendeeEdit</cstring>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>250</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ <spacer row="2" column="1">
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>140</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+</widget>
+<includes>
+ <include location="global" impldecl="in declaration">libkdepim/addresseelineedit.h</include>
+</includes>
+<layoutdefaults spacing="6" margin="0"/>
+<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/>
+<includehints>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>klistbox.h</includehint>
+ <includehint>libkdepim/addresseelineedit.h</includehint>
+</includehints>
+</UI>