• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.8.5 API Reference
  • KDE Home
  • Contact Us
 

KAlarm Library

alarmtext.cpp
00001 /*
00002  *  alarmtext.cpp  -  text/email alarm text conversion
00003  *  This file is part of kalarmcal library, which provides access to KAlarm
00004  *  calendar data.
00005  *  Copyright © 2004,2005,2007-2012 by David Jarvie <djarvie@kde.org>
00006  *
00007  *  This library is free software; you can redistribute it and/or modify
00008  *  it under the terms of the GNU Library General Public License as published
00009  *  by the Free Software Foundation; either version 2 of the License, or (at
00010  *  your option) any later version.
00011  *
00012  *  This library is distributed in the hope that it will be useful, but WITHOUT
00013  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00015  *  License for more details.
00016  *
00017  *  You should have received a copy of the GNU Library General Public License
00018  *  along with this library; see the file COPYING.LIB.  If not, write to the
00019  *  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00020  *  MA 02110-1301, USA.
00021  */
00022 
00023 #include "alarmtext.h"
00024 
00025 #include "kaevent.h"
00026 
00027 #ifdef KALARMCAL_USE_KRESOURCES
00028 #include <kcal/todo.h>
00029 #endif
00030 #include <klocale.h>
00031 #include <kglobal.h>
00032 #include <QStringList>
00033 
00034 namespace KAlarmCal
00035 {
00036 
00037 class AlarmText::Private
00038 {
00039     public:
00040         enum Type { None, Email, Script, Todo };
00041         QString        displayText() const;
00042         void           clear();
00043         static void    initialise();
00044         static void    setUpTranslations();
00045         static int     emailHeaderCount(const QStringList&);
00046         static QString todoTitle(const QString& text);
00047 
00048         static QString mFromPrefix;       // translated header prefixes
00049         static QString mToPrefix;
00050         static QString mCcPrefix;
00051         static QString mDatePrefix;
00052         static QString mSubjectPrefix;
00053         static QString mTitlePrefix;
00054         static QString mLocnPrefix;
00055         static QString mDuePrefix;
00056         static QString mFromPrefixEn;     // untranslated header prefixes
00057         static QString mToPrefixEn;
00058         static QString mCcPrefixEn;
00059         static QString mDatePrefixEn;
00060         static QString mSubjectPrefixEn;
00061         static bool    mInitialised;
00062 
00063         QString        mBody, mFrom, mTo, mCc, mTime, mSubject;
00064         unsigned long  mKMailSerialNum;   // if email, message's KMail serial number, else 0
00065         Type           mType;
00066         bool           mIsEmail;
00067 };
00068 
00069 QString AlarmText::Private::mFromPrefix;
00070 QString AlarmText::Private::mToPrefix;
00071 QString AlarmText::Private::mCcPrefix;
00072 QString AlarmText::Private::mDatePrefix;
00073 QString AlarmText::Private::mSubjectPrefix;
00074 QString AlarmText::Private::mTitlePrefix;
00075 QString AlarmText::Private::mLocnPrefix;
00076 QString AlarmText::Private::mDuePrefix;
00077 QString AlarmText::Private::mFromPrefixEn;
00078 QString AlarmText::Private::mToPrefixEn;
00079 QString AlarmText::Private::mCcPrefixEn;
00080 QString AlarmText::Private::mDatePrefixEn;
00081 QString AlarmText::Private::mSubjectPrefixEn;
00082 bool    AlarmText::Private::mInitialised = false;
00083 
00084 void AlarmText::Private::initialise()
00085 {
00086     if (!mInitialised)
00087     {
00088         mInitialised     = true;
00089         mFromPrefixEn    = QLatin1String("From:");
00090         mToPrefixEn      = QLatin1String("To:");
00091         mCcPrefixEn      = QLatin1String("Cc:");
00092         mDatePrefixEn    = QLatin1String("Date:");
00093         mSubjectPrefixEn = QLatin1String("Subject:");
00094     }
00095 }
00096 
00097 AlarmText::AlarmText(const QString& text)
00098     : d(new Private)
00099 {
00100     Private::initialise();
00101     setText(text);
00102 }
00103 
00104 AlarmText::AlarmText(const AlarmText& other)
00105     : d(new Private(*other.d))
00106 {
00107 }
00108 
00109 AlarmText::~AlarmText()
00110 {
00111     delete d;
00112 }
00113 
00114 AlarmText& AlarmText::operator=(const AlarmText& other)
00115 {
00116     if (&other != this)
00117         *d = *other.d;
00118     return *this;
00119 }
00120 
00121 void AlarmText::setText(const QString& text)
00122 {
00123     d->clear();
00124     d->mBody = text;
00125     if (text.startsWith(QLatin1String("#!")))
00126         d->mType = Private::Script;
00127 }
00128 
00129 void AlarmText::setScript(const QString& text)   
00130 {
00131     setText(text);
00132     d->mType = Private::Script;
00133 }
00134 
00135 void AlarmText::setEmail(const QString& to, const QString& from, const QString& cc, const QString& time,
00136                          const QString& subject, const QString& body, unsigned long kmailSerialNumber)
00137 {
00138     d->clear();
00139     d->mType           = Private::Email;
00140     d->mTo             = to;
00141     d->mFrom           = from;
00142     d->mCc             = cc;
00143     d->mTime           = time;
00144     d->mSubject        = subject;
00145     d->mBody           = body;
00146     d->mKMailSerialNum = kmailSerialNumber;
00147 }
00148 
00149 #ifndef KALARMCAL_USE_KRESOURCES
00150 void AlarmText::setTodo(const KCalCore::Todo::Ptr& todo)
00151 #else
00152 void AlarmText::setTodo(const KCal::Todo* todo)
00153 #endif
00154 {
00155     d->clear();
00156     d->mType    = Private::Todo;
00157     d->mSubject = todo->summary();
00158     d->mBody    = todo->description();
00159     d->mTo      = todo->location();
00160     if (todo->hasDueDate())
00161     {
00162         KDateTime due = todo->dtDue(false);   // fetch the next due date
00163         if (todo->hasStartDate()  &&  todo->dtStart() != due)
00164         {
00165             d->mTime = todo->allDay() ? KGlobal::locale()->formatDate(due.date(), KLocale::ShortDate)
00166                                       : KGlobal::locale()->formatDateTime(due.dateTime());
00167         }
00168     }
00169 }
00170 
00171 /******************************************************************************
00172 * Return the text for a text message alarm, in display format.
00173 */
00174 QString AlarmText::displayText() const
00175 {
00176     return d->displayText();
00177 }
00178 
00179 QString AlarmText::Private::displayText() const
00180 {
00181     QString text;
00182     switch (mType)
00183     {
00184         case Email:
00185             // Format the email into a text alarm
00186             setUpTranslations();
00187             text = mFromPrefix + '\t' + mFrom + '\n';
00188             text += mToPrefix + '\t' + mTo + '\n';
00189             if (!mCc.isEmpty())
00190                 text += mCcPrefix + '\t' + mCc + '\n';
00191             if (!mTime.isEmpty())
00192                 text += mDatePrefix + '\t' + mTime + '\n';
00193             text += mSubjectPrefix + '\t' + mSubject;
00194             if (!mBody.isEmpty())
00195             {
00196                 text += "\n\n";
00197                 text += mBody;
00198             }
00199             break;
00200         case Todo:
00201             // Format the todo into a text alarm
00202             setUpTranslations();
00203             if (!mSubject.isEmpty())
00204                 text = mTitlePrefix + '\t' + mSubject + '\n';
00205             if (!mTo.isEmpty())
00206                 text += mLocnPrefix + '\t' + mTo + '\n';
00207             if (!mTime.isEmpty())
00208                 text += mDuePrefix + '\t' + mTime + '\n';
00209             if (!mBody.isEmpty())
00210             {
00211                 if (!text.isEmpty())
00212                     text += '\n';
00213                 text += mBody;
00214             }
00215             break;
00216         default:
00217             break;
00218     }
00219     return !text.isEmpty() ? text : mBody;
00220 }
00221 
00222 QString AlarmText::to() const
00223 {
00224     return (d->mType == Private::Email) ? d->mTo : QString();
00225 }
00226 
00227 QString AlarmText::from() const
00228 {
00229     return (d->mType == Private::Email) ? d->mFrom : QString();
00230 }
00231 
00232 QString AlarmText::cc() const
00233 {
00234     return (d->mType == Private::Email) ? d->mCc : QString();
00235 }
00236 
00237 QString AlarmText::time() const
00238 {
00239     return (d->mType == Private::Email) ? d->mTime : QString();
00240 }
00241 
00242 QString AlarmText::subject() const
00243 {
00244     return (d->mType == Private::Email) ? d->mSubject : QString();
00245 }
00246 
00247 QString AlarmText::body() const
00248 {
00249     return (d->mType == Private::Email) ? d->mBody : QString();
00250 }
00251 
00252 QString AlarmText::summary() const
00253 {
00254     return (d->mType == Private::Todo) ? d->mSubject : QString();
00255 }
00256 
00257 QString AlarmText::location() const
00258 {
00259     return (d->mType == Private::Todo) ? d->mTo : QString();
00260 }
00261 
00262 QString AlarmText::due() const
00263 {
00264     return (d->mType == Private::Todo) ? d->mTime : QString();
00265 }
00266 
00267 QString AlarmText::description() const
00268 {
00269     return (d->mType == Private::Todo) ? d->mBody : QString();
00270 }
00271 
00272 /******************************************************************************
00273 * Return whether there is any text.
00274 */
00275 bool AlarmText::isEmpty() const
00276 {
00277     if (!d->mBody.isEmpty())
00278         return false;
00279     if (d->mType != Private::Email)
00280         return true;
00281     return d->mFrom.isEmpty() && d->mTo.isEmpty() && d->mCc.isEmpty() && d->mTime.isEmpty() && d->mSubject.isEmpty();
00282 }
00283 
00284 bool AlarmText::isEmail() const            
00285 {
00286     return d->mType == Private::Email;
00287 }
00288 
00289 bool AlarmText::isScript() const           
00290 {
00291     return d->mType == Private::Script;
00292 }
00293 
00294 bool AlarmText::isTodo() const             
00295 {
00296     return d->mType == Private::Todo;
00297 }
00298 
00299 unsigned long AlarmText::kmailSerialNumber() const  
00300 {
00301     return d->mKMailSerialNum;
00302 }
00303 
00304 /******************************************************************************
00305 * Return the alarm summary text for either single line or tooltip display.
00306 * The maximum number of line returned is determined by 'maxLines'.
00307 * If 'truncated' is non-null, it will be set true if the text returned has been
00308 * truncated, other than to strip a trailing newline.
00309 */
00310 QString AlarmText::summary(const KAEvent& event, int maxLines, bool* truncated)
00311 {
00312     static const QRegExp localfile("^file:/+");
00313     QString text;
00314     switch (event.actionSubType())
00315     {
00316         case KAEvent::AUDIO:
00317             text = event.audioFile();
00318             if (localfile.indexIn(text) >= 0)
00319                 text = text.mid(localfile.matchedLength() - 1);
00320             break;
00321         case KAEvent::EMAIL:
00322             text = event.emailSubject();
00323             break;
00324         case KAEvent::COMMAND:
00325             text = event.cleanText();
00326             if (localfile.indexIn(text) >= 0)
00327                 text = text.mid(localfile.matchedLength() - 1);
00328             break;
00329         case KAEvent::FILE:
00330             text = event.cleanText();
00331             break;
00332         case KAEvent::MESSAGE:
00333         {
00334             text = event.cleanText();
00335             // If the message is the text of an email, return its headers or just subject line
00336             QString subject = emailHeaders(text, (maxLines <= 1));
00337             if (!subject.isNull())
00338             {
00339                 if (truncated)
00340                     *truncated = true;
00341                 return subject;
00342             }
00343             if (maxLines == 1)
00344             {
00345                 // If the message is the text of a todo, return either the
00346                 // title/description or the whole text.
00347                 subject = Private::todoTitle(text);
00348                 if (!subject.isEmpty())
00349                 {
00350                     if (truncated)
00351                         *truncated = true;
00352                     return subject;
00353                 }
00354             }
00355             break;
00356         }
00357     }
00358     if (truncated)
00359         *truncated = false;
00360     if (text.count('\n') < maxLines)
00361         return text;
00362     int newline = -1;
00363     for (int i = 0;  i < maxLines;  ++i)
00364     {
00365         newline = text.indexOf('\n', newline + 1);
00366         if (newline < 0)
00367             return text;       // not truncated after all !?!
00368     }
00369     if (newline == static_cast<int>(text.length()) - 1)
00370         return text.left(newline);    // text ends in newline
00371     if (truncated)
00372         *truncated = true;
00373     return text.left(newline + (maxLines <= 1 ? 0 : 1)) + QLatin1String("...");
00374 }
00375 
00376 /******************************************************************************
00377 * Check whether a text is an email.
00378 */
00379 bool AlarmText::checkIfEmail(const QString& text)
00380 {
00381     QStringList lines = text.split('\n', QString::SkipEmptyParts);
00382     return Private::emailHeaderCount(lines);
00383 }
00384 
00385 /******************************************************************************
00386 * Check whether a text is an email, and if so return its headers or optionally
00387 * only its subject line.
00388 * Reply = headers/subject line, or QString() if not the text of an email.
00389 */
00390 QString AlarmText::emailHeaders(const QString& text, bool subjectOnly)
00391 {
00392     QStringList lines = text.split('\n', QString::SkipEmptyParts);
00393     int n = Private::emailHeaderCount(lines);
00394     if (!n)
00395         return QString();
00396     if (subjectOnly)
00397         return lines[n-1].mid(Private::mSubjectPrefix.length()).trimmed();
00398     QString h = lines[0];
00399     for (int i = 1;  i < n;  ++i)
00400     {
00401         h += '\n';
00402         h += lines[i];
00403     }
00404     return h;
00405 }
00406 
00407 /******************************************************************************
00408 * Translate an alarm calendar text to a display text.
00409 * Translation is needed for email texts, since the alarm calendar stores
00410 * untranslated email prefixes.
00411 * 'email' is set to indicate whether it is an email text.
00412 */
00413 QString AlarmText::fromCalendarText(const QString& text, bool& email)
00414 {
00415     Private::initialise();
00416     QStringList lines = text.split('\n', QString::SkipEmptyParts);
00417     int maxn = lines.count();
00418     if (maxn >= 4
00419     &&  lines[0].startsWith(Private::mFromPrefixEn)
00420     &&  lines[1].startsWith(Private::mToPrefixEn))
00421     {
00422         int n = 2;
00423         if (lines[2].startsWith(Private::mCcPrefixEn))
00424             ++n;
00425         if (maxn > n + 1
00426         &&  lines[n].startsWith(Private::mDatePrefixEn)
00427         &&  lines[n+1].startsWith(Private::mSubjectPrefixEn))
00428         {
00429             Private::setUpTranslations();
00430             QString dispText;
00431             dispText = Private::mFromPrefix + lines[0].mid(Private::mFromPrefixEn.length()) + '\n';
00432             dispText += Private::mToPrefix + lines[1].mid(Private::mToPrefixEn.length()) + '\n';
00433             if (n == 3)
00434                 dispText += Private::mCcPrefix + lines[2].mid(Private::mCcPrefixEn.length()) + '\n';
00435             dispText += Private::mDatePrefix + lines[n].mid(Private::mDatePrefixEn.length()) + '\n';
00436             dispText += Private::mSubjectPrefix + lines[n+1].mid(Private::mSubjectPrefixEn.length());
00437             int i = text.indexOf(Private::mSubjectPrefixEn);
00438             i = text.indexOf('\n', i);
00439             if (i > 0)
00440                 dispText += text.mid(i);
00441             email = true;
00442             return dispText;
00443         }
00444     }
00445     email = false;
00446     return text;
00447 }
00448 
00449 /******************************************************************************
00450 * Return the text for a text message alarm, in alarm calendar format.
00451 * (The prefix strings are untranslated in the calendar.)
00452 */
00453 QString AlarmText::toCalendarText(const QString& text)
00454 {
00455     Private::setUpTranslations();
00456     QStringList lines = text.split('\n', QString::SkipEmptyParts);
00457     int maxn = lines.count();
00458     if (maxn >= 4
00459     &&  lines[0].startsWith(Private::mFromPrefix)
00460     &&  lines[1].startsWith(Private::mToPrefix))
00461     {
00462         int n = 2;
00463         if (lines[2].startsWith(Private::mCcPrefix))
00464             ++n;
00465         if (maxn > n + 1
00466         &&  lines[n].startsWith(Private::mDatePrefix)
00467         &&  lines[n+1].startsWith(Private::mSubjectPrefix))
00468         {
00469             // Format the email into a text alarm
00470             QString calText;
00471             calText = Private::mFromPrefixEn + lines[0].mid(Private::mFromPrefix.length()) + '\n';
00472             calText += Private::mToPrefixEn + lines[1].mid(Private::mToPrefix.length()) + '\n';
00473             if (n == 3)
00474                 calText += Private::mCcPrefixEn + lines[2].mid(Private::mCcPrefix.length()) + '\n';
00475             calText += Private::mDatePrefixEn + lines[n].mid(Private::mDatePrefix.length()) + '\n';
00476             calText += Private::mSubjectPrefixEn + lines[n+1].mid(Private::mSubjectPrefix.length());
00477             int i = text.indexOf(Private::mSubjectPrefix);
00478             i = text.indexOf('\n', i);
00479             if (i > 0)
00480                 calText += text.mid(i);
00481             return calText;
00482         }
00483     }
00484     return text;
00485 }
00486 
00487 void AlarmText::Private::clear()
00488 {
00489     mType = None;
00490     mBody.clear();
00491     mTo.clear();
00492     mFrom.clear();
00493     mCc.clear();
00494     mTime.clear();
00495     mSubject.clear();
00496     mKMailSerialNum = 0;
00497 }
00498 
00499 /******************************************************************************
00500 * Set up messages used by executeDropEvent() and emailHeaders().
00501 */
00502 void AlarmText::Private::setUpTranslations()
00503 {
00504     initialise();
00505     if (mFromPrefix.isNull())
00506     {
00507         mFromPrefix    = i18nc("@info/plain 'From' email address", "From:");
00508         mToPrefix      = i18nc("@info/plain Email addressee", "To:");
00509         mCcPrefix      = i18nc("@info/plain Copy-to in email headers", "Cc:");
00510         mDatePrefix    = i18nc("@info/plain", "Date:");
00511         mSubjectPrefix = i18nc("@info/plain Email subject", "Subject:");
00512         // Todo prefixes
00513         mTitlePrefix   = i18nc("@info/plain Todo calendar item's title field", "To-do:");
00514         mLocnPrefix    = i18nc("@info/plain Todo calendar item's location field", "Location:");
00515         mDuePrefix     = i18nc("@info/plain Todo calendar item's due date/time", "Due:");
00516     }
00517 }
00518 
00519 /******************************************************************************
00520 * Check whether a text is an email.
00521 * Reply = number of email header lines, or 0 if not an email.
00522 */
00523 int AlarmText::Private::emailHeaderCount(const QStringList& lines)
00524 {
00525     setUpTranslations();
00526     int maxn = lines.count();
00527     if (maxn >= 4
00528     &&  lines[0].startsWith(mFromPrefix)
00529     &&  lines[1].startsWith(mToPrefix))
00530     {
00531         int n = 2;
00532         if (lines[2].startsWith(mCcPrefix))
00533             ++n;
00534         if (maxn > n + 1
00535         &&  lines[n].startsWith(mDatePrefix)
00536         &&  lines[n+1].startsWith(mSubjectPrefix))
00537             return n+2;
00538     }
00539     return 0;
00540 }
00541 
00542 /******************************************************************************
00543 * Return the Todo title line, if the text is for a Todo.
00544 */
00545 QString AlarmText::Private::todoTitle(const QString& text)
00546 {
00547     setUpTranslations();
00548     QStringList lines = text.split('\n', QString::SkipEmptyParts);
00549     int n;
00550     for (n = 0;  n < lines.count() && lines[n].contains('\t');  ++n) ;
00551     if (!n  ||  n > 3)
00552         return QString();
00553     QString title;
00554     int i = 0;
00555     if (lines[i].startsWith(mTitlePrefix + '\t'))
00556     {
00557         title = lines[i].mid(mTitlePrefix.length()).trimmed();
00558         ++i;
00559     }
00560     if (i < n  &&  lines[i].startsWith(mLocnPrefix + '\t'))
00561         ++i;
00562     if (i < n  &&  lines[i].startsWith(mDuePrefix + '\t'))
00563         ++i;
00564     if (i == n)
00565     {
00566         // It's a Todo text
00567         if (!title.isEmpty())
00568             return title;
00569         if (n < lines.count())
00570             return lines[n];
00571     }
00572     return QString();
00573 }
00574 
00575 } // namespace KAlarmCal
00576 
00577 // vim: et sw=4:
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Thu Aug 2 2012 15:26:19 by doxygen 1.7.5 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KAlarm Library

Skip menu "KAlarm Library"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • Related Pages

kdepimlibs-4.8.5 API Reference

Skip menu "kdepimlibs-4.8.5 API Reference"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal