diff options
Diffstat (limited to 'plugins/kmail/bodypartformatter')
-rw-r--r-- | plugins/kmail/bodypartformatter/Makefile.am | 52 | ||||
-rw-r--r-- | plugins/kmail/bodypartformatter/attendeeselector.cpp | 82 | ||||
-rw-r--r-- | plugins/kmail/bodypartformatter/attendeeselector.h | 49 | ||||
-rw-r--r-- | plugins/kmail/bodypartformatter/delegateselector.cpp | 54 | ||||
-rw-r--r-- | plugins/kmail/bodypartformatter/delegateselector.h | 49 | ||||
-rw-r--r-- | plugins/kmail/bodypartformatter/text_calendar.cpp | 715 | ||||
-rw-r--r-- | plugins/kmail/bodypartformatter/text_calendar.desktop | 86 | ||||
-rw-r--r-- | plugins/kmail/bodypartformatter/text_vcard.cpp | 167 | ||||
-rw-r--r-- | plugins/kmail/bodypartformatter/text_vcard.desktop | 87 | ||||
-rw-r--r-- | plugins/kmail/bodypartformatter/text_xdiff.cpp | 152 | ||||
-rw-r--r-- | plugins/kmail/bodypartformatter/text_xdiff.desktop | 83 | ||||
-rw-r--r-- | plugins/kmail/bodypartformatter/ui_attendeeselector.ui | 88 |
12 files changed, 1664 insertions, 0 deletions
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 <vkrause@kde.org></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> |