[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 < aMsg->numBodyParts(); j++) {
...
if (!qstricmp(msgPart.typeStr(), "text")
&& !qstricmp(msgPart.subtypeStr(), "x-vcard")) {
...
vc = VCard::parseVCard(msgPart.body(), &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("<a href=\""+vcname+"\">"+i18n("[vCard]")+"</a>");
}
...
</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(), &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, &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(), &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