[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kmail-devel
Subject:    Re: KMail is seriously in need of a code audit
From:       sybille.schumann-bjoern.wolf () t-online ! de (=?iso-8859-1?q?Bj=F6rn=20Wolf?=)
Date:       2001-07-31 21:25:52
[Download RAW message or body]

Hi,

On Saturday, 28. July 2001 01:38, Alan Chandler wrote:
> Seriously, to conduct a code audit you need to understand the bigger
> picture - have a view on the design understand what each functions purpose
> is and then review whether the code meets that purpose.  

Several days ago (15. July 2001) Marc Mutz added a DESIGN file to CVS. 
While reading this thread I wondered if I shouldn't write down what I learned 
from investigating the kmail sources. Maybe it helps to document "the bigger 
picture"

What I wrote covers only a very small area of KMail, namely vcard support, 
and - worse - covers only parts of that. But anyway, it maybe helps others to 
understand easier what happens with vcards in KMail.

If you think that this kind of information is helpful I could continue and 
put down some words on KMail's addressbook support.

Regards
Björn


["DESIGN-vcard.html" (text/html)]

<html>
<body>
<h1>
KMail VCard Support
</h1>

KMail currently supports:
<ul>
<li>
displaying vcard attachments in a separate popup
</li>
</ul>

For KDE 2.3, support is planned for ;-)
<ul>
<li>
adding vcards to kaddessbook
</li>
<li>
pretty formatting of vcard attachments
</li>
</ul>

<h2>
Components
</h2>

<ul>
<li>
a vcard parser (vcard.h/.cpp)
</li>
<li>
a separate dialog to display vcards (kmdisplayvcard.h/.cpp)
</li>
<li>
vcard specific code in the message reader (kmreaderwin.h/.cpp)
</li>
</ul>


<h2>
How it works
</h2>

<h3>
Parsing vCards
</h3>

The main class is `VCard´. Every VCard object represents one single
vcard.  VCards can be constructed directly (via the VCard() constructor)
but im KMail code they are always constructed by the static
VCard::parseVCard method.

<blockquote><pre>
      #include "vcard.h"
      ...
      VCard *vc = VCard::parseVCard(filename);
</pre></blockquote>

<h3>
Displaying vCards
</h3>

To display a vcard, one has to construct a KMDisplayVCard-Dialog, passing
a constructed VCard object as an argument.
<blockquote><pre>
      vcdlg = new KMDisplayVCard(vc);
      kernel->kbp()->idle();
      vcdlg->show();
</pre></blockquote></blockquote>
Because the dialog is non-modal, the vcard is destructed on destruction of the dialog.

<h3>
VCards in the Message Reader
</h3>

VCards are ordinary attachments to e-mails of MIME type "text/x-vcard".
Therefore - from the user's point of view - it is easy to SEND vcards to others
by attaching a .vcf file.
<p>
The message reader deals with vcard attachments in the following manner

<ol>
  <li>the KMail-Reader checks the MIME type of ALL attachments. If one of them has
   the MIME type "text/x-vcard" it adds an anchor with the text "[vcard]" to the
   sender´s address, cf.
   <a href="#KMReaderWin-writeMsgHeader">KMReaderWin::writeMsgHeader()</a>.<p>
     The URL of the anchor begins with `part:´ and refers to the vcard attachment<p>
     If further checks (by parsing the vcard attachment) if the attachment contains
   a valid vcard
  </li>
  <li>If the user clicks onto that `part:' anchor, this anchor emits a signal which is
   connected to the slot `<a href="#KMReaderWin-slotAtmOpen">slotAtmOpen()</a>'.
   This slot checks if the current msgpart
   is a vcard (compares its MIME type to "text/x-vcard" again) and, if so, opens a
   KMDisplayVCard dialog.<p>
     The same happens if the Icon which is representing the VCard attachment is
   clicked on.
  </li>
  <li>Similar code is executed if the user decides to `view...' the vcard
    (<a href="#KMReaderWin-atmView">atmView()</a>)
  </li>
</ol>



<h2>
VCard Parser
</h2>

KMail has its own, native C++ parser for VCards; it does not make use of
the versit VCard/VCalender classes, which are used elsewhere (by
KOrganizer, for example).

<h3>
The <code>VCard</code> Class
</h3>

The main vcard class is `VCard'. Every VCard object represents a visiting card
with a lot of attributes to a person.<p>
The usual way to construct a VCard object is by parsing it from a file (or from a
message part):
<blockquote><pre>
      #include "vcard.h"
      ...
      VCard *vc = VCard::parseVCard(filename);
</pre></blockquote>
On success, <var>vc</var> is different from <code>NULL</code> and refers to a
valid <code>VCard</code> object.<p>
It should be possible to construct a VCard from scratch (using the primitives
VCard::addLine() and VCard::addQualifiedLine(). However, vcards are not
created this way in KMail.<p>

<h3>
Querying Data from a <code>VCard</code>
</h3>
Generally spoken, VCard data is organized by keywords and, optionally, qualifiers.
For example, a telephone number can be just `the' telephone number of the person,
or it can be a special telephone number, let's say, that of the cellular.<p>
The methods getValue(...) and getValues(...) can be used to query data from a
<code>VCard</code> object, either by querying by keyword, e.g.
<blockquote><pre>
      QString s = vc->getValue(VCARD_TEL);
</pre></blockquote>
or by keyword <em>and</em> qualifier, e.g.
<blockquote><pre>
      QString s = vc->getValue(VCARD_TEL, VCARD_TEL_CELL);
</pre></blockquote>
There are also entrys (like name, address of the person) which do not consist
of one single text string, but rather consist of <em>a number</em> of strings.
These entries are then queried by the corresponding getValues(...) methods.<p>
Again, querying by keyword
<blockquote><pre>
      QStringList l = vc->getValues(VCARD_ADR);
</pre></blockquote>
or querying by keyword <em>and</em> qualifier, e.g.
<blockquote><pre>
      QStringList l = vc->getValues(VCARD_ADR, VCARD_ADR_HOME);
</pre></blockquote>
is possible.<p>
Unfortunately, one has to <em>know</em> which entry has to be queried by
<code>getValue()</code> and which one by <code>getValue<strong>s</strong>()</code>.
Have a look into <code>kmdisplayvcard.cpp</code> for concrete examples.


<h2>
Code fragments
</h2>

<h3>
kmreaderwin.cpp
</h3>

Context menu for attachments
<blockquote><a name="KMReaderWin-slotUrlPopup"><pre>
void <b>KMReaderWin::slotUrlPopup</b>(const QString &aUrl, const QPoint& aPos)
...
    menu->insertItem(i18n("Open..."), this, SLOT(slotAtmOpen()));
    menu->insertItem(i18n("Open with..."), this, SLOT(slotAtmOpenWith()));
    menu->insertItem(i18n("View..."), this, SLOT(slotAtmView()));
    menu->insertItem(i18n("Save as..."), this, SLOT(slotAtmSave()));
...
</pre></a></blockquote>

Is there any vcard attached?
<blockquote><a name="KMReaderWin-parseMsg"><pre>
void <b>KMReaderWin::parseMsg</b>(KMMessage* aMsg)
  ...
  for (int j = 0; j &lt; aMsg-&gt;numBodyParts(); j++) {
    ...
    if (!qstricmp(msgPart.typeStr(), "text")
       && !qstricmp(msgPart.subtypeStr(), "x-vcard")) {
        ...
        vc = VCard::parseVCard(msgPart.body(), &amp;vcerr);

        if (vc) {
          ...
          vcnum = j;
          break;
        }
    }
  }

  writeMsgHeader(vcnum);
  ...
</pre></a></blockquote>

Add "[vCard]" to the from-address
<blockquote><a name="KMReaderWin-writeMsgHeader"><pre>
void <b>KMReaderWin::writeMsgHeader</b>(int vcpartnum)
    ...
    if (vcpartnum >= 0) {
      mViewer->write("&lt;a href=\""+vcname+"\"&gt;"+i18n("[vCard]")+"&lt;/a&gt;");
    }
    ...
</pre></a></blockquote>

Opening a vCard...
<blockquote><a name="KMReaderWin-slotAtmOpen"><pre>
void <b>KMReaderWin::slotAtmOpen</b>()
{
  ...
  if (qstricmp(msgPart.typeStr(), "text") == 0) {
    if (qstricmp(msgPart.subtypeStr(), "x-vcard") == 0) {
      ...
      VCard *vc = VCard::parseVCard(msgPart.body(), &amp;vcerr);
      ...
      vcdlg = new KMDisplayVCard(vc);
      vcdlg->show();
      return;
    }
  }
</pre></a></blockquote>

...or viewing it (part 1)
<blockquote><a name="KMReaderWin-slotAtmView"><pre>
void <b>KMReaderWin::slotAtmView</b>()
{
  KMMessagePart msgPart;
  mMsg->bodyPart(mAtmCurrent, &amp;msgPart);
  QString pname = msgPart.fileName();
  if (pname.isEmpty()) pname=msgPart.name();
  if (pname.isEmpty()) pname=msgPart.contentDescription();
  if (pname.isEmpty()) pname="unnamed";
  // image Attachment is saved already
  atmView(this, &msgPart, htmlMail(), QString("%1part%2/%3").arg(mAttachDir).
    arg(mAtmCurrent+1).arg(pname), pname, mCodec);
}
</pre></a></blockquote>

(part 2)
<blockquote><a name="KMReaderWin-atmView"><pre>
void <b>KMReaderWin::atmView</b>(KMReaderWin* aReaderWin, KMMessagePart* aMsgPart,
    bool aHTML, const QString& aFileName, const QString& pname, QTextCodec *codec)
    ...
    if (qstricmp(aMsgPart->typeStr(), "text")==0) {
      if (qstricmp(aMsgPart->subtypeStr(), "x-vcard") == 0) {
        ...
        VCard *vc = VCard::parseVCard(aMsgPart->body(), &amp;vcerr);
        ...
        vcdlg = new KMDisplayVCard(vc);
        kernel->kbp()->idle();
        vcdlg->show();
        ...
</pre></a></blockquote>
</body>
</html>
_______________________________________________
Kmail Developers mailing list
Kmail@master.kde.org
http://master.kde.org/mailman/listinfo/kmail


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic