• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepim API Reference
  • KDE Home
  • Contact Us
 

knode

  • sources
  • kde-4.12
  • kdepim
  • knode
knarticlefactory.cpp
Go to the documentation of this file.
1 /*
2  KNode, the KDE newsreader
3  Copyright (c) 1999-2006 the KNode authors.
4  See file AUTHORS for details
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  You should have received a copy of the GNU General Public License
11  along with this program; if not, write to the Free Software Foundation,
12  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, US
13 */
14 
15 
16 #include "knarticlefactory.h"
17 
18 #include "knglobals.h"
19 #include "kngroupmanager.h"
20 #include "knaccountmanager.h"
21 #include "knfoldermanager.h"
22 #include "knarticlemanager.h"
23 #include "knfolder.h"
24 #include "kncomposer.h"
25 #include "knnntpaccount.h"
26 #include "mailsendjob.h"
27 #include "nntpjobs.h"
28 #include "utilities.h"
29 #include "resource.h"
30 #include "settings.h"
31 #include "utils/locale.h"
32 
33 #include <QByteArray>
34 #include <QList>
35 #include <QListWidget>
36 #include <KPIMIdentities/Identity>
37 #include <KPIMIdentities/IdentityManager>
38 #include <KPIMUtils/Email>
39 #include <QLabel>
40 #include <kiconloader.h>
41 #include <klocale.h>
42 #include <kmessagebox.h>
43 #include <kwindowsystem.h>
44 #include <ktoolinvocation.h>
45 #include <kvbox.h>
46 #include <mailtransport/transportmanager.h>
47 
48 
49 using namespace KNode;
50 using namespace KNode::Utilities;
51 using namespace MailTransport;
52 
53 KNArticleFactory::KNArticleFactory( QObject *parent )
54  : QObject( parent ), s_endErrDlg(0)
55 {
56 }
57 
58 
59 KNArticleFactory::~KNArticleFactory()
60 {
61  for ( QList<KNComposer*>::Iterator it = mCompList.begin(); it != mCompList.end(); ++it )
62  delete (*it);
63  delete s_endErrDlg;
64 }
65 
66 
67 void KNArticleFactory::createPosting( KNNntpAccount::Ptr a )
68 {
69  if(!a)
70  return;
71 
72  KNLocalArticle::Ptr art = newArticle( a, Locale::defaultCharset() );
73 
74  if(!art)
75  return;
76 
77  art->setServerId(a->id());
78  art->setDoPost(true);
79  art->setDoMail(false);
80 
81  KNComposer *c = new KNComposer( art, QString(), QString(), true, false, false, false );
82  mCompList.append( c );
83  connect(c, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*)));
84  c->show();
85 }
86 
87 
88 void KNArticleFactory::createPosting( KNGroup::Ptr g )
89 {
90  if(!g)
91  return;
92 
93  QByteArray chset = Locale::defaultCharset( g );
94  KNLocalArticle::Ptr art = newArticle( g, chset );
95 
96  if(!art)
97  return;
98 
99  art->setServerId(g->account()->id());
100  art->setDoPost(true);
101  art->setDoMail(false);
102  art->newsgroups()->fromUnicodeString(g->groupname(), art->defaultCharset());
103  KNComposer *c = new KNComposer( art, QString(), QString(), true, false, false, false );
104  mCompList.append( c );
105  connect(c, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*)));
106  c->show();
107 }
108 
109 
110 void KNArticleFactory::createReply( KNRemoteArticle::Ptr a, const QString &selectedText, bool post, bool mail )
111 {
112  if(!a)
113  return;
114 
115  KNGroup::Ptr g = boost::static_pointer_cast<KNGroup>( a->collection() );
116 
117  QByteArray chset;
118  if ( knGlobals.settings()->useOwnCharset() ) {
119  chset = Locale::defaultCharset( g );
120  } else {
121  chset = a->contentType()->charset();
122  }
123 
124  //create new article
125  KNLocalArticle::Ptr art = newArticle( g, chset, true, a );
126 
127  if(!art)
128  return;
129 
130  art->setServerId(g->account()->id());
131  art->setDoPost(post);
132  art->setDoMail(mail);
133 
134  //------------------------- <Headers> ----------------------------
135 
136  //subject
137  QString subject=a->subject()->asUnicodeString();
138  if ( subject.left(3).toUpper() != "RE:" )
139  subject.prepend("Re: ");
140  art->subject()->fromUnicodeString(subject, a->subject()->rfc2047Charset());
141 
142  //newsgroups
143  KMime::Headers::FollowUpTo *fup2=a->followUpTo(false);
144  if(fup2 && !fup2->isEmpty()) {
145  if( ( fup2->as7BitString(false).toUpper()=="POSTER" ) ) { //Followup-To: poster
146  if( post && // user wanted to reply by public posting?
147  // ask the user if she wants to ignore this F'up-To: poster
148  ( KMessageBox::Yes != KMessageBox::questionYesNo(knGlobals.topWidget,
149  i18n("The author has requested a reply by email instead\nof a followup to the newsgroup. (Followup-To: poster)\nDo you want to reply in public anyway?"), QString(), KGuiItem(i18n("Reply Public")), KGuiItem(i18n("Reply by Email"))) ))
150  {
151  art->setDoPost(false);
152  art->setDoMail(true);
153  }
154  art->newsgroups()->from7BitString(a->newsgroups()->as7BitString(false));
155  }
156  else
157  art->newsgroups()->from7BitString(fup2->as7BitString(false));
158  }
159  else
160  art->newsgroups()->from7BitString(a->newsgroups()->as7BitString(false));
161 
162  //To
163  KMime::Headers::ReplyTo *replyTo=a->replyTo(false);
164  KMime::Types::Mailbox address;
165  if(replyTo && !replyTo->isEmpty()) {
166  foreach( const KMime::Types::Mailbox &mbox, replyTo->mailboxes() ) {
167  art->to()->addAddress( mbox );
168  }
169  }
170  else {
171  KMime::Headers::From *from=a->from();
172  foreach( const KMime::Types::Mailbox &mbox, from->mailboxes() ) {
173  art->to()->addAddress( mbox );
174  }
175  }
176 
177  //References
178  KMime::Headers::References *references=a->references(false);
179  QByteArray refs;
180  if (references)
181  refs=references->as7BitString(false);
182  else
183  refs = "";
184 
185  art->references()->from7BitString(refs);
186  art->references()->appendIdentifier(a->messageID()->as7BitString(false));
187 
188  //Mail-Copies-To
189  bool authorDislikesMailCopies=false;
190  bool authorWantsMailCopies=false;
191  KMime::Headers::MailCopiesTo *mailCopiesTo=a->mailCopiesTo(false);
192 
193  if( mailCopiesTo && !mailCopiesTo->isEmpty() ) {
194  authorDislikesMailCopies = mailCopiesTo->neverCopy();
195  authorWantsMailCopies = mailCopiesTo->alwaysCopy();
196  if (authorWantsMailCopies) // warn the user
197  KMessageBox::information( knGlobals.topWidget, i18n("The author requested a mail copy of your reply. (Mail-Copies-To header)"),
198  QString(), "mailCopiesToWarning" );
199  if ( authorWantsMailCopies && !mailCopiesTo->mailboxes().isEmpty() ) {
200  art->to()->clear();
201  foreach ( const KMime::Types::Mailbox &mbox, mailCopiesTo->mailboxes() ) {
202  art->to()->addAddress( mbox );
203  }
204  }
205  }
206 
207  //------------------------- </Headers> ---------------------------
208 
209  //--------------------------- <Body> -----------------------------
210 
211  // attribution line
212  QString attribution = knGlobals.settings()->intro();
213  QString name( a->from()->displayNames().join( ", ") );
214  if ( name.isEmpty() && !a->from()->isEmpty() )
215  name = QString::fromLatin1( a->from()->addresses().first() );
216  attribution.replace(QRegExp("%NAME"),name);
217  if ( !a->from()->isEmpty() )
218  attribution.replace(QRegExp("%EMAIL"), QString::fromLatin1(a->from()->addresses().first()));
219  attribution.replace( QRegExp("%DATE"), KGlobal::locale()->formatDateTime(a->date()->dateTime().toLocalZone().dateTime(), KLocale::LongDate) );
220  QString msid = a->messageID()->identifier();
221  attribution.replace( QRegExp("%MSIDX"), msid );
222  attribution.replace( QRegExp("%MSID"), QLatin1Char('<') + msid + QLatin1Char('>') );
223  attribution.replace(QRegExp("%GROUP"),g->groupname());
224  attribution.replace(QRegExp("%L"),"\n");
225  attribution+="\n\n";
226 
227  QString quoted=attribution;
228  QString notRewraped;
229  QStringList text;
230  QStringList::Iterator line;
231  bool incSig = knGlobals.settings()->includeSignature();
232 
233  if (selectedText.isEmpty()) {
234  KMime::Content *tc = a->textContent();
235  if(tc)
236  text = tc->decodedText( true, knGlobals.settings()->removeTrailingNewlines() ).split( '\n' );
237  }
238  else
239  text = selectedText.split('\n');
240 
241  for(line=text.begin(); line!=text.end(); ++line) {
242  if(!incSig && (*line)=="-- ")
243  break;
244 
245  if ((*line)[0]=='>')
246  quoted += '>' + (*line) + '\n'; // second quote level without space
247  else
248  quoted += "> " +(*line) + '\n';
249  }
250 
251  if ( knGlobals.settings()->rewrap() ) { //rewrap original article
252 
253  notRewraped=quoted; // store the original text in here, the user can request it in the composer
254  quoted=attribution;
255 
256  quoted += KNHelper::rewrapStringList( text, knGlobals.settings()->maxLineLength(), '>', !incSig, false );
257  }
258 
259  //-------------------------- </Body> -----------------------------
260 
261  if ( art->doMail() && knGlobals.settings()->useExternalMailer() ) {
262  sendMailExternal(address.prettyAddress(), subject, quoted);
263  art->setDoMail(false);
264  if (!art->doPost()) {
265  return;
266  }
267  }
268 
269  //open composer
270  KNComposer *c=new KNComposer(art, quoted, notRewraped, true, authorDislikesMailCopies, authorWantsMailCopies);
271  mCompList.append( c );
272  connect(c, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*)));
273  c->show();
274 }
275 
276 
277 void KNArticleFactory::createForward( KNArticle::Ptr a )
278 {
279  if(!a)
280  return;
281 
282  KMime::Headers::ContentType *ct=a->contentType();
283  QByteArray chset;
284  bool incAtt = ( !knGlobals.settings()->useExternalMailer() &&
285  ct->isMultipart() && ct->isSubtype("mixed") &&
286  KMessageBox::Yes == KMessageBox::questionYesNo(knGlobals.topWidget,
287  i18n("This article contains attachments. Do you want them to be forwarded as well?"), QString(), KGuiItem(i18n("Forward")), KGuiItem(i18n("Do Not Forward")))
288  );
289 
290  if ( knGlobals.settings()->useOwnCharset() )
291  chset = Locale::defaultCharset();
292  else
293  chset = a->contentType()->charset();
294 
295  //create new article
296  KNLocalArticle::Ptr art = newArticle( knGlobals.groupManager()->currentGroup(), chset );
297  if(!art)
298  return;
299 
300  art->setDoPost(false);
301  art->setDoMail(true);
302 
303  //------------------------- <Headers> ----------------------------
304 
305  //subject
306  QString subject=("Fwd: "+a->subject()->asUnicodeString());
307  art->subject()->fromUnicodeString(subject, a->subject()->rfc2047Charset());
308 
309  //------------------------- </Headers> ---------------------------
310 
311  //--------------------------- <Body> -----------------------------
312 
313  QString fwd = QString("\n--------------- %1\n\n").arg(i18n("Forwarded message (begin)"));
314 
315  fwd+=( i18n("Subject") + ": " + a->subject()->asUnicodeString() + '\n' );
316  fwd+=( i18n("From") + ": " + a->from()->asUnicodeString() + '\n' );
317  fwd+=( i18n("Date") + ": " + a->date()->asUnicodeString() + '\n' );
318  fwd+=( i18n("Newsgroup") + ": " + a->newsgroups()->asUnicodeString() + "\n\n" );
319 
320  KMime::Content *text=a->textContent();
321  if(text)
322  fwd += text->decodedText( false, false );
323 
324  fwd += QString("\n--------------- %1\n").arg(i18n("Forwarded message (end)"));
325 
326  //--------------------------- </Body> ----------------------------
327 
328 
329  //------------------------ <Attachments> -------------------------
330 
331  if(incAtt) {
332  KMime::Content::List al = a->attachments( false );
333  foreach ( KMime::Content *c, al )
334  art->addContent( new KMime::Content(c->head(), c->body()) );
335  }
336 
337  //------------------------ </Attachments> ------------------------
338 
339 
340  if ( knGlobals.settings()->useExternalMailer() ) {
341  sendMailExternal( QString(), subject, fwd );
342  return;
343  }
344 
345  //open composer
346  KNComposer *c = new KNComposer( art, fwd, QString(), true );
347  mCompList.append( c );
348  connect(c, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*)));
349  c->show();
350 }
351 
352 
353 void KNArticleFactory::createCancel( KNArticle::Ptr a )
354 {
355  if(!cancelAllowed(a))
356  return;
357 
358  if( KMessageBox::No == KMessageBox::questionYesNo( knGlobals.topWidget,
359  i18n("Do you really want to cancel this article?"), QString(), KGuiItem(i18n("Cancel Article")), KStandardGuiItem::cancel() ) )
360  return;
361 
362  bool sendNow;
363  switch (KMessageBox::warningYesNoCancel(knGlobals.topWidget, i18n("Do you want to send the cancel\nmessage now or later?"), i18n("Question"),KGuiItem(i18n("&Now")),KGuiItem(i18n("&Later")))) {
364  case KMessageBox::Yes : sendNow = true; break;
365  case KMessageBox::No : sendNow = false; break;
366  default : return;
367  }
368 
369  KNGroup::Ptr grp;
370  KNNntpAccount::Ptr nntp;
371 
372  if ( a->type() == KNArticle::ATremote )
373  nntp = boost::static_pointer_cast<KNGroup>( a->collection() )->account();
374  else {
375  if(!nntp)
376  nntp=knGlobals.accountManager()->first();
377  if(!nntp) {
378  KMessageBox::error(knGlobals.topWidget, i18n("You have no valid news accounts configured."));
379  return;
380  }
381  KNLocalArticle::Ptr la = boost::static_pointer_cast<KNLocalArticle>( a );
382  la->setCanceled(true);
383  la->updateListItem();
384  nntp=knGlobals.accountManager()->account(la->serverId());
385  }
386 
387  if ( !a->newsgroups()->isEmpty() )
388  grp = knGlobals.groupManager()->group(a->newsgroups()->groups().first(), nntp);
389 
390  KNLocalArticle::Ptr art = newArticle( grp, "us-ascii", false );
391 
392  if(!art)
393  return;
394 
395  //init
396  art->setDoPost(true);
397  art->setDoMail(false);
398 
399  //server
400  art->setServerId(nntp->id());
401 
402  //subject
403  KMime::Headers::MessageID *msgId=a->messageID();
404  QByteArray tmp;
405  tmp="cancel of "+msgId->as7BitString(false);
406  art->subject()->from7BitString(tmp);
407 
408  //newsgroups
409  art->newsgroups()->from7BitString(a->newsgroups()->as7BitString(false));
410 
411  //control
412  tmp="cancel "+msgId->as7BitString(false);
413  art->control()->from7BitString(tmp);
414 
415  //Lines
416  art->lines()->setNumberOfLines(1);
417 
418  //body
419  art->fromUnicodeString(QString::fromLatin1("cancel by original author\n"));
420 
421  //assemble
422  art->assemble();
423 
424  //send
425  KNLocalArticle::List lst;
426  lst.append(art);
427  sendArticles( lst, sendNow );
428 }
429 
430 
431 void KNArticleFactory::createSupersede( KNArticle::Ptr a )
432 {
433  if (!a)
434  return;
435 
436  if(!cancelAllowed(a))
437  return;
438 
439  if ( KMessageBox::No==KMessageBox::questionYesNo( knGlobals.topWidget,
440  i18n("Do you really want to supersede this article?"), QString(), KGuiItem(i18n("Supersede")), KStandardGuiItem::cancel() ) )
441  return;
442 
443  KNGroup::Ptr grp;
444  KNNntpAccount::Ptr nntp;
445 
446  if ( a->type() == KNArticle::ATremote )
447  nntp = boost::static_pointer_cast<KNGroup>( a->collection() )->account();
448  else {
449  KNLocalArticle::Ptr la = boost::static_pointer_cast<KNLocalArticle>( a );
450  la->setCanceled(true);
451  la->updateListItem();
452  nntp=knGlobals.accountManager()->account(la->serverId());
453  if(!nntp)
454  nntp=knGlobals.accountManager()->first();
455  if(!nntp) {
456  KMessageBox::error(knGlobals.topWidget, i18n("You have no valid news accounts configured."));
457  return;
458  }
459  }
460 
461  if ( !a->newsgroups()->isEmpty() )
462  grp = knGlobals.groupManager()->group(a->newsgroups()->groups().first(), nntp);
463 
464  //new article
465  KNLocalArticle::Ptr art = newArticle( grp, a->contentType()->charset() );
466 
467  if(!art)
468  return;
469 
470  art->setDoPost(true);
471  art->setDoMail(false);
472 
473  //server
474  art->setServerId(nntp->id());
475 
476  //subject
477  art->subject()->fromUnicodeString(a->subject()->asUnicodeString(), a->subject()->rfc2047Charset());
478 
479  //newsgroups
480  art->newsgroups()->from7BitString(a->newsgroups()->as7BitString(false));
481 
482  //followup-to
483  art->followUpTo()->from7BitString(a->followUpTo()->as7BitString(false));
484 
485  //References
486  if ( !a->references()->isEmpty() )
487  art->references()->from7BitString( a->references()->as7BitString(false) );
488 
489  //Supersedes
490  art->supersedes()->from7BitString(a->messageID()->as7BitString(false));
491 
492  //Body
493  QString text;
494  KMime::Content *textContent=a->textContent();
495  if(textContent)
496  text = textContent->decodedText();
497 
498  //open composer
499  KNComposer *c=new KNComposer(art, text);
500  mCompList.append( c );
501  connect(c, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*)));
502  c->show();
503 }
504 
505 
506 void KNArticleFactory::createMail(KMime::Types::Mailbox *address)
507 {
508  if ( knGlobals.settings()->useExternalMailer() ) {
509  sendMailExternal(address->prettyAddress());
510  return;
511  }
512 
513  //create new article
514  KNLocalArticle::Ptr art = newArticle( knGlobals.groupManager()->currentGroup(), Locale::defaultCharset() );
515  if(!art)
516  return;
517 
518  art->setDoMail(true);
519  art->setDoPost(false);
520  art->to()->addAddress((*address));
521 
522  //open composer
523  KNComposer *c = new KNComposer( art, QString(), QString(), true );
524  mCompList.append( c );
525  connect(c, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*)));
526  c->show();
527 }
528 
529 
530 void KNArticleFactory::sendMailExternal(const QString &address, const QString &subject, const QString &body)
531 {
532  KUrl mailtoURL;
533  QStringList queries;
534  QString query;
535  mailtoURL.setProtocol("mailto");
536 
537  if (!address.isEmpty())
538  mailtoURL.setPath(address);
539  if (!subject.isEmpty())
540  queries.append("subject="+KUrl::toPercentEncoding(subject));
541  if (!body.isEmpty())
542  queries.append("body="+KUrl::toPercentEncoding(body));
543 
544  if (queries.count() > 0) {
545  query = '?';
546  for ( QStringList::Iterator it = queries.begin(); it != queries.end(); ++it ) {
547  if (it != queries.begin())
548  query.append( '&' );
549  query.append((*it));
550  }
551  }
552 
553  if (!query.isEmpty())
554  mailtoURL.setQuery(query);
555 
556  KToolInvocation::invokeMailer(mailtoURL);
557 }
558 
559 
560 void KNArticleFactory::edit( KNLocalArticle::Ptr a )
561 {
562  if(!a)
563  return;
564 
565  KNComposer *com=findComposer(a);
566  if(com) {
567 #ifdef Q_OS_UNIX
568  KWindowSystem::activateWindow(com->winId());
569 #endif
570  return;
571  }
572 
573  if(a->editDisabled()) {
574  KMessageBox::sorry(knGlobals.topWidget, i18n("This article cannot be edited."));
575  return;
576  }
577 
578  //load article body
579  if(!a->hasContent())
580  knGlobals.articleManager()->loadArticle(a);
581 
582  //open composer
583  com = new KNComposer( a, QString() );
584  mCompList.append( com );
585  connect(com, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*)));
586  com->show();
587 }
588 
589 
590 void KNArticleFactory::sendArticles( KNLocalArticle::List &l, bool now )
591 {
592  KNJobData *job=0;
593  KNServerInfo::Ptr ser;
594 
595  KNLocalArticle::List unsent, sent;
596  for ( KNLocalArticle::List::Iterator it = l.begin(); it != l.end(); ++it ) {
597  if ( (*it)->pending() )
598  unsent.append( (*it) );
599  else
600  sent.append( (*it) );
601  }
602 
603  if(!sent.isEmpty()) {
604  showSendErrorDialog();
605  for ( KNLocalArticle::List::Iterator it = sent.begin(); it != sent.end(); ++it )
606  s_endErrDlg->append( (*it)->subject()->asUnicodeString(), i18n("Article has already been sent.") );
607  }
608 
609  if(!now) {
610  knGlobals.articleManager()->moveIntoFolder(unsent, knGlobals.folderManager()->outbox());
611  return;
612  }
613 
614 
615  for ( KNLocalArticle::List::Iterator it = unsent.begin(); it != unsent.end(); ++it ) {
616 
617  if ( (*it)->isLocked() )
618  continue;
619 
620  if ( !(*it)->hasContent() ) {
621  if ( !knGlobals.articleManager()->loadArticle( (*it) ) ) {
622  showSendErrorDialog();
623  s_endErrDlg->append( (*it)->subject()->asUnicodeString(), i18n("Unable to load article.") );
624  continue;
625  }
626  }
627 
628 
629  // filter out internal headers
630  QByteArray head = (*it)->head();
631  KMime::Headers::Base *header = 0;
632  while ( true ) {
633  header = KMime::HeaderParsing::extractFirstHeader( head );
634  if ( !header ) {
635  break;
636  }
637  if ( qstrncmp( header->type(), "X-KNode", 7 ) == 0 ) {
638  (*it)->removeHeader( header->type() );
639  }
640  }
641  (*it)->assemble(); // Validate change made above
642 
643 
644  if ( (*it)->doPost() && !(*it)->posted() ) {
645  ser = knGlobals.accountManager()->account( (*it)->serverId() );
646  job = new ArticlePostJob( this, ser, (*it) );
647  emitJob(job);
648  }
649  if ( (*it)->doMail() && !(*it)->mailed() ) {
650  int transportId = TransportManager::self()->defaultTransportId();
651  job = new MailSendJob( this, transportId, (*it) );
652  emitJob(job);
653  }
654  }
655 }
656 
657 
658 void KNArticleFactory::sendOutbox()
659 {
660  KNLocalArticle::List lst;
661  KNFolder::Ptr ob;
662 
663  if(!knGlobals.folderManager()->loadOutbox()) {
664  KMessageBox::error(knGlobals.topWidget, i18n("Unable to load the outbox-folder."));
665  return;
666  }
667 
668  ob=knGlobals.folderManager()->outbox();
669  for(int i=0; i< ob->length(); ++i)
670  lst.append(ob->at(i));
671 
672  sendArticles( lst, true );
673 }
674 
675 
676 bool KNArticleFactory::closeComposeWindows()
677 {
678  while ( !mCompList.isEmpty() ) {
679  QList<KNComposer*>::Iterator it = mCompList.begin();
680  if ( !(*it)->close() )
681  return false;
682  }
683 
684  return true;
685 }
686 
687 
688 void KNArticleFactory::deleteComposerForArticle( KNLocalArticle::Ptr a )
689 {
690  KNComposer *com = findComposer( a );
691  if ( com ) {
692  mCompList.removeAll( com );
693  com->deleteLater();
694  }
695 }
696 
697 
698 KNComposer* KNArticleFactory::findComposer( KNLocalArticle::Ptr a )
699 {
700  for ( QList<KNComposer*>::Iterator it = mCompList.begin(); it != mCompList.end(); ++it )
701  if ( (*it)->article() == a )
702  return (*it);
703  return 0;
704 }
705 
706 
707 void KNArticleFactory::configChanged()
708 {
709  for ( QList<KNComposer*>::Iterator it = mCompList.begin(); it != mCompList.end(); ++it )
710  (*it)->setConfig( false );
711 }
712 
713 
714 void KNArticleFactory::processJob(KNJobData *j)
715 {
716  KNLocalArticle::Ptr art = boost::static_pointer_cast<KNLocalArticle>( j->data() );
717  KNLocalArticle::List lst;
718  lst.append(art);
719 
720  if(j->canceled()) {
721  delete j;
722 
723  //sending of this article was canceled => move it to the "Outbox-Folder"
724  if(art->collection()!=knGlobals.folderManager()->outbox())
725  knGlobals.articleManager()->moveIntoFolder(lst, knGlobals.folderManager()->outbox());
726 
727  KMessageBox::information(knGlobals.topWidget, i18n("You canceled the article posting. The unsent articles are stored in the \"Outbox\" folder."));
728 
729  return;
730  }
731 
732  if(!j->success()) {
733  showSendErrorDialog();
734  s_endErrDlg->append(art->subject()->asUnicodeString(), j->errorString());
735  delete j; //unlock article
736 
737  //sending of this article failed => move it to the "Outbox-Folder"
738  if(art->collection()!=knGlobals.folderManager()->outbox())
739  knGlobals.articleManager()->moveIntoFolder(lst, knGlobals.folderManager()->outbox());
740  }
741  else {
742 
743  //disable edit
744  art->setEditDisabled(true);
745 
746  switch(j->type()) {
747 
748  case KNJobData::JTpostArticle:
749  delete j; //unlock article
750  art->setPosted(true);
751  if(art->doMail() && !art->mailed()) { //article has been posted, now mail it
752  sendArticles( lst, true );
753  return;
754  }
755  break;
756 
757  case KNJobData::JTmail:
758  delete j; //unlock article
759  art->setMailed(true);
760  break;
761 
762  default: break;
763  };
764 
765  //article has been sent successfully => move it to the "Sent-folder"
766  knGlobals.articleManager()->moveIntoFolder(lst, knGlobals.folderManager()->sent());
767  }
768 }
769 
770 
771 KNLocalArticle::Ptr KNArticleFactory::newArticle( KNCollection::Ptr col, const QByteArray &defChset, bool withXHeaders, KNArticle::Ptr origPost )
772 {
773  if ( knGlobals.settings()->generateMessageID() && knGlobals.settings()->hostname().isEmpty() ) {
774  KMessageBox::sorry(knGlobals.topWidget, i18n("Please set a hostname for the generation\nof the message-id or disable it."));
775  return KNLocalArticle::Ptr();
776  }
777 
778  KNLocalArticle::Ptr art( new KNLocalArticle( KNArticleCollection::Ptr() ) );
779  KPIMIdentities::Identity id;
780 
781  if (col) {
782  if (col->type() == KNCollection::CTgroup) {
783  id = boost::static_pointer_cast<KNGroup>( col )->identity();
784  if ( id.isNull() ) {
785  id = boost::static_pointer_cast<KNGroup>( col )->account()->identity();
786  }
787  } else if (col->type() == KNCollection::CTnntpAccount) {
788  id = boost::static_pointer_cast<KNNntpAccount>( col )->identity();
789  }
790  }
791  if ( id.isNull() ) {
792  id = KNGlobals::self()->settings()->identity();
793  }
794  // Identity UOID
795  KMime::Headers::Generic *xKnodeIdentity = new KMime::Headers::Generic( "X-KNode-Identity",
796  art.get(),
797  QByteArray::number( id.uoid() ) );
798  art->setHeader( xKnodeIdentity );
799 
800  //Message-id
801  if ( knGlobals.settings()->generateMessageID() )
802  art->messageID()->generate( knGlobals.settings()->hostname().toLatin1() );
803 
804  //From
805  KMime::Headers::From *from=art->from();
806  if ( KPIMUtils::isValidSimpleAddress( id.primaryEmailAddress() ) ) {
807  from->fromUnicodeString( id.fullEmailAddr(), Locale::defaultCharset() );
808  } else {
809  KMessageBox::sorry( knGlobals.topWidget,
810  i18n( "<qt>Please enter a valid email address for the "
811  "identity named <emphasis>%1</emphasis> "
812  "at the identity section of the configuration dialog.</qt>",
813  id.identityName() ) );
814  return KNLocalArticle::Ptr();
815  }
816 
817  //Reply-To
818  if ( KPIMUtils::isValidAddress( id.replyToAddr() ) == KPIMUtils::AddressOk ) {
819  art->replyTo()->fromUnicodeString( id.replyToAddr(), Locale::defaultCharset() );
820  } else {
821  art->removeHeader( "Reply-To" );
822  }
823 
824  //Mail-Copies-To
825  if ( KPIMUtils::isValidAddress( id.property( "Mail-Copies-To" ).toString() ) == KPIMUtils::AddressOk ) {
826  art->mailCopiesTo()->fromUnicodeString( id.property( "Mail-Copies-To" ).toString(), Locale::defaultCharset() );
827  } else {
828  art->removeHeader( "Mail-Copies-To" );
829  }
830 
831  //Organization
832  if ( !id.organization().trimmed().isEmpty() ) {
833  art->organization()->fromUnicodeString( id.organization(), Locale::defaultCharset() );
834  } else {
835  art->removeHeader( "Organization" );
836  }
837 
838  //Date
839  art->date()->setDateTime( KDateTime::currentLocalDateTime() );
840 
841  //User-Agent
842  if( !knGlobals.settings()->noUserAgent() ) {
843  art->userAgent()->from7BitString("KNode/" KNODE_VERSION);
844  }
845 
846  //Mime
847  KMime::Headers::ContentType *type=art->contentType();
848  type->setMimeType("text/plain");
849 
850  type->setCharset(defChset);
851 
852  if ( defChset.toLower() == "us-ascii" )
853  art->contentTransferEncoding()->setEncoding(KMime::Headers::CE7Bit);
854  else
855  art->contentTransferEncoding()->setEncoding( knGlobals.settings()->allow8BitBody() ? KMime::Headers::CE8Bit : KMime::Headers::CEquPr );
856 
857  //X-Headers
858  if(withXHeaders) {
859  XHeader::List xhdr = knGlobals.settings()->xHeaders();
860  for ( XHeader::List::Iterator it = xhdr.begin(); it != xhdr.end(); ++it ) {
861  QString value = (*it).value();
862  if(origPost) {
863  QString name( origPost->from()->displayNames().join(", ") );
864  if ( name.isEmpty() && !origPost->from()->isEmpty() )
865  name = QString::fromLatin1( origPost->from()->addresses().first() );
866  value.replace(QRegExp("%NAME"), name);
867  if ( !origPost->from()->isEmpty() )
868  value.replace( QRegExp("%EMAIL"), QString::fromLatin1(origPost->from()->addresses().first() ) );
869  }
870  else
871  if ( value.indexOf( "%NAME" ) != -1 || value.indexOf( "%EMAIL" ) != -1 )
872  continue;
873 
874  art->setHeader( new KMime::Headers::Generic( (*it).name().toLatin1(), art.get(), value,
875  Locale::defaultCharset() ) );
876  }
877  }
878 
879  return art;
880 }
881 
882 
883 bool KNArticleFactory::cancelAllowed( KNArticle::Ptr a )
884 {
885  if(!a)
886  return false;
887 
888  if(a->type()==KNArticle::ATlocal) {
889  KNLocalArticle::Ptr localArt = boost::static_pointer_cast<KNLocalArticle>( a );
890 
891  if(localArt->doMail() && !localArt->doPost()) {
892  KMessageBox::sorry(knGlobals.topWidget, i18n("Emails cannot be canceled or superseded."));
893  return false;
894  }
895 
896  KMime::Headers::Control *ctrl=localArt->control(false);
897  if(ctrl && ctrl->isCancel()) {
898  KMessageBox::sorry(knGlobals.topWidget, i18n("Cancel messages cannot be canceled or superseded."));
899  return false;
900  }
901 
902  if(!localArt->posted()) {
903  KMessageBox::sorry(knGlobals.topWidget, i18n("Only sent articles can be canceled or superseded."));
904  return false;
905  }
906 
907  if(localArt->canceled()) {
908  KMessageBox::sorry(knGlobals.topWidget, i18n("This article has already been canceled or superseded."));
909  return false;
910  }
911 
912  KMime::Headers::MessageID *mid=localArt->messageID(false);
913  if(!mid || mid->isEmpty()) {
914  KMessageBox::sorry(knGlobals.topWidget, i18n(
915 "This article cannot be canceled or superseded,\n\
916 because its message-id has not been created by KNode.\n\
917 But you can look for your article in the newsgroup\n\
918 and cancel (or supersede) it there."));
919  return false;
920  }
921 
922  return true;
923  }
924  else if ( a->type() == KNArticle::ATremote ) {
925  KNRemoteArticle::Ptr remArt = boost::static_pointer_cast<KNRemoteArticle>( a );
926  KPIMIdentities::IdentityManager *im = KNGlobals::self()->identityManager();
927  bool ownArticle = false;
928  const QList<QByteArray> fromAddr = remArt->from()->addresses();
929  foreach ( const QByteArray &addr, fromAddr ) {
930  if ( im->thatIsMe( QString::fromLatin1( addr ) ) ) {
931  ownArticle = true;
932  break;
933  }
934  }
935  if(!ownArticle) {
936  KMessageBox::sorry(knGlobals.topWidget, i18n("This article does not appear to be from you.\nYou can only cancel or supersede your own articles."));
937  return false;
938  }
939 
940  if(!remArt->hasContent()) {
941  KMessageBox::sorry(knGlobals.topWidget, i18n("You have to download the article body\nbefore you can cancel or supersede the article."));
942  return false;
943  }
944 
945  return true;
946  }
947 
948  return false;
949 }
950 
951 
952 void KNArticleFactory::showSendErrorDialog()
953 {
954  if(!s_endErrDlg) {
955  s_endErrDlg=new KNSendErrorDialog();
956  connect(s_endErrDlg, SIGNAL(closeClicked()), this, SLOT(slotSendErrorDialogDone()));
957  }
958  s_endErrDlg->show();
959 }
960 
961 
962 void KNArticleFactory::slotComposerDone(KNComposer *com)
963 {
964  bool delCom=true;
965  KNLocalArticle::List lst;
966  lst.append(com->article());
967 
968  switch(com->result()) {
969 
970  case KNComposer::CRsendNow:
971  delCom=com->hasValidData();
972  if(delCom) {
973  if ( com->applyChanges() )
974  sendArticles( lst, true );
975  else
976  delCom = false;
977  }
978  break;
979 
980  case KNComposer::CRsendLater:
981  delCom=com->hasValidData();
982  if(delCom) {
983  if ( com->applyChanges() )
984  sendArticles( lst, false );
985  else
986  delCom = false;
987  }
988  break;
989 
990  case KNComposer::CRsave :
991  com->applyChanges();
992  knGlobals.articleManager()->moveIntoFolder(lst, knGlobals.folderManager()->drafts());
993  break;
994 
995  case KNComposer::CRdelAsk:
996  delCom=knGlobals.articleManager()->deleteArticles(lst, true);
997  break;
998 
999  case KNComposer::CRdel:
1000  delCom=knGlobals.articleManager()->deleteArticles(lst, false);
1001  break;
1002 
1003  case KNComposer::CRcancel:
1004  // just close...
1005  break;
1006 
1007  default: break;
1008 
1009  };
1010 
1011  if ( delCom ) {
1012  mCompList.removeAll( com );
1013  com->deleteLater();
1014  }
1015 #ifdef Q_OS_UNIX
1016  else
1017  KWindowSystem::activateWindow(com->winId());
1018 #endif
1019 }
1020 
1021 
1022 void KNArticleFactory::slotSendErrorDialogDone()
1023 {
1024  s_endErrDlg->deleteLater();
1025  s_endErrDlg=0;
1026 }
1027 
1028 
1029 //======================================================================================================
1030 
1031 
1032 KNSendErrorDialog::KNSendErrorDialog()
1033  : KDialog( knGlobals.topWidget )
1034 {
1035  setCaption( i18n("Errors While Sending") );
1036  setButtons( Close );
1037  KVBox *page = new KVBox( this );
1038  setMainWidget( page );
1039  setDefaultButton( Close );
1040 
1041  new QLabel(QString("<b>%1</b><br>%2").arg(i18n("Errors occurred while sending these articles:"))
1042  .arg(i18n("The unsent articles are stored in the \"Outbox\" folder.")), page);
1043  mErrorList = new QListWidget( page );
1044  mError = new QLabel( QString(), page );
1045  mError->setWordWrap( true );
1046 
1047  connect( mErrorList, SIGNAL(currentRowChanged(int)), SLOT(slotHighlighted(int)) );
1048 
1049  KNHelper::restoreWindowSize("sendDlg", this, QSize(320,250));
1050 }
1051 
1052 
1053 KNSendErrorDialog::~KNSendErrorDialog()
1054 {
1055  KNHelper::saveWindowSize("sendDlg", size());
1056 }
1057 
1058 
1059 void KNSendErrorDialog::append(const QString &subject, const QString &error)
1060 {
1061  ErrorListItem *item = new ErrorListItem( subject, error );
1062  item->setIcon( UserIcon("snderr") );
1063  mErrorList->addItem( item );
1064  mErrorList->setCurrentItem( item );
1065 }
1066 
1067 
1068 void KNSendErrorDialog::slotHighlighted(int idx)
1069 {
1070  ErrorListItem *item = static_cast<ErrorListItem*>( mErrorList->item( idx ) );
1071  if ( item ) {
1072  QString tmp = i18n("<b>Error message:</b><br />") + item->error();
1073  mError->setText( tmp );
1074  }
1075 }
1076 
1077 //-------------------------------
1078 #include "knarticlefactory.moc"
KNComposer::result
composerResult result() const
Definition: kncomposer.h:76
KNNntpAccount
Represents an account on a news server.
Definition: knnntpaccount.h:56
KNLocalArticle::setCanceled
void setCanceled(bool b=true)
Definition: knarticle.h:236
KNArticleFactory::sendMailExternal
void sendMailExternal(const QString &address=QString(), const QString &subject=QString(), const QString &body=QString())
Send a mail via an external program.
Definition: knarticlefactory.cpp:530
KNArticleFactory::findComposer
KNComposer * findComposer(KNLocalArticle::Ptr a)
Definition: knarticlefactory.cpp:698
KVBox
KNLocalArticle::Ptr
boost::shared_ptr< KNLocalArticle > Ptr
Shared pointer to a KNLocalArticle. To be used instead of raw KNLocalArticle*.
Definition: knarticle.h:214
KNArticle::ATremote
Definition: knarticle.h:45
KNSendErrorDialog::append
void append(const QString &subject, const QString &error)
Definition: knarticlefactory.cpp:1059
KNHelper::saveWindowSize
static void saveWindowSize(const QString &name, const QSize &s)
Definition: utilities.cpp:205
KNArticleFactory::cancelAllowed
bool cancelAllowed(KNArticle::Ptr a)
Definition: knarticlefactory.cpp:883
KNArticleFactory::newArticle
KNLocalArticle::Ptr newArticle(KNCollection::Ptr col, const QByteArray &defChset, bool withXHeaders=true, KNArticle::Ptr origPost=KNArticle::Ptr())
Generate a new article to edit before posting.
Definition: knarticlefactory.cpp:771
KNJobConsumer::emitJob
void emitJob(KNJobData *j)
Send the job to the scheduler and append it to the job queue.
Definition: knjobdata.cpp:42
KNArticleFactory::createReply
void createReply(KNRemoteArticle::Ptr a, const QString &selectedText=QString(), bool post=true, bool mail=false)
Definition: knarticlefactory.cpp:110
utilities.h
knfolder.h
text
virtual QByteArray text(quint32 serialNumber) const =0
KNArticleFactory::mCompList
QList< KNComposer * > mCompList
Definition: knarticlefactory.h:87
KNJobData
Abstract base class for all KNode internal jobs.
Definition: knjobdata.h:101
KNComposer::CRsave
Definition: kncomposer.h:48
knarticlefactory.h
KNArticleFactory::closeComposeWindows
bool closeComposeWindows()
Definition: knarticlefactory.cpp:676
QListWidget
KNHelper::restoreWindowSize
static void restoreWindowSize(const QString &name, QWidget *d, const QSize &defaultSize)
Definition: utilities.cpp:212
knaccountmanager.h
KNJobData::JTpostArticle
Definition: knjobdata.h:113
KNComposer::CRdelAsk
Definition: kncomposer.h:47
KNGlobals::self
static KNGlobals * self()
Return the KNGlobals instance.
Definition: knglobals.cpp:72
KDialog
kngroupmanager.h
KNArticleFactory::createPosting
void createPosting(KNNntpAccount::Ptr a)
Definition: knarticlefactory.cpp:67
KNGroup
Representation of a news group.
Definition: kngroup.h:41
from
QString from() const
QObject
knarticlemanager.h
KNFolder::Ptr
boost::shared_ptr< KNFolder > Ptr
Shared pointer to a KNFolder.
Definition: knfolder.h:38
KNArticleFactory::slotComposerDone
void slotComposerDone(KNComposer *com)
Definition: knarticlefactory.cpp:962
KNSendErrorDialog
Message send error dialog.
Definition: knarticlefactory.h:98
KNNntpAccount::Ptr
boost::shared_ptr< KNNntpAccount > Ptr
Shared pointer to a KNNntpAccount.
Definition: knnntpaccount.h:62
KNArticleFactory::createForward
void createForward(KNArticle::Ptr a)
Definition: knarticlefactory.cpp:277
knnntpaccount.h
nntpjobs.h
KNComposer::hasValidData
bool hasValidData()
Definition: kncomposer.cpp:533
KNSendErrorDialog::mError
QLabel * mError
Error message label.
Definition: knarticlefactory.h:127
KNode::ArticlePostJob
Post a article to the given news server.
Definition: nntpjobs.h:101
KNComposer
Message composer window.
Definition: kncomposer.h:41
KNLocalArticle
This class encapsulates an article, that is stored locally in an MBOX-file.
Definition: knarticle.h:210
KNArticleFactory::configChanged
void configChanged()
Definition: knarticlefactory.cpp:707
KNGlobals::identityManager
KPIMIdentities::IdentityManager * identityManager()
Returns the identity manager.
Definition: knglobals.cpp:167
KNSendErrorDialog::mErrorList
QListWidget * mErrorList
Error list widget.
Definition: knarticlefactory.h:125
KNJobData::type
jobType type() const
Definition: knjobdata.h:120
KNArticle::ATlocal
Definition: knarticle.h:46
KNArticleFactory::s_endErrDlg
KNSendErrorDialog * s_endErrDlg
Definition: knarticlefactory.h:88
KNArticleFactory::~KNArticleFactory
~KNArticleFactory()
Definition: knarticlefactory.cpp:59
KNArticleFactory::edit
void edit(KNLocalArticle::Ptr a)
Definition: knarticlefactory.cpp:560
KNJobData::data
KNJobItem::Ptr data() const
Definition: knjobdata.h:123
KNSendErrorDialog::ErrorListItem::error
QString error() const
Returns the error message of this item.
Definition: knarticlefactory.h:119
KNode::Settings::identity
virtual const KPIMIdentities::Identity & identity() const
Returns the global identity (or the default one when none is set yet).
Definition: settings.cpp:91
subject
QString subject() const
KNSendErrorDialog::~KNSendErrorDialog
~KNSendErrorDialog()
Definition: knarticlefactory.cpp:1053
locale.h
KNGlobals::settings
KNode::Settings * settings()
Returns the KConfigXT generated settings object.
Definition: knglobals.cpp:182
resource.h
KNJobData::canceled
bool canceled() const
Returns true if the job has been canceled by the user.
Definition: knjobdata.h:132
KNComposer::CRsendNow
Definition: kncomposer.h:47
KNArticleFactory::deleteComposerForArticle
void deleteComposerForArticle(KNLocalArticle::Ptr a)
Definition: knarticlefactory.cpp:688
KNArticleFactory::createMail
void createMail(KMime::Types::Mailbox *address)
Definition: knarticlefactory.cpp:506
KNArticleFactory::slotSendErrorDialogDone
void slotSendErrorDialogDone()
Definition: knarticlefactory.cpp:1022
KNArticleFactory::sendArticles
void sendArticles(KNLocalArticle::List &l, bool now=true)
Definition: knarticlefactory.cpp:590
KNComposer::article
KNLocalArticle::Ptr article() const
Definition: kncomposer.h:77
KNODE_VERSION
#define KNODE_VERSION
Definition: resource.h:22
KNArticleFactory::createSupersede
void createSupersede(KNArticle::Ptr a)
Definition: knarticlefactory.cpp:431
KNCollection::CTgroup
Definition: kncollection.h:33
KNSendErrorDialog::KNSendErrorDialog
KNSendErrorDialog()
Definition: knarticlefactory.cpp:1032
KNHelper::rewrapStringList
static QString rewrapStringList(const QStringList &text, int wrapAt, QChar quoteChar, bool stopAtSig, bool alwaysSpace)
used for rewarping a text when replying to a message or inserting a file into a box ...
Definition: utilities.cpp:286
knglobals.h
KNJobData::errorString
QString errorString() const
Returns the error message.
Definition: knjobdata.h:128
KNRemoteArticle::Ptr
boost::shared_ptr< KNRemoteArticle > Ptr
Shared pointer to a KNRemoteArticle. To be used instead of raw KNRemoteArticle*.
Definition: knarticle.h:107
KNCollection::Ptr
boost::shared_ptr< KNCollection > Ptr
Shared pointer to a KNCollection.
Definition: kncollection.h:40
KNArticleFactory::showSendErrorDialog
void showSendErrorDialog()
Definition: knarticlefactory.cpp:952
KNArticleFactory::sendOutbox
void sendOutbox()
Definition: knarticlefactory.cpp:658
knfoldermanager.h
settings.h
KNArticleFactory::createCancel
void createCancel(KNArticle::Ptr a)
Definition: knarticlefactory.cpp:353
KNArticle::Ptr
boost::shared_ptr< KNArticle > Ptr
Shared pointer to a KNArticle. To be used instead of raw KNArticle*.
Definition: knarticle.h:39
kncomposer.h
KNComposer::CRdel
Definition: kncomposer.h:48
mailsendjob.h
KNJobData::success
bool success() const
Returns true if the job finished successfully.
Definition: knjobdata.h:130
QLabel
KNComposer::applyChanges
bool applyChanges()
Applies changes from the editor into the article being edited.
Definition: kncomposer.cpp:725
KNComposer::CRsendLater
Definition: kncomposer.h:47
KNArticleFactory::KNArticleFactory
KNArticleFactory(QObject *parent=0)
Definition: knarticlefactory.cpp:53
KNArticleCollection::Ptr
boost::shared_ptr< KNArticleCollection > Ptr
Shared pointer to a KNArticle.
Definition: knarticlecollection.h:82
KNRemoteArticle
KNRemoteArticle represents an article, whos body has to be retrieved from a remote host or from the l...
Definition: knarticle.h:103
KNServerInfo::Ptr
boost::shared_ptr< KNServerInfo > Ptr
Shared pointer to a KNServerInfo.
Definition: knserverinfo.h:37
KNJobData::JTmail
Definition: knjobdata.h:114
KNArticleFactory::processJob
void processJob(KNJobData *j)
The actual work is done here.
Definition: knarticlefactory.cpp:714
KNSendErrorDialog::ErrorListItem
Error list widget item.
Definition: knarticlefactory.h:110
knGlobals
#define knGlobals
Keep compatibility with the old way.
Definition: knglobals.h:28
KNCollection::CTnntpAccount
Definition: kncollection.h:33
KNode::MailSendJob
Sends a mail to a SMTP server.
Definition: mailsendjob.h:23
QList
KNGroup::Ptr
boost::shared_ptr< KNGroup > Ptr
Shared pointer to a KNGroup.
Definition: kngroup.h:47
KNSendErrorDialog::slotHighlighted
void slotHighlighted(int idx)
Definition: knarticlefactory.cpp:1068
KNComposer::CRcancel
Definition: kncomposer.h:48
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:58:36 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

knode

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

kdepim API Reference

Skip menu "kdepim API Reference"
  • akonadi_next
  • akregator
  • blogilo
  • calendarsupport
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt2
  • kjots
  • kleopatra
  • kmail
  • knode
  • knotes
  • kontact
  • korgac
  • korganizer
  • ktimetracker
  • libkdepim
  • libkleo
  • libkpgp
  • mailcommon
  • messagelist
  • messageviewer

Search



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