Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 38579 Details for
Bug 62382
Kolab useflag support for kdepim
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Kolab2/Proko2 changes against KDE_3_3_BRANCH
proko2.patch (text/plain), 145.83 KB, created by
Stephan Buys
on 2004-08-31 07:40:41 UTC
(
hide
)
Description:
Kolab2/Proko2 changes against KDE_3_3_BRANCH
Filename:
MIME Type:
Creator:
Stephan Buys
Created:
2004-08-31 07:40:41 UTC
Size:
145.83 KB
patch
obsolete
>diff -u -r kdepim/kioslaves/imap4/imap4.cc proko2/kioslaves/imap4/imap4.cc >--- kdepim/kioslaves/imap4/imap4.cc 2004-07-26 19:25:31.000000000 +0200 >+++ proko2/kioslaves/imap4/imap4.cc 2004-08-31 12:36:23.803771576 +0200 >@@ -33,6 +33,8 @@ > * - September 1997 (CRAM-MD5 authentication method) > * - RFC 2104 - HMAC: Keyed-Hashing for Message Authentication - February 1997 > * - RFC 2086 - IMAP4 ACL extension - January 1997 >+ * - http://www.ietf.org/internet-drafts/draft-daboo-imap-annotatemore-05.txt >+ * IMAP ANNOTATEMORE draft - April 2004. > * > * Supported URLs: > * - imap://server/ - Prompt for user/pass, list all folders in home directory >@@ -570,7 +572,7 @@ > } > } > if ( !selectInfo.alert().isNull() ) { >- warning( i18n( "Message from %1 while processing '%2': %3" ).arg( myHost, myBox ,selectInfo.alert() ) ); >+ warning( i18n( "Message from %1 while processing '%2': %3" ).arg( myHost, myBox, selectInfo.alert() ) ); > selectInfo.setAlert( 0 ); > } > >@@ -1132,6 +1134,7 @@ > * Subscribe: data = 'u' + URL (KURL) > * Change the status: data = 'S' + URL (KURL) + Flags (QCString) > * ACL commands: data = 'A' + command + URL (KURL) + command-dependent args >+ * AnnotateMore commands: data = 'M' + 'G'et/'S'et + URL + entry + command-dependent args > */ > void > IMAP4Protocol::special (const QByteArray & aData) >@@ -1218,6 +1221,18 @@ > } > break; > } >+ case 'M': // annotatemore >+ { >+ int cmd; >+ stream >> cmd; >+ if ( hasCapability( "ANNOTATEMORE" ) ) { >+ specialAnnotateMoreCommand( cmd, stream ); >+ finished(); >+ } else { >+ error( ERR_UNSUPPORTED_ACTION, "ANNOTATEMORE" ); >+ } >+ break; >+ } > case 'S': // status > { > KURL _url; >@@ -1356,6 +1371,71 @@ > } > > void >+IMAP4Protocol::specialAnnotateMoreCommand( int command, QDataStream& stream ) >+{ >+ // All commands start with the URL to the box >+ KURL _url; >+ stream >> _url; >+ QString aBox, aSequence, aLType, aSection, aValidity, aDelimiter, aInfo; >+ parseURL (_url, aBox, aSection, aLType, aSequence, aValidity, aDelimiter, aInfo); >+ >+ switch( command ) { >+ case 'S': // SETANNOTATION >+ { >+ // Params: >+ // KURL URL of the mailbox >+ // QString entry (should be an actual entry name, no % or *; empty for server entries) >+ // QMap<QString,QString> attributes (name and value) >+ QString entry; >+ QMap<QString, QString> attributes; >+ stream >> entry >> attributes; >+ kdDebug(7116) << "SETANNOTATION " << aBox << " " << entry << " " << attributes.count() << " attributes" << endl; >+ imapCommand *cmd = doCommand(imapCommand::clientSetAnnotation(aBox, entry, attributes)); >+ if (cmd->result () != "OK") >+ { >+ error(ERR_SLAVE_DEFINED, i18n("Setting the annotation %1 on folder %2 " >+ " failed. The server returned: %3") >+ .arg(entry) >+ .arg(_url.prettyURL()) >+ .arg(cmd->resultInfo())); >+ return; >+ } >+ completeQueue.removeRef (cmd); >+ break; >+ } >+ case 'G': // GETANNOTATION. >+ { >+ // Params: >+ // KURL URL of the mailbox >+ // QString entry (should be an actual entry name, no % or *; empty for server entries) >+ // QStringList attributes (list of attributes to be retrieved, possibly with % or *) >+ QString entry; >+ QStringList attributeNames; >+ stream >> entry >> attributeNames; >+ kdDebug(7116) << "GETANNOTATION " << aBox << " " << entry << " " << attributeNames << endl; >+ imapCommand *cmd = doCommand(imapCommand::clientGetAnnotation(aBox, entry, attributeNames)); >+ if (cmd->result () != "OK") >+ { >+ error(ERR_SLAVE_DEFINED, i18n("Retrieving the annotation %1 on folder %2 " >+ "failed. The server returned: %3") >+ .arg(entry) >+ .arg(_url.prettyURL()) >+ .arg(cmd->resultInfo())); >+ return; >+ } >+ // Returning information to the application from a special() command isn't easy. >+ // I'm reusing the infoMessage trick seen above (for capabilities and acls), but this >+ // limits me to a string instead of a stringlist. Let's use \r as separator. >+ kdDebug(7116) << getResults() << endl; >+ infoMessage(getResults().join( "\r" )); >+ break; >+ } >+ default: >+ kdWarning(7116) << "Unknown special annotate command:" << command << endl; >+ } >+} >+ >+void > IMAP4Protocol::rename (const KURL & src, const KURL & dest, bool overwrite) > { > kdDebug(7116) << "IMAP4::rename - [" << (overwrite ? "Overwrite" : "NoOverwrite") << "] " << src.prettyURL() << " -> " << dest.prettyURL() << endl; >diff -u -r kdepim/kioslaves/imap4/imap4.h proko2/kioslaves/imap4/imap4.h >--- kdepim/kioslaves/imap4/imap4.h 2004-06-09 12:00:35.000000000 +0200 >+++ proko2/kioslaves/imap4/imap4.h 2004-08-31 12:36:23.805771272 +0200 >@@ -164,6 +164,7 @@ > const imapList & item); > > void specialACLCommand( int command, QDataStream& stream ); >+ void specialAnnotateMoreCommand( int command, QDataStream& stream ); > > private: > >diff -u -r kdepim/kioslaves/imap4/imapcommand.cc proko2/kioslaves/imap4/imapcommand.cc >--- kdepim/kioslaves/imap4/imapcommand.cc 2004-04-06 02:30:12.000000000 +0200 >+++ proko2/kioslaves/imap4/imapcommand.cc 2004-08-31 12:36:23.808770816 +0200 >@@ -348,3 +348,42 @@ > return new imapCommand ("MYRIGHTS", QString("\"") + rfcDecoder::toIMAP (box) > + "\""); > } >+ >+imapCommand * >+imapCommand::clientSetAnnotation( const QString& box, const QString& entry, const QMap<QString, QString>& attributes ) >+{ >+ QString parameter = QString("\"") + rfcDecoder::toIMAP (box) >+ + "\" \"" + rfcDecoder::toIMAP (entry) >+ + "\" ("; >+ for( QMap<QString,QString>::ConstIterator it = attributes.begin(); it != attributes.end(); ++it ) { >+ parameter += "\""; >+ parameter += rfcDecoder::toIMAP (it.key()); >+ parameter += "\" \""; >+ parameter += rfcDecoder::toIMAP (it.data()); >+ parameter += "\" "; >+ } >+ // Turn last space into a ')' >+ parameter[parameter.length()-1] = ')'; >+ >+ return new imapCommand ("SETANNOTATION", parameter); >+} >+ >+imapCommand * >+imapCommand::clientGetAnnotation( const QString& box, const QString& entry, const QStringList& attributeNames ) >+{ >+ QString parameter = QString("\"") + rfcDecoder::toIMAP (box) >+ + "\" \"" + rfcDecoder::toIMAP (entry) >+ + "\" "; >+ if ( attributeNames.count() == 1 ) >+ parameter += "\"" + rfcDecoder::toIMAP (attributeNames.first()) + '"'; >+ else { >+ parameter += '('; >+ for( QStringList::ConstIterator it = attributeNames.begin(); it != attributeNames.end(); ++it ) { >+ parameter += "\"" + rfcDecoder::toIMAP (*it) + "\" "; >+ } >+ // Turn last space into a ')' >+ parameter[parameter.length()-1] = ')'; >+ } >+ return new imapCommand ("GETANNOTATION", parameter); >+} >+ >diff -u -r kdepim/kioslaves/imap4/imapcommand.h proko2/kioslaves/imap4/imapcommand.h >--- kdepim/kioslaves/imap4/imapcommand.h 2004-04-06 02:30:12.000000000 +0200 >+++ proko2/kioslaves/imap4/imapcommand.h 2004-08-31 12:36:23.810770512 +0200 >@@ -25,6 +25,7 @@ > > #include <qstringlist.h> > #include <qstring.h> >+#include <qmap.h> > > /** > * @brief encapulate a IMAP command >@@ -338,6 +339,25 @@ > */ > static imapCommand *clientMyRights ( const QString& box ); > >+ //////////// ANNOTATEMORE support ///////////// >+ /** >+ * @brief Create a SETANNOTATION command >+ * @param box mailbox name >+ * @param entry entry specifier >+ * @param attributes map of attribute names + values >+ * @return a SETANNOTATION imapCommand >+ */ >+ static imapCommand *clientSetAnnotation ( const QString& box, const QString& entry, const QMap<QString, QString>& attributes ); >+ >+ /** >+ * @brief Create a GETANNOTATION command >+ * @param box mailbox name >+ * @param entry entry specifier >+ * @param attribute attribute specifier >+ * @return a GETANNOTATION imapCommand >+ */ >+ static imapCommand *clientGetAnnotation ( const QString& box, const QString& entry, const QStringList& attributeNames ); >+ > protected: > QString aCommand; > QString mId; >diff -u -r kdepim/kioslaves/imap4/imapparser.cc proko2/kioslaves/imap4/imapparser.cc >--- kdepim/kioslaves/imap4/imapparser.cc 2004-07-11 23:40:52.000000000 +0200 >+++ proko2/kioslaves/imap4/imapparser.cc 2004-08-31 12:36:24.164716704 +0200 >@@ -100,7 +100,8 @@ > else if (command.find ("SEARCH") != -1 > || command == "GETACL" > || command == "LISTRIGHTS" >- || command == "MYRIGHTS") >+ || command == "MYRIGHTS" >+ || command == "GETANNOTATION") > { > lastResults.clear (); > } >@@ -285,11 +286,15 @@ > } > break; > >- case 'A': // ACL >+ case 'A': // ACL or ANNOTATION > if (qstrncmp(what, "ACL", what.size()) == 0) > { > parseAcl (result); > } >+ else if (qstrncmp(what, "ANNOTATION", what.size()) == 0) >+ { >+ parseAnnotation (result); >+ } > break; > default: > //better be a number >@@ -512,7 +517,7 @@ > result.pos++; // tie off ( > > this_one.parseAttributes( result ); >- >+ > result.pos++; // tie off ) > skipWS (result); > >@@ -550,6 +555,24 @@ > } > } > >+void imapParser::parseAnnotation (parseString & result) >+{ >+ parseOneWordC (result); // skip mailbox name >+ skipWS (result); >+ parseOneWordC (result); // skip entry name (we know it since we don't allow wildcards in it) >+ skipWS (result); >+ if (result.isEmpty() || result[0] != '(') >+ return; >+ result.pos++; >+ skipWS (result); >+ int outlen = 1; >+ // The result is name1 value1 name2 value2 etc. The caller will sort it out. >+ while ( outlen && !result.isEmpty() && result[0] != ')' ) { >+ QCString word = parseLiteralC (result, false, false, &outlen); >+ lastResults.append (word); >+ } >+} >+ > void imapParser::parseMyRights (parseString & result) > { > parseOneWordC (result); // skip mailbox name >@@ -678,7 +701,7 @@ > envelope->setDate(parseLiteralC(inWords)); > > //subject >- envelope->setSubjectEncoded(parseLiteralC(inWords)); >+ envelope->setSubject(parseLiteralC(inWords)); > > QPtrList<mailAddress> list; > list.setAutoDelete(true); >@@ -1396,7 +1419,7 @@ > > if (!parseReadLine(result.data)) return -1; > >- //kdDebug(7116) << result.cstr(); // includes \n >+ kdDebug(7116) << result.cstr(); // includes \n > > if (result.data.isEmpty()) > return 0; >@@ -1497,16 +1520,14 @@ > imapParser::parseURL (const KURL & _url, QString & _box, QString & _section, > QString & _type, QString & _uid, QString & _validity, QString & _info) > { >+// kdDebug(7116) << "imapParser::parseURL - " << endl; > QStringList parameters; > > _box = _url.path (); >- int paramStart = _box.find("/;"); >- if ( paramStart > -1 ) >- { >- QString paramString = _box.right( _box.length() - paramStart-2 ); >- parameters = QStringList::split (';', paramString); //split parameters >- _box.truncate( paramStart ); // strip parameters >- } >+ parameters = QStringList::split (';', _box); //split parameters >+ if (parameters.count () > 0) //assertion failure otherwise >+ parameters.remove (parameters.begin ()); //strip path >+ _box.truncate(_box.find (';')); // strip parameters > for (QStringList::ConstIterator it (parameters.begin ()); > it != parameters.end (); ++it) > { >diff -u -r kdepim/kioslaves/imap4/imapparser.h proko2/kioslaves/imap4/imapparser.h >--- kdepim/kioslaves/imap4/imapparser.h 2004-04-21 23:18:25.000000000 +0200 >+++ proko2/kioslaves/imap4/imapparser.h 2004-08-31 12:36:24.167716248 +0200 >@@ -273,6 +273,8 @@ > void parseExpunge (ulong value, parseString & result); > /** @brief parse a ACL line */ > void parseAcl (parseString & result); >+ /** @brief parse a ANNOTATION line */ >+ void parseAnnotation (parseString & result); > > /** > * parses the results of a fetch command >@@ -365,7 +367,7 @@ > > /** extract the box,section,list type, uid, uidvalidity from an url */ > static void parseURL (const KURL & _url, QString & _box, QString & _section, >- QString & _type, QString & _uid, QString & _validity, >+ QString & _type, QString & _uid, QString & _validity, > QString & _info); > > >diff -u -r kdepim/kioslaves/imap4/mailheader.h proko2/kioslaves/imap4/mailheader.h >--- kdepim/kioslaves/imap4/mailheader.h 2004-08-21 18:34:51.000000000 +0200 >+++ proko2/kioslaves/imap4/mailheader.h 2004-08-31 12:36:24.171715640 +0200 >@@ -101,12 +101,11 @@ > _subject = rfcDecoder::encodeRFC2047String(_str).latin1(); > } > /** >- * set an encoded subject >- * Whitespace is removed from begin and end >+ * set a encoded subject > */ > void setSubjectEncoded (const QCString & _str) > { >- _subject = _str.stripWhiteSpace(); >+ _subject = _str.simplifyWhiteSpace(); > } > > /** >diff -u -r kdepim/kmail/CVS/Entries proko2/kmail/CVS/Entries >--- kdepim/kmail/CVS/Entries 2004-08-31 11:39:25.000000000 +0200 >+++ proko2/kmail/CVS/Entries 2004-08-31 12:36:46.407335312 +0200 >@@ -3,7 +3,6 @@ > /ChangeLog/1.104/Tue Aug 12 17:38:55 2003//TKDE_3_3_BRANCH > /DESIGN/1.18/Fri May 14 11:44:36 2004//TKDE_3_3_BRANCH > /KMail.desktop/1.282.2.2/Tue Aug 31 07:23:13 2004//TKDE_3_3_BRANCH >-/Makefile.am/1.286/Fri Jul 30 14:13:13 2004//TKDE_3_3_BRANCH > /TODO/1.9/Sat Aug 30 23:14:30 2003//TKDE_3_3_BRANCH > /aboutdata.cpp/1.15/Wed Aug 4 22:14:42 2004//TKDE_3_3_BRANCH > /aboutdata.h/1.2/Sat Jul 26 14:51:48 2003//TKDE_3_3_BRANCH >@@ -46,10 +45,8 @@ > /compactionjob.cpp/1.9/Thu Jul 29 21:45:12 2004//TKDE_3_3_BRANCH > /compactionjob.h/1.6/Thu Jul 22 13:57:04 2004//TKDE_3_3_BRANCH > /composercryptoconfiguration.ui/1.3/Mon Jun 7 12:05:08 2004//TKDE_3_3_BRANCH >-/configuredialog.cpp/1.481.2.1/Tue Aug 10 08:47:07 2004//TKDE_3_3_BRANCH > /configuredialog.h/1.84/Thu Apr 15 14:07:47 2004//TKDE_3_3_BRANCH > /configuredialog_p.cpp/1.27/Sat Jun 5 09:27:34 2004//TKDE_3_3_BRANCH >-/configuredialog_p.h/1.94/Fri Jul 9 20:30:44 2004//TKDE_3_3_BRANCH > /cr128-app-kmail.png/1.1/Mon Oct 28 09:01:12 2002//TKDE_3_3_BRANCH > /cr16-app-kmail.png/1.3/Mon Oct 28 09:01:12 2002//TKDE_3_3_BRANCH > /cr22-app-kmail.png/1.1/Wed Aug 27 21:09:24 2003/-kb/TKDE_3_3_BRANCH >@@ -102,8 +99,6 @@ > /identitydrag.h/1.5/Fri Jun 4 00:04:08 2004//TKDE_3_3_BRANCH > /identitylistview.cpp/1.14/Thu Jul 15 14:09:40 2004//TKDE_3_3_BRANCH > /identitylistview.h/1.7/Fri May 14 11:44:36 2004//TKDE_3_3_BRANCH >-/imapaccountbase.cpp/1.101/Thu Jul 29 21:45:13 2004//TKDE_3_3_BRANCH >-/imapaccountbase.h/1.55/Thu Jul 22 19:24:11 2004//TKDE_3_3_BRANCH > /imapjob.cpp/1.68/Wed Jul 14 21:49:51 2004//TKDE_3_3_BRANCH > /imapjob.h/1.13/Tue Jun 1 22:48:51 2004//TKDE_3_3_BRANCH > /isubject.cpp/1.5/Mon Apr 26 16:10:25 2004//TKDE_3_3_BRANCH >@@ -152,7 +147,6 @@ > /kmail-upd-identities.pl/1.3/Thu Aug 15 21:45:09 2002//TKDE_3_3_BRANCH > /kmail.antispamrc/1.10/Tue Jul 13 21:07:18 2004//TKDE_3_3_BRANCH > /kmail.antivirusrc/1.1/Tue Jul 13 21:07:18 2004//TKDE_3_3_BRANCH >-/kmail.kcfg/1.21/Mon Aug 2 11:30:53 2004//TKDE_3_3_BRANCH > /kmail.upd/1.26/Fri Jul 9 22:26:41 2004//TKDE_3_3_BRANCH > /kmailIface.h/1.35/Thu Jul 1 10:44:22 2004//TKDE_3_3_BRANCH > /kmail_config_appearance.desktop/1.33.2.2/Tue Aug 31 07:23:13 2004//TKDE_3_3_BRANCH >@@ -165,9 +159,6 @@ > /kmail_part.cpp/1.56/Thu Jul 29 21:45:13 2004//TKDE_3_3_BRANCH > /kmail_part.h/1.15/Tue Jun 1 22:48:51 2004//TKDE_3_3_BRANCH > /kmail_view.desktop/1.2.2.1/Tue Aug 24 06:32:12 2004//TKDE_3_3_BRANCH >-/kmailicalIface.h/1.10/Mon Jul 26 22:05:27 2004//TKDE_3_3_BRANCH >-/kmailicalifaceimpl.cpp/1.55.2.1/Fri Aug 13 07:02:55 2004//TKDE_3_3_BRANCH >-/kmailicalifaceimpl.h/1.27/Mon Jul 26 22:05:27 2004//TKDE_3_3_BRANCH > /kmailpartIface.h/1.2/Sat Nov 30 21:27:19 2002//TKDE_3_3_BRANCH > /kmbroadcaststatus.cpp/1.43/Thu Jun 10 16:03:38 2004//TKDE_3_3_BRANCH > /kmbroadcaststatus.h/1.22/Thu Jun 10 16:03:38 2004//TKDE_3_3_BRANCH >@@ -193,8 +184,6 @@ > /kmfldsearch.h/1.44/Tue Jul 13 08:48:21 2004//TKDE_3_3_BRANCH > /kmfolder.cpp/1.338.2.1/Thu Aug 5 21:58:23 2004//TKDE_3_3_BRANCH > /kmfolder.h/1.161/Thu Jul 22 19:17:09 2004//TKDE_3_3_BRANCH >-/kmfoldercachedimap.cpp/1.131.2.1/Wed Aug 18 09:34:12 2004//TKDE_3_3_BRANCH >-/kmfoldercachedimap.h/1.55.2.1/Wed Aug 18 09:34:12 2004//TKDE_3_3_BRANCH > /kmfoldercombobox.cpp/1.18/Thu May 13 11:51:22 2004//TKDE_3_3_BRANCH > /kmfoldercombobox.h/1.8/Wed Jun 23 11:08:06 2004//TKDE_3_3_BRANCH > /kmfolderdia.cpp/1.161/Tue Aug 3 22:58:34 2004//TKDE_3_3_BRANCH >@@ -273,7 +262,6 @@ > /kmsystemtray.h/1.14/Fri Jul 9 20:30:44 2004//TKDE_3_3_BRANCH > /kmtransport.cpp/1.39/Tue Jul 13 22:10:31 2004//TKDE_3_3_BRANCH > /kmtransport.h/1.10/Sat Apr 10 09:21:44 2004//TKDE_3_3_BRANCH >-/kmversion.h/1.134/Wed Aug 4 16:22:16 2004//TKDE_3_3_BRANCH > /listjob.cpp/1.9/Fri Jul 9 22:16:59 2004//TKDE_3_3_BRANCH > /listjob.h/1.5/Sat Jun 12 17:07:14 2004//TKDE_3_3_BRANCH > /mailcomposerIface.h/1.2/Wed Jul 25 12:31:46 2001//TKDE_3_3_BRANCH >@@ -349,3 +337,19 @@ > D/interfaces//// > D/pics//// > D/profiles//// >+/kmailicalifaceimpl.cpp/1.46.2.70/Tue Aug 31 10:36:31 2004//Tproko2 >+/kmailicalifaceimpl.h/1.21.2.25/Tue Aug 31 10:36:31 2004//Tproko2 >+/kmailicalIface.h/1.9.2.15/Tue Aug 31 10:36:31 2004//Tproko2 >+/kmversion.h/1.134.4.1/Tue Aug 31 10:36:31 2004//Tproko2 >+/Makefile.am/1.281.2.6/Tue Aug 31 10:36:37 2004//Tproko2 >+/annotationjobs.cpp/1.1/Fri Jun 18 19:27:19 2004//Tproko2 >+/annotationjobs.h/1.1/Fri Jun 18 19:27:19 2004//Tproko2 >+/kmfoldercachedimap.cpp/1.125.2.15/Tue Aug 31 10:36:39 2004//Tproko2 >+/kmfoldercachedimap.h/1.53.2.6/Tue Aug 31 10:36:39 2004//Tproko2 >+/imapaccountbase.h/1.54.2.2/Tue Aug 31 10:36:39 2004//Tproko2 >+/imapaccountbase.cpp/1.94.2.4/Tue Aug 31 10:36:39 2004//Tproko2 >+/kmail.kcfg/1.15.2.5/Tue Aug 31 10:36:46 2004//Tproko2 >+/configuredialog.cpp/1.464.2.20/Tue Aug 31 10:36:46 2004//Tproko2 >+/configuredialog_p.h/1.92.2.5/Tue Aug 31 10:36:46 2004//Tproko2 >+/accountcombobox.cpp/1.1.2.10/Wed Aug 18 19:17:54 2004//Tproko2 >+/accountcombobox.h/1.1.2.3/Wed Aug 18 19:17:54 2004//Tproko2 >diff -u -r kdepim/kmail/Makefile.am proko2/kmail/Makefile.am >--- kdepim/kmail/Makefile.am 2004-07-30 16:13:13.000000000 +0200 >+++ proko2/kmail/Makefile.am 2004-08-31 12:36:37.427700424 +0200 >@@ -66,7 +66,7 @@ > kmfawidgets.cpp kmfoldermbox.cpp kmfolderimap.cpp \ > undostack.cpp kmfoldercachedimap.cpp \ > kmfoldermaildir.cpp kmacctexppop.cpp colorlistbox.cpp \ >- kmkernel.cpp kmailIface.skel kmailicalIface.skel \ >+ kmkernel.cpp kmailIface.skel kmailicalIface.skel \ > accountdialog.cpp kmfldsearch.cpp vcardviewer.cpp \ > vacationdialog.cpp vacation.cpp sieveconfig.cpp sievejob.cpp \ > kmpopheaders.cpp kmpopfiltercnfrmdlg.cpp \ >@@ -103,7 +103,8 @@ > expirejob.cpp compactionjob.cpp jobscheduler.cpp callback.cpp \ > listjob.cpp \ > composercryptoconfiguration.ui \ >- warningconfiguration.ui smimeconfiguration.ui >+ warningconfiguration.ui smimeconfiguration.ui annotationjobs.cpp \ >+ accountcombobox.cpp > > kmail_SOURCES = main.cpp > >@@ -116,6 +117,7 @@ > dcoptest_SOURCES = dcoptest.cpp kmailIface.skel mailcomposerIface.skel > > kmailIface_DCOPIDLNG = true >+kmailicalIface_DCOPIDLNG = true > > korganizeriface_DIR = $(top_srcdir)/korganizer > >@@ -148,7 +150,7 @@ > kmail-3.3b1-misc.pl > > confdir = $(kde_confdir) >-conf_DATA = kmail.antispamrc kmail.antivirusrc >+conf_DATA = kmail.antispamrc > > tipdir = $(kde_datadir)/kmail > tip_DATA = tips >Only in proko2/kmail: accountcombobox.cpp >Only in proko2/kmail: accountcombobox.h >Only in proko2/kmail: annotationjobs.cpp >Only in proko2/kmail: annotationjobs.h >diff -u -r kdepim/kmail/configuredialog.cpp proko2/kmail/configuredialog.cpp >--- kdepim/kmail/configuredialog.cpp 2004-08-10 10:47:07.000000000 +0200 >+++ proko2/kmail/configuredialog.cpp 2004-08-31 12:36:46.377339872 +0200 >@@ -45,11 +45,15 @@ > #include <composercryptoconfiguration.h> > #include <warningconfiguration.h> > #include <smimeconfiguration.h> >+#include "accountcombobox.h" >+#include "imapaccountbase.h" >+#include "folderstorage.h" > > using KMail::IdentityListView; > using KMail::IdentityListViewItem; > #include "identitydialog.h" > using KMail::IdentityDialog; >+using KMail::ImapAccountBase; > > // other kdenetwork headers: > #include <libkpimidentities/identity.h> >@@ -94,6 +98,7 @@ > #include <qradiobutton.h> > #include <qlayout.h> > #include <qcheckbox.h> >+#include <qwidgetstack.h> > > // other headers: > #include <assert.h> >@@ -4049,16 +4054,37 @@ > this, SLOT( slotEmitChanged( void ) ) ); > > mBox = new QWidget( b1 ); >- QGridLayout* grid = new QGridLayout( mBox, 3, 2, 0, KDialog::spacingHint() ); >+ QGridLayout* grid = new QGridLayout( mBox, 4, 2, 0, KDialog::spacingHint() ); > grid->setColStretch( 1, 1 ); > connect( mEnableImapResCB, SIGNAL( toggled(bool) ), > mBox, SLOT( setEnabled(bool) ) ); >+ >+ QLabel* storageFormatLA = new QLabel( i18n("&Format used for the groupware folders:"), >+ mBox ); >+ QString toolTip = i18n( "Choose the format to use to store the contents of the groupware folders." ); >+ QString whatsThis = i18n( GlobalSettings::self() >+ ->theIMAPResourceStorageFormatItem()->whatsThis().utf8() ); >+ grid->addWidget( storageFormatLA, 0, 0 ); >+ QToolTip::add( storageFormatLA, toolTip ); >+ QWhatsThis::add( storageFormatLA, whatsThis ); >+ mStorageFormatCombo = new QComboBox( false, mBox ); >+ storageFormatLA->setBuddy( mStorageFormatCombo ); >+ QStringList formatLst; >+ formatLst << i18n("Standard (Ical / Vcard)") << i18n("Kolab (XML)"); >+ mStorageFormatCombo->insertStringList( formatLst ); >+ grid->addWidget( mStorageFormatCombo, 0, 1 ); >+ QToolTip::add( mStorageFormatCombo, toolTip ); >+ QWhatsThis::add( mStorageFormatCombo, whatsThis ); >+ connect( mStorageFormatCombo, SIGNAL( activated( int ) ), >+ this, SLOT( slotStorageFormatChanged( int ) ) ); >+ > QLabel* languageLA = new QLabel( i18n("&Language of the groupware folders:"), > mBox ); >- QString toolTip = i18n( "Set the language of the folder names" ); >- QString whatsThis = i18n( GlobalSettings::self() >+ >+ toolTip = i18n( "Set the language of the folder names" ); >+ whatsThis = i18n( GlobalSettings::self() > ->theIMAPResourceFolderLanguageItem()->whatsThis().utf8() ); >- grid->addWidget( languageLA, 0, 0 ); >+ grid->addWidget( languageLA, 1, 0 ); > QToolTip::add( languageLA, toolTip ); > QWhatsThis::add( languageLA, whatsThis ); > mLanguageCombo = new QComboBox( false, mBox ); >@@ -4066,30 +4092,44 @@ > QStringList lst; > lst << i18n("English") << i18n("German") << i18n("French") << i18n("Dutch"); > mLanguageCombo->insertStringList( lst ); >- grid->addWidget( mLanguageCombo, 0, 1 ); >+ grid->addWidget( mLanguageCombo, 1, 1 ); > QToolTip::add( mLanguageCombo, toolTip ); > QWhatsThis::add( mLanguageCombo, whatsThis ); > connect( mLanguageCombo, SIGNAL( activated( int ) ), > this, SLOT( slotEmitChanged( void ) ) ); > >- QLabel* subfolderLA = >- new QLabel( i18n("Resource folders are &subfolders of:"), mBox ); >+ mFolderComboLabel = new QLabel( mBox ); // text depends on storage format > toolTip = i18n( "Set the parent of the resource folders" ); > whatsThis = i18n( GlobalSettings::self()->theIMAPResourceFolderParentItem()->whatsThis().utf8() ); >- grid->addWidget( subfolderLA, 1, 0 ); >- QToolTip::add( subfolderLA, toolTip ); >- QWhatsThis::add( subfolderLA, whatsThis ); >+ QToolTip::add( mFolderComboLabel, toolTip ); >+ QWhatsThis::add( mFolderComboLabel, whatsThis ); >+ grid->addWidget( mFolderComboLabel, 2, 0 ); >+ >+ mFolderComboStack = new QWidgetStack( mBox ); >+ grid->addWidget( mFolderComboStack, 2, 1 ); >+ >+ // First possibility in the widgetstack: a combo showing the list of all folders >+ // This is used with the ical/vcard storage > mFolderCombo = new KMFolderComboBox( mBox ); >- subfolderLA->setBuddy( mFolderCombo ); >- grid->addWidget( mFolderCombo, 1, 1 ); >+ mFolderComboStack->addWidget( mFolderCombo, 0 ); > QToolTip::add( mFolderCombo, toolTip ); > QWhatsThis::add( mFolderCombo, whatsThis ); > connect( mFolderCombo, SIGNAL( activated( int ) ), >- this, SLOT( slotEmitChanged( void ) ) ); >+ this, SLOT( slotEmitChanged() ) ); >+ >+ // Second possibility in the widgetstack: a combo showing the list of accounts >+ // This is used with the kolab xml storage since the groupware folders >+ // are always under the inbox. >+ mAccountCombo = new KMail::AccountComboBox( mBox ); >+ mFolderComboStack->addWidget( mAccountCombo, 1 ); >+ QToolTip::add( mAccountCombo, toolTip ); >+ QWhatsThis::add( mAccountCombo, whatsThis ); >+ connect( mAccountCombo, SIGNAL( activated( int ) ), >+ this, SLOT( slotEmitChanged() ) ); > > mHideGroupwareFolders = new QCheckBox( i18n( "&Hide groupware folders" ), > mBox, "HideGroupwareFoldersBox" ); >- grid->addMultiCellWidget( mHideGroupwareFolders, 2, 2, 0, 1 ); >+ grid->addMultiCellWidget( mHideGroupwareFolders, 3, 3, 0, 1 ); > QToolTip::add( mHideGroupwareFolders, > i18n( "When this is checked, you will not see the IMAP " > "resource folders in the folder tree." ) ); >@@ -4167,6 +4207,9 @@ > mHideGroupwareFolders->setChecked( GlobalSettings::hideGroupwareFolders() ); > int i = GlobalSettings::theIMAPResourceFolderLanguage(); > mLanguageCombo->setCurrentItem(i); >+ i = GlobalSettings::theIMAPResourceStorageFormat(); >+ mStorageFormatCombo->setCurrentItem(i); >+ slotStorageFormatChanged( i ); > > QString folderId( GlobalSettings::theIMAPResourceFolderParent() ); > if( !folderId.isNull() && kmkernel->findFolderById( folderId ) ) { >@@ -4175,6 +4218,32 @@ > // Folder was deleted, we have to choose a new one > mFolderCombo->setFolder( i18n( "<Choose a Folder>" ) ); > } >+ >+ KMAccount* selectedAccount = 0; >+ int accountId = GlobalSettings::theIMAPResourceAccount(); >+ if ( accountId ) >+ selectedAccount = kmkernel->acctMgr()->find( accountId ); >+ else { >+ // Fallback: iterate over accounts to select folderId if found (as an inbox folder) >+ for( KMAccount *a = kmkernel->acctMgr()->first(); a!=0; >+ a = kmkernel->acctMgr()->next() ) { >+ if( a->folder() && a->folder()->child() ) { >+ // Look inside that folder for an INBOX >+ KMFolderNode *node; >+ for (node = a->folder()->child()->first(); node; node = a->folder()->child()->next()) >+ if (!node->isDir() && node->name() == "INBOX") break; >+ >+ if ( node && static_cast<KMFolder*>(node)->idString() == folderId ) { >+ selectedAccount = a; >+ break; >+ } >+ } >+ } >+ } >+ if ( selectedAccount ) >+ mAccountCombo->setCurrentAccount( selectedAccount ); >+ else if ( GlobalSettings::theIMAPResourceStorageFormat() == 1 ) >+ kdDebug(5006) << "Folder " << folderId << " not found as an account's inbox" << endl; > } > > void MiscPage::GroupwareTab::save() { >@@ -4184,36 +4253,47 @@ > GlobalSettings::setLegacyMangleFromToHeaders( mLegacyMangleFromTo->isChecked() ); > GlobalSettings::setLegacyBodyInvites( mLegacyBodyInvites->isChecked() ); > >+ int format = mStorageFormatCombo->currentItem(); >+ GlobalSettings::setTheIMAPResourceStorageFormat( format ); >+ > // Write the IMAP resource config > GlobalSettings::setHideGroupwareFolders( mHideGroupwareFolders->isChecked() ); > > // If there is a leftover folder in the foldercombo, getFolder can > // return 0. In that case we really don't have it enabled >- KMFolder *folder = mFolderCombo->getFolder(); >- bool enabled = mEnableImapResCB->isChecked() && folder; >+ QString folderId; >+ if ( format == 0 ) { >+ KMFolder* folder = mFolderCombo->getFolder(); >+ if ( folder ) >+ folderId = folder->idString(); >+ } else { >+ // Inbox folder of the selected account >+ KMAccount* acct = mAccountCombo->currentAccount(); >+ if ( acct ) { >+ folderId = QString( ".%1.directory/INBOX" ).arg( acct->id() ); >+ GlobalSettings::setTheIMAPResourceAccount( acct->id() ); >+ } >+ } >+ >+ bool enabled = mEnableImapResCB->isChecked() && !folderId.isEmpty(); > GlobalSettings::setTheIMAPResourceEnabled( enabled ); > GlobalSettings::setTheIMAPResourceFolderLanguage( mLanguageCombo->currentItem() ); >- GlobalSettings::setTheIMAPResourceFolderParent( folder? folder->idString(): "" ); >+ GlobalSettings::setTheIMAPResourceFolderParent( folderId ); >+} > >- KMAccount* account = 0; >- // Didn't find an easy way to find the account for a given folder... >- // Fallback: iterate over accounts to select folderId if found (as an inbox folder) >- for( KMAccount *a = kmkernel->acctMgr()->first(); >- a && !account; // stop when found >- a = kmkernel->acctMgr()->next() ) { >- if( a->folder() && a->folder()->child() ) { >- KMFolderNode *node; >- for (node = a->folder()->child()->first(); node; node = a->folder()->child()->next()) >- if ( node && static_cast<KMFolder*>(node) == folder ) { >- account = a; >- break; >- } >- } >+void MiscPage::GroupwareTab::slotStorageFormatChanged( int format ) >+{ >+ mLanguageCombo->setEnabled( format == 0 ); // only ical/vcard needs the language hack >+ mFolderComboStack->raiseWidget( format ); >+ if ( format == 0 ) { >+ mFolderComboLabel->setText( i18n("&Resource folders are subfolders of:") ); >+ mFolderComboLabel->setBuddy( mFolderCombo ); >+ } else { >+ mFolderComboLabel->setText( i18n("&Resource folders are in account:") ); >+ mFolderComboLabel->setBuddy( mAccountCombo ); > } >- GlobalSettings::setTheIMAPResourceAccount( account ? account->id() : 0 ); > } > >- > #undef DIM > > //---------------------------- >diff -u -r kdepim/kmail/configuredialog_p.h proko2/kmail/configuredialog_p.h >--- kdepim/kmail/configuredialog_p.h 2004-07-09 22:30:44.000000000 +0200 >+++ proko2/kmail/configuredialog_p.h 2004-08-31 12:36:46.392337592 +0200 >@@ -51,6 +51,7 @@ > namespace KMail { > class IdentityDialog; > class IdentityListView; >+ class AccountComboBox; > } > namespace Kleo { > class BackendConfigWidget; >@@ -857,6 +858,7 @@ > void defaults() {} > QString helpAnchor() const; > private slots: >+ void slotStorageFormatChanged( int ); > void slotLegaceBodyInvitesToggled( bool on ); > private: > QCheckBox* mEnableGwCB; >@@ -865,8 +867,14 @@ > QWidget* mBox; > QVBox* gBox; > >+ QComboBox* mStorageFormatCombo; > QComboBox* mLanguageCombo; >- KMFolderComboBox* mFolderCombo; >+ >+ QLabel* mFolderComboLabel; >+ QWidgetStack* mFolderComboStack; >+ KMFolderComboBox* mFolderCombo; // in the widgetstack >+ KMail::AccountComboBox* mAccountCombo; // in the widgetstack >+ > QCheckBox* mHideGroupwareFolders; > QCheckBox* mAutoResCB; > QCheckBox* mAutoDeclConflCB; >diff -u -r kdepim/kmail/imapaccountbase.cpp proko2/kmail/imapaccountbase.cpp >--- kdepim/kmail/imapaccountbase.cpp 2004-07-29 23:45:13.000000000 +0200 >+++ proko2/kmail/imapaccountbase.cpp 2004-08-31 12:36:39.259421960 +0200 >@@ -92,6 +92,7 @@ > mErrorDialogIsActive( false ), > mPasswordDialogIsActive( false ), > mACLSupport( true ), >+ mAnnotationSupport( true ), > mSlaveConnected( false ), > mListDirProgressItem( 0 ) > { >@@ -408,6 +409,7 @@ > } > > //----------------------------------------------------------------------------- >+ // Do not remove imapPath, FolderDiaACLTab needs to call this with parent==0. > void ImapAccountBase::getACL( KMFolder* parent, const QString& imapPath ) > { > KURL url = getUrl(); >@@ -428,7 +430,7 @@ > JobIterator it = findJob( job ); > if ( it == jobsEnd() ) return; > >- KMFolder* folder = (*it).parent; >+ KMFolder* folder = (*it).parent; // can be 0 > emit receivedACL( folder, job, job->entries() ); > if (mSlave) removeJob(job); > } >diff -u -r kdepim/kmail/imapaccountbase.h proko2/kmail/imapaccountbase.h >--- kdepim/kmail/imapaccountbase.h 2004-07-22 21:24:11.000000000 +0200 >+++ proko2/kmail/imapaccountbase.h 2004-08-31 12:36:39.247423784 +0200 >@@ -243,6 +243,17 @@ > bool hasACLSupport() const { return mACLSupport; } > > /** >+ * Returns false if the IMAP server for this account doesn't support annotations. >+ * (and true if it does, or if we didn't try yet). >+ */ >+ bool hasAnnotationSupport() const { return mAnnotationSupport; } >+ >+ /** >+ * Called if the annotation command failed due to 'unsupported' >+ */ >+ void setHasNoAnnotationSupport() { mAnnotationSupport = false; } >+ >+ /** > * React to an error from the job. Uses job->error and job->errorString and calls > * the protected virtual handleJobError with them. See handleError below for details. > */ >@@ -365,6 +376,7 @@ > bool mErrorDialogIsActive : 1; > bool mPasswordDialogIsActive : 1; > bool mACLSupport : 1; >+ bool mAnnotationSupport : 1; > bool mSlaveConnected : 1; > > // folders that should be checked for new mails >diff -u -r kdepim/kmail/kmail.kcfg proko2/kmail/kmail.kcfg >--- kdepim/kmail/kmail.kcfg 2004-08-02 13:30:53.000000000 +0200 >+++ proko2/kmail/kmail.kcfg 2004-08-31 12:36:46.344344888 +0200 >@@ -41,7 +41,10 @@ > > <entry name="SendOnCheck" type="Enum"> > <label>Send queued mail on mail check</label> >- <whatsthis><qt><p>Select whether you want KMail to send all messages in the outbox on manual or all mail checks, or whether you do not want messages to be sent automatically at all. </p></qt></whatsthis> >+ <whatsthis><qt><p>Select whether you want KMail to send " >+ "all messages in the outbox on manual or all mail checks, " >+ "or whether you do not want messages to be sent automatically " >+ "at all. </p></qt></whatsthis> > <choices> > <choice name="DontSendOnCheck"/> > <choice name="SendOnManualChecks"/> >@@ -55,7 +58,8 @@ > <group name="FolderSelectionDialog"> > <entry name="LastSelectedFolder" type="String"> > <default>inbox</default> >- <whatsthis>The most recently selected folder in the folder selection dialog.</whatsthis> >+ <whatsthis>The most recently selected folder in the folder selection " >+ "dialog.</whatsthis> > </entry> > </group> > >@@ -75,7 +79,10 @@ > <entry name="VerboseNewMailNotification" type="Bool"> > <default>true</default> > <label>Verbose new mail notification</label> >- <whatsthis>If this option is enabled then for each folder the number of newly arrived messages is shown in the new mail notification; otherwise, you will only get a simple 'New mail arrived' message.</whatsthis> >+ <whatsthis>If this option is enabled then for each folder the number " >+ "of newly arrived messages is shown in the new mail notification; " >+ "otherwise, you will only get a simple 'New mail arrived' message." >+ "</whatsthis> > </entry> > </group> > >@@ -88,13 +95,21 @@ > > <entry name="LegacyMangleFromToHeaders" type="Bool"> > <label>Mangle From:/To: headers in replies to replies</label> >- <whatsthis>Microsoft Outlook has a number of shortcomings in its implementation of the iCalendar standard; this option works around one of them. If you have problems with Outlook users not being able to get your replies, try setting this option.</whatsthis> >+ <whatsthis>Microsoft Outlook has a number of shortcomings " >+ "in its implementation of the iCalendar standard; " >+ "this option works around one of them. If you have " >+ "problems with Outlook users not being able to " >+ "get your replies, try setting this option.</whatsthis> > <default>false</default> > </entry> > > <entry name="LegacyBodyInvites" type="Bool"> > <label>Send groupware invitations in the mail body</label> >- <whatsthis>Microsoft Outlook has a number of shortcomings in its implementation of the iCalendar standard; this option works around one of them. If you have problems with Outlook users not being able to get your invitations, try setting this option.</whatsthis> >+ <whatsthis>Microsoft Outlook has a number of shortcomings " >+ "in its implementation of the iCalendar standard; " >+ "this option works around one of them. If you have " >+ "problems with Outlook users not being able to " >+ "get your invitations, try setting this option.</whatsthis> > <default>false</default> > </entry> > </group> >@@ -102,27 +117,59 @@ > <group name="IMAP Resource"> > <entry name="TheIMAPResourceEnabled" type="Bool"> > <default>false</default> >- <whatsthis><p>Enabling this makes it possible to store the entries from the Kontact applications (KOrganizer, KAddressBook, and KNotes.)</p><p>If you want to set this option you must also set the applications to use the IMAP resource; this is done in the KDE Control Center.</p></whatsthis> >+ <whatsthis><p>Enabling this makes it possible to store the " >+ "entries from the Kontact applications (KOrganizer, " >+ "KAddressBook, and KNotes.)</p><p>If you want to set " >+ "this option you must also set the applications to use the " >+ "IMAP resource; this is done in the KDE Control " >+ "Center.</p></whatsthis> > </entry> > > <entry name="HideGroupwareFolders" type="Bool"> > <default>true</default> >- <whatsthis><p>Usually you will not have any reason to see the folders that hold the IMAP resources. But if you need to see them, you can set that here.</p></whatsthis> >+ <whatsthis><p>Usually you will not have any reason to see the " >+ "folders that hold the IMAP resources. But if you " >+ "need to see them, you can set that here.</p></whatsthis> >+ </entry> >+ >+ <entry name="TheIMAPResourceStorageFormat" type="Enum"> >+ <choices> >+ <choice name="IcalVcard"/> >+ <choice name="XML"/> >+ </choices> >+ <default>IcalVcard</default> >+ <whatsthis><p>Choose the storage format of the groupware folders. " >+ "<ul><li>The default format is to use the ical (for calendar folders) and " >+ "vcard (for addressbook folders) standards. " >+ "This format makes all Kontact features available.</li>" >+ "<li>The Kolab XML format uses a custom model that matches more closely " >+ "the one used in Outlook. This format gives better Outlook compatibility, " >+ "when using a Kolab server or a compatible solution.</li></ul></p></whatsthis> > </entry> > > <entry name="TheIMAPResourceFolderParent" type="String"> > <default>inbox</default> >- <whatsthis><p>This chooses the parent of the IMAP resource folders.</p><p>By default, the Kolab server sets the IMAP inbox to be the parent.</p></whatsthis> >+ <whatsthis><p>This chooses the parent of the IMAP resource " >+ "folders.</p><p>By default, the Kolab server sets " >+ "the IMAP inbox to be the parent.</p></whatsthis> > </entry> > > <entry name="TheIMAPResourceAccount" type="Int"> > <default></default> >- <whatsthis><p>This is the ID of the account holding the IMAP resource folders.</p></whatsthis> >+ <whatsthis><p>This is the ID of the account holding the IMAP resource " >+ "folders.</p></whatsthis> > </entry> > > <entry name="TheIMAPResourceFolderLanguage" type="Int"> > <default>0</default> >- <whatsthis><p>If you want to set the folder names of the IMAP storage to your local language, you can choose between these available languages.</p><p> Please note, that the only reason to do so is for compatibility with Microsoft Outlook. It is considered a bad idea to set this, since it makes changing languages impossible. </p><p>So do not set this unless you have to.</p></whatsthis> >+ <whatsthis><p>If you want to set the folder names of the " >+ "IMAP storage to your local language, you can " >+ "choose between these available languages.</p>" >+ "<p> Please note, that the only reason to do so " >+ "is for compatibility with Microsoft Outlook. It " >+ "is considered a bad idea to set this, since it " >+ "makes changing languages impossible. </p><p>So " >+ "do not set this unless you have to.</p></whatsthis> > </entry> > </group> > >@@ -132,7 +179,8 @@ > </entry> > <entry name="PreviousNewFeaturesMD5" type="String" hidden="true"> > <default></default> >- <whatsthis>This value is used to decide whether the KMail Introduction should be displayed.</whatsthis> >+ <whatsthis>This value is used to decide whether the KMail " >+ "Introduction should be displayed.</whatsthis> > </entry> > </group> > >@@ -141,14 +189,18 @@ > <default>0</default> > <min>0</min> > <label>Maximal number of connections per host</label> >- <whatsthis>This can be used to restrict the number of connections per host while checking for new mail. By default the number of connections is unlimited (0).</whatsthis> >+ <whatsthis>This can be used to restrict the number of connections " >+ "per host while checking for new mail. By default the number of " >+ "connections is unlimited (0).</whatsthis> > </entry> > </group> > > <group name="UserInterface"> > <entry name="QuickSearchActive" type="Bool"> > <label>Show quick search line edit</label> >- <whatsthis>This option enabled or disables the search line edit above the message list which can be used to quickly search the information shown in the message list.</whatsthis> >+ <whatsthis>This option enabled or disables the search line edit " >+ "above the message list which can be used to quickly search the " >+ "information shown in the message list.</whatsthis> > <default>true</default> > </entry> > </group> >diff -u -r kdepim/kmail/kmailicalIface.h proko2/kmail/kmailicalIface.h >--- kdepim/kmail/kmailicalIface.h 2004-07-27 00:05:27.000000000 +0200 >+++ proko2/kmail/kmailicalIface.h 2004-08-31 12:36:31.873544784 +0200 >@@ -34,21 +34,48 @@ > > #include <dcopobject.h> > #include <qstringlist.h> >+#include <kurl.h> >+ >+// yes, this is this very header - but it tells dcopidl to include it >+// in _stub.cpp and _skel.cpp files, to get the definition of the structs. >+// ### dcopidlng bug: "" is copied verbatim... >+// The kmail/ is so that it can be found by the resources easily >+#include <kmail/kmailicalIface.h> > > class KMailICalIface : virtual public DCOPObject > { > K_DCOP >+ >+public: > k_dcop: >+ struct SubResource { >+ //dcopidl barfs on those constructors, but dcopidlng works >+ SubResource() {} // for QValueList >+ SubResource( const QString& loc, const QString& lab, bool rw ) >+ : location( loc ), label( lab ), writable( rw ) {} >+ QString location; // unique >+ QString label; // shown to the user >+ bool writable; >+ }; >+ > virtual bool addIncidence( const QString& type, const QString& folder, > const QString& uid, const QString& ical ) = 0; > virtual bool deleteIncidence( const QString& type, const QString& folder, > const QString& uid ) = 0; > virtual QStringList incidences( const QString& type, > const QString& folder ) = 0; >+ /** >+ * Return list of subresources. @p type is >+ * Mail, Calendar, Contact, Note, Task or Journal >+ */ > virtual QStringList subresources( const QString& type ) = 0; > virtual bool isWritableFolder( const QString& type, > const QString& resource ) = 0; > >+ virtual KURL getAttachment( const QString& resource, >+ Q_UINT32 sernum, >+ const QString& filename ) = 0; >+ > // This saves the iCals/vCards in the entries in the folder. > // The format in the string list is uid, entry, uid, entry... > virtual bool update( const QString& type, const QString& folder, >@@ -58,16 +85,68 @@ > virtual bool update( const QString& type, const QString& folder, > const QString& uid, const QString& entry ) = 0; > >+ /// Update a kolab storage entry. Returns the new mail serial number, >+ /// or 0 if something went wrong >+ virtual Q_UINT32 update( const QString& resource, >+ Q_UINT32 sernum, >+ const QString& subject, >+ const QStringList& attachmentURLs, >+ const QStringList& attachmentMimetypes, >+ const QStringList& attachmentNames, >+ const QStringList& deletedAttachments ) = 0; >+ >+ virtual bool deleteIncidenceKolab( const QString& resource, >+ Q_UINT32 sernum ) = 0; >+ virtual QMap<Q_UINT32, QString> incidencesKolab( const QString& mimetype, >+ const QString& resource ) = 0; >+ /** >+ * Return list of subresources. @p contentsType is >+ * Mail, Calendar, Contact, Note, Task or Journal >+ */ >+ virtual QValueList<KMailICalIface::SubResource> subresourcesKolab( const QString& contentsType ) = 0; >+ >+ /// The format of the mails containing other contents than actual mail >+ /// (like contacts, calendar etc.) >+ /// This is currently either ical/vcard, or XML. >+ /// The imap resource uses this folder if ical/vcard storage, >+ /// the kolab resource uses this folder if xml storage. >+ /// For actual mail folders this simply to know which resource handles it >+ /// This enum matches the one defined in kmail.kcfg >+ enum StorageFormat { StorageIcalVcard, StorageXML }; >+ > k_dcop_signals: >+ // For vcard/ical type storage (imap resource) > void incidenceAdded( const QString& type, const QString& folder, > const QString& entry ); >+ void asyncLoadResult( const QStringList& list, const QString& type, >+ const QString& folder ); >+ >+ // For xml kolab style storage >+ void incidenceAdded( const QString& type, const QString& folder, >+ Q_UINT32 sernum, int format, const QString& entry ); >+ void asyncLoadResult( const QMap<Q_UINT32, QString>, const QString& type, >+ const QString& folder ); >+ //common > void incidenceDeleted( const QString& type, const QString& folder, > const QString& uid ); > void signalRefresh( const QString& type, const QString& folder ); > void subresourceAdded( const QString& type, const QString& resource ); >+ void subresourceAdded( const QString& type, const QString& resource, >+ const QString& label ); > void subresourceDeleted( const QString& type, const QString& resource ); >- void asyncLoadResult( const QStringList& list, const QString& type, >- const QString& folder ); >+ > }; > >+inline QDataStream& operator<<( QDataStream& str, const KMailICalIface::SubResource& subResource ) >+{ >+ str << subResource.location << subResource.label << subResource.writable; >+ return str; >+} >+ >+inline QDataStream& operator>>( QDataStream& str, KMailICalIface::SubResource& subResource ) >+{ >+ str >> subResource.location >> subResource.label >> subResource.writable; >+ return str; >+} >+ > #endif >diff -u -r kdepim/kmail/kmailicalifaceimpl.cpp proko2/kmail/kmailicalifaceimpl.cpp >--- kdepim/kmail/kmailicalifaceimpl.cpp 2004-08-13 09:02:55.000000000 +0200 >+++ proko2/kmail/kmailicalifaceimpl.cpp 2004-08-31 12:36:31.438610904 +0200 >@@ -43,33 +43,51 @@ > #include "kmcommands.h" > #include "kmfolderindex.h" > #include "kmmsgdict.h" >+#include "kmmsgpart.h" > #include "kmfolderimap.h" > #include "globalsettings.h" > #include "kmacctmgr.h" > > #include <mimelib/enum.h> >+#include <mimelib/utility.h> >+#include <mimelib/body.h> >+#include <mimelib/mimepp.h> > > #include <kdebug.h> > #include <kiconloader.h> > #include <dcopclient.h> > #include <kmessagebox.h> > #include <kconfig.h> >+#include <kurl.h> > #include <qmap.h> >+#include <ktempfile.h> >+#include <qfile.h> >+#include <qdom.h> >+#include "kmfoldercachedimap.h" >+#include "kmacctcachedimap.h" >+#include "kmacctimap.h" > > // Local helper methods > static void vPartMicroParser( const QString& str, QString& s ); > static void reloadFolderTree(); >+// Local helper class >+class KMailICalIfaceImpl::ExtraFolder { >+public: >+ ExtraFolder( KMFolder* f ) : folder( f ) {} >+ QGuardedPtr<KMFolder> folder; >+}; > > // The index in this array is the KMail::FolderContentsType enum > static const struct { > const char* contentsTypeStr; // the string used in the DCOP interface >+ const char* mimetype; > } s_folderContentsType[] = { >- { "Mail" }, >- { "Calendar" }, >- { "Contact" }, >- { "Note" }, >- { "Task" }, >- { "Journal" } >+ { "Mail", "application/x-vnd.kolab.mail" }, >+ { "Calendar", "application/x-vnd.kolab.event" }, >+ { "Contact", "application/x-vnd.kolab.contact" }, >+ { "Note", "application/x-vnd.kolab.note" }, >+ { "Task", "application/x-vnd.kolab.task" }, >+ { "Journal", "application/x-vnd.kolab.journal" } > }; > > static QString folderContentsType( KMail::FolderContentsType type ) >@@ -77,6 +95,11 @@ > return s_folderContentsType[type].contentsTypeStr; > } > >+static QString folderKolabMimeType( KMail::FolderContentsType type ) >+{ >+ return s_folderContentsType[type].mimetype; >+} >+ > static KMail::FolderContentsType folderContentsType( const QString& type ) > { > for ( uint i = 0 ; i < sizeof s_folderContentsType / sizeof *s_folderContentsType; ++i ) >@@ -98,13 +121,15 @@ > KMailICalIfaceImpl::KMailICalIfaceImpl() > : DCOPObject( "KMailICalIface" ), QObject( 0, "KMailICalIfaceImpl" ), > mContacts( 0 ), mCalendar( 0 ), mNotes( 0 ), mTasks( 0 ), mJournals( 0 ), >- mFolderLanguage( 0 ), mUseResourceIMAP( false ), mHideFolders( true ) >+ mFolderLanguage( 0 ), mUseResourceIMAP( false ), mResourceQuiet( false ), >+ mHideFolders( true ) > { > // Listen to config changes > connect( kmkernel, SIGNAL( configChanged() ), this, SLOT( readConfig() ) ); >+ connect( kmkernel, SIGNAL( folderRemoved( KMFolder* ) ), >+ this, SLOT( slotFolderRemoved( KMFolder* ) ) ); > > mExtraFolders.setAutoDelete( true ); >- mAccumulators.setAutoDelete( true ); > } > > // Receive an iCal or vCard from the resource >@@ -114,44 +139,303 @@ > const QString& ical ) > { > kdDebug(5006) << "KMailICalIfaceImpl::addIncidence( " << type << ", " >- << uid << ", " << ical << " )" << endl; >+ << uid << ", " << ical << " )" << endl; > > if( !mUseResourceIMAP ) > return false; > >+ // Find the folder >+ KMFolder* f = folderFromType( type, folder ); >+ if( !f ) { >+ kdError(5006) << "addIncidence(" << type << "," << folder << ") : Not an IMAP resource folder" << endl; >+ return false; >+ } >+ if ( storageFormat( f ) != StorageIcalVcard ) { >+ kdError(5006) << "addIncidence(" << type << "," << folder << ") : Folder has wrong storage format " << storageFormat( f ) << endl; >+ return false; >+ } >+ > bool rc = false; >+ bool quiet = mResourceQuiet; >+ mResourceQuiet = true; >+ // Make a new message for the incidence >+ KMMessage* msg = new KMMessage(); >+ msg->initHeader(); >+ msg->setType( DwMime::kTypeText ); >+ if( f == mContacts ) { >+ msg->setSubtype( DwMime::kSubtypeXVCard ); >+ msg->setHeaderField( "Content-Type", "Text/X-VCard; charset=\"utf-8\"" ); >+ msg->setSubject( "vCard " + uid ); >+ } else { >+ msg->setSubtype( DwMime::kSubtypeVCal ); >+ msg->setHeaderField("Content-Type", >+ "text/calendar; method=REQUEST; charset=\"utf-8\""); >+ msg->setSubject( "iCal " + uid ); >+ } >+ msg->setBodyEncoded( ical.utf8() ); > >- if ( !mInTransit.contains( uid ) ) { >- mInTransit.insert( uid, true ); >+ // Mark the message as read and store it in the folder >+ msg->touch(); >+ f->addMsg( msg ); >+ >+ rc = true; >+ >+ mResourceQuiet = quiet; >+ return rc; >+} >+ >+// Helper function to find an attachment of a given mimetype >+// Can't use KMMessage::findDwBodyPart since it only works with known mimetypes. >+static DwBodyPart* findBodyPartByMimeType( const KMMessage& msg, const char* sType, const char* sSubtype ) >+{ >+ // quickly searching for our message part: since Kolab parts are >+ // top-level parts we do *not* have to travel into embedded multiparts >+ DwBodyPart* part = msg.getFirstDwBodyPart(); >+ while( part ){ >+ // kdDebug() << part->Headers().ContentType().TypeStr().c_str() << " " >+ // << part->Headers().ContentType().SubtypeStr().c_str() << endl; >+ if ( part->hasHeaders() >+ && part->Headers().HasContentType() >+ && part->Headers().ContentType().TypeStr() == sType >+ && part->Headers().ContentType().SubtypeStr() == sSubtype) >+ return part; >+ part = part->Next(); > } >+ return 0; >+} > >- // Find the folder >- KMFolder* f = folderFromType( type, folder ); >- if( f ) { >- // Make a new message for the incidence >- KMMessage* msg = new KMMessage(); >- msg->initHeader(); >- msg->setType( DwMime::kTypeText ); >- if( f == mContacts ) { >- msg->setSubtype( DwMime::kSubtypeXVCard ); >- msg->setHeaderField( "Content-Type", "Text/X-VCard; charset=\"utf-8\"" ); >- msg->setSubject( "vCard " + uid ); >- } else { >- msg->setSubtype( DwMime::kSubtypeVCal ); >- msg->setHeaderField("Content-Type", >- "text/calendar; method=REQUEST; charset=\"utf-8\""); >- msg->setSubject( "iCal " + uid ); >+// Helper function to find an attachment with a given filename >+static DwBodyPart* findBodyPart( const KMMessage& msg, const QString& attachmentName ) >+{ >+ // quickly searching for our message part: since Kolab parts are >+ // top-level parts we do *not* have to travel into embedded multiparts >+ for ( DwBodyPart* part = msg.getFirstDwBodyPart(); part; part = part->Next() ) { >+ //kdDebug(5006) << "findBodyPart: - " << part->Headers().ContentDisposition().Filename().c_str() << endl; >+ if ( part->hasHeaders() >+ && attachmentName == part->Headers().ContentDisposition().Filename().c_str() ) >+ return part; >+ } >+ return 0; >+} >+ >+#if 0 >+static void debugBodyParts( const char* foo, const KMMessage& msg ) >+{ >+ kdDebug() << "--debugBodyParts " << foo << "--" << endl; >+ for ( DwBodyPart* part = msg.getFirstDwBodyPart(); part; part = part->Next() ) { >+ if ( part->hasHeaders() ) { >+ kdDebug() << " bodypart: " << part << endl; >+ kdDebug() << " " << part->Headers().AsString().c_str() << endl; > } >- msg->setBodyEncoded( ical.utf8() ); >+ else >+ kdDebug() << " part " << part << " has no headers" << endl; >+ } >+} >+#else >+inline static void debugBodyParts( const char*, const KMMessage& ) {} >+#endif >+ >+ >+// Add (or overwrite, resp.) an attachment in an existing mail, >+// attachments must be local files, they are identified by their names. >+// If lookupByName if false the attachment to replace is looked up by mimetype. >+// return value: wrong if attachment could not be added/updated >+bool KMailICalIfaceImpl::updateAttachment( KMMessage& msg, >+ const QString& attachmentURL, >+ const QString& attachmentName, >+ const QString& attachmentMimetype, >+ bool lookupByName ) >+{ >+ kdDebug(5006) << "KMailICalIfaceImpl::updateAttachment( " << attachmentURL << " )" << endl; >+ >+ bool bOK = false; >+ >+ KURL url( attachmentURL ); >+ if ( url.isValid() && url.isLocalFile() ) { >+ const QString fileName( url.path() ); >+ QFile file( fileName ); >+ if( file.open( IO_ReadOnly ) ) { >+ QByteArray rawData = file.readAll(); >+ file.close(); >+ >+ // create the new message part with data read from temp file >+ KMMessagePart msgPart; >+ msgPart.setName( attachmentName ); >+ >+ const int iSlash = attachmentMimetype.find('/'); >+ const QCString sType = attachmentMimetype.left( iSlash ).latin1(); >+ const QCString sSubtype = attachmentMimetype.mid( iSlash+1 ).latin1(); >+ msgPart.setTypeStr( sType ); >+ msgPart.setSubtypeStr( sSubtype ); >+ QCString ctd("attachment;\n filename=\""); >+ ctd.append( attachmentName.latin1() ); >+ ctd.append("\""); >+ msgPart.setContentDisposition( ctd ); >+ QValueList<int> dummy; >+ msgPart.setBodyAndGuessCte( rawData, dummy ); >+ msgPart.setPartSpecifier( fileName ); >+ >+ DwBodyPart* newPart = msg.createDWBodyPart( &msgPart ); >+ // This whole method is a bit special. We mix code for writing and code for reading. >+ // E.g. we need to parse the content-disposition again for ContentDisposition().Filename() >+ // to work later on. >+ newPart->Headers().ContentDisposition().Parse(); >+ >+ DwBodyPart* part = lookupByName ? findBodyPart( msg, attachmentName ) >+ : findBodyPartByMimeType( msg, sType, sSubtype ); >+ if ( part ) { >+ // Make sure the replacing body part is pointing >+ // to the same next part as the original body part. >+ newPart->SetNext( part->Next() ); >+ // call DwBodyPart::operator = >+ // which calls DwEntity::operator = >+ *part = *newPart; >+ delete newPart; >+ msg.setNeedsAssembly(); >+ kdDebug(5006) << "Attachment " << attachmentName << " updated." << endl; >+ } else { >+ msg.addDwBodyPart( newPart ); >+ kdDebug(5006) << "Attachment " << attachmentName << " added." << endl; >+ } >+ bOK = true; >+ }else{ >+ kdDebug(5006) << "Attachment " << attachmentURL << " can not be read." << endl; >+ } >+ }else{ >+ kdDebug(5006) << "Attachment " << attachmentURL << " not a local file." << endl; >+ } >+ >+ return bOK; >+} >+ >+// Look for the attachment with the right mimetype >+bool KMailICalIfaceImpl::kolabXMLFoundAndDecoded( const KMMessage& msg, const QString& mimetype, QString& s ) >+{ >+ const int iSlash = mimetype.find('/'); >+ const QCString sType = mimetype.left( iSlash ).latin1(); >+ const QCString sSubtype = mimetype.mid( iSlash+1 ).latin1(); >+ DwBodyPart* part = findBodyPartByMimeType( msg, sType, sSubtype ); >+ if ( part ) { >+ KMMessagePart msgPart; >+ KMMessage::bodyPart(part, &msgPart); >+ s = msgPart.bodyToUnicode(); >+ return true; >+ } >+ return false; >+} >+ >+// Delete an attachment in an existing mail. >+// return value: wrong if attachment could not be deleted >+// >+// This code could be optimized: for now we just replace >+// the attachment by an empty dummy attachment since Mimelib >+// does not provide an option for deleting attachments yet. >+bool KMailICalIfaceImpl::deleteAttachment( KMMessage& msg, >+ const QString& attachmentName ) >+{ >+ kdDebug(5006) << "KMailICalIfaceImpl::deleteAttachment( " << attachmentName << " )" << endl; >+ >+ bool bOK = false; >+ >+ // quickly searching for our message part: since Kolab parts are >+ // top-level parts we do *not* have to travel into embedded multiparts >+ DwBodyPart* part = findBodyPart( msg, attachmentName ); >+ if ( part ) { >+ msg.getTopLevelPart()->Body().RemoveBodyPart( part ); >+ delete part; >+ msg.setNeedsAssembly(); >+ kdDebug(5006) << "Attachment deleted." << endl; >+ bOK = true; >+ } >+ >+ if( !bOK ){ >+ kdDebug(5006) << "Attachment " << attachmentName << " not found." << endl; >+ } >+ >+ return bOK; >+} >+ >+ >+// Store a new entry that was received from the resource >+Q_UINT32 KMailICalIfaceImpl::addIncidenceKolab( KMFolder& folder, >+ const QString& subject, >+ const QStringList& attachmentURLs, >+ const QStringList& attachmentNames, >+ const QStringList& attachmentMimetypes ) >+{ >+ kdDebug(5006) << "KMailICalIfaceImpl::addIncidenceKolab( " << attachmentNames << " )" << endl; >+ >+ Q_UINT32 sernum = 0; >+ bool bAttachOK = true; >+ bool quiet = mResourceQuiet; >+ mResourceQuiet = true; >+ >+ // Make a new message for the incidence >+ KMMessage* msg = new KMMessage(); >+ msg->initHeader(); >+ msg->setType( DwMime::kTypeMultipart ); >+ msg->setSubtype( DwMime::kSubtypeMixed ); >+ msg->headers().ContentType().CreateBoundary( 0 ); >+ msg->headers().ContentType().Assemble(); >+ msg->setSubject( subject ); >+ msg->setAutomaticFields( true ); >+ // add a first body part to be displayed by all mailer >+ // than cn NOT display Kolab data: no matter if these >+ // mailers are MIME compliant or not >+ KMMessagePart firstPart; >+ firstPart.setType( DwMime::kTypeText ); >+ firstPart.setSubtype( DwMime::kSubtypePlain ); >+ const char * firstPartTextUntranslated = I18N_NOOP( >+ "This is a Kolab Groupware object.\nTo view this object you" >+ " will need an email client that can understand the Kolab" >+ " Groupware format.\nFor a list of such email clients please" >+ " visit\nhttp://www.kolab.org/kolab-clients.html"); >+ QString firstPartText = i18n( firstPartTextUntranslated ); >+ if ( firstPartText != firstPartTextUntranslated ) { >+ firstPartText.append("\n\n-----------------------------------------------------\n\n"); >+ firstPartText.append( firstPartTextUntranslated ); >+ } >+ firstPart.setBodyFromUnicode( firstPartText ); >+ msg->addBodyPart( &firstPart ); >+ >+ Q_ASSERT( attachmentMimetypes.count() == attachmentURLs.count() ); >+ Q_ASSERT( attachmentNames.count() == attachmentURLs.count() ); >+ // Add all attachments by reading them from their temp. files >+ QStringList::ConstIterator itmime = attachmentMimetypes.begin(); >+ QStringList::ConstIterator iturl = attachmentURLs.begin(); >+ for( QStringList::ConstIterator itname = attachmentNames.begin(); >+ itname != attachmentNames.end() >+ && itmime != attachmentMimetypes.end() >+ && iturl != attachmentURLs.end(); >+ ++itname, ++iturl, ++itmime ){ >+ bool bymimetype = (*itmime).startsWith( "application/x-vnd.kolab." ); >+ if( !updateAttachment( *msg, *iturl, *itname, *itmime, !bymimetype ) ){ >+ kdWarning(5006) << "Attachment error, can not add Incidence." << endl; >+ bAttachOK = false; >+ break; >+ } >+ if ( bymimetype ) >+ msg->setHeaderField( "X-Kolab-Type", *itmime ); >+ } > >+ if( bAttachOK ){ > // Mark the message as read and store it in the folder >+ msg->cleanupHeader(); >+ //debugBodyParts( "after cleanup", *msg ); > msg->touch(); >- f->addMsg( msg ); >- rc = true; >+ if ( folder.addMsg( msg ) == 0 ) >+ // Message stored >+ sernum = msg->getMsgSerNum(); >+ kdDebug(5006) << "addIncidenceKolab(): Message done and saved. Sernum: " >+ << sernum << endl; >+ >+ //debugBodyParts( "after addMsg", *msg ); >+ > } else >- kdError(5006) << "Not an IMAP resource folder" << endl; >+ kdError(5006) << "addIncidenceKolab(): Message *NOT* saved!\n"; > >- return rc; >+ mResourceQuiet = quiet; >+ return sernum; > } > > // The resource orders a deletion >@@ -165,22 +449,70 @@ > kdDebug(5006) << "KMailICalIfaceImpl::deleteIncidence( " << type << ", " > << uid << " )" << endl; > >+ // Find the folder >+ KMFolder* f = folderFromType( type, folder ); >+ >+ if( !f ) { >+ kdError(5006) << "deleteIncidence(" << type << "," << folder << ") : Not an IMAP resource folder" << endl; >+ return false; >+ } >+ if ( storageFormat( f ) != StorageIcalVcard ) { >+ kdError(5006) << "deleteIncidence(" << type << "," << folder << ") : Folder has wrong storage format " << storageFormat( f ) << endl; >+ return false; >+ } >+ > bool rc = false; >+ bool quiet = mResourceQuiet; >+ mResourceQuiet = true; > >- // Find the folder and the incidence in it >- KMFolder* f = folderFromType( type, folder ); >- if( f ) { >- KMMessage* msg = findMessageByUID( uid, f ); >- if( msg ) { >- // Message found - delete it and return happy >- deleteMsg( msg ); >- rc = true; >- mUIDToSerNum.remove( uid ); >- } else >- kdDebug(5006) << type << " not found, cannot remove uid " << uid << endl; >- } else >- kdError(5006) << "Not an IMAP resource folder" << endl; >+ KMMessage* msg = findMessageByUID( uid, f ); >+ if( msg ) { >+ // Message found - delete it and return happy >+ deleteMsg( msg ); >+ rc = true; >+ } else { >+ kdDebug(5006) << "Message not found, cannot remove id " << uid << endl; >+ } > >+ mResourceQuiet = quiet; >+ return rc; >+} >+ >+bool KMailICalIfaceImpl::deleteIncidenceKolab( const QString& resource, >+ Q_UINT32 sernum ) >+{ >+ // Find the message from the serial number and delete it. >+ if( !mUseResourceIMAP ) >+ return false; >+ >+ kdDebug(5006) << "KMailICalIfaceImpl::deleteIncidenceKolab( " >+ << resource << ", " << sernum << ")\n"; >+ >+ // Find the folder >+ KMFolder* f = findResourceFolder( resource ); >+ if( !f ) { >+ kdError(5006) << "deleteIncidenceKolab(" << resource << ") : Not an IMAP resource folder" << endl; >+ return false; >+ } >+ if ( storageFormat( f ) != StorageXML ) { >+ kdError(5006) << "deleteIncidenceKolab(" << resource << ") : Folder has wrong storage format " << storageFormat( f ) << endl; >+ return false; >+ } >+ >+ bool rc = false; >+ bool quiet = mResourceQuiet; >+ mResourceQuiet = true; >+ >+ KMMessage* msg = findMessageBySerNum( sernum, f ); >+ if( msg ) { >+ // Message found - delete it and return happy >+ deleteMsg( msg ); >+ rc = true; >+ } else { >+ kdDebug(5006) << "Message not found, cannot remove serNum " << sernum << endl; >+ } >+ >+ mResourceQuiet = quiet; > return rc; > } > >@@ -196,76 +528,77 @@ > QStringList ilist; > > KMFolder* f = folderFromType( type, folder ); >- if ( f ) { >- f->open(); >- QString s; >- for( int i=0; i<f->count(); ++i ) { >- bool unget = !f->isMessage(i); >- KMMessage *msg = f->getMsg( i ); >- Q_ASSERT( msg ); >- if( msg->isComplete() ) { >- if( KMGroupware::vPartFoundAndDecoded( msg, s ) ) { >- QString uid( "UID" ); >- vPartMicroParser( s, uid ); >- const Q_UINT32 sernum = msg->getMsgSerNum(); >- kdDebug(5006) << "Insert uid: " << uid << endl; >- mUIDToSerNum.insert( uid, sernum ); >- ilist << s; >- } >- if( unget ) f->unGetMsg(i); >- } else { >- // message needs to be gotten first, once it arrives, we'll >- // accumulate it and add it to the resource >- if ( !mAccumulators[ folder ] ) >- mAccumulators.insert( folder, new Accumulator( type, folder, f->count() )); >- if ( unget ) mTheUnGetMes.insert( msg->getMsgSerNum(), true ); >- FolderJob *job = msg->parent()->createJob( msg ); >- connect( job, SIGNAL( messageRetrieved( KMMessage* ) ), >- this, SLOT( slotMessageRetrieved( KMMessage* ) ) ); >- job->start(); >- } >- } >+ if( !f ) { >+ kdError(5006) << "incidences(" << type << "," << folder << ") : Not an IMAP resource folder" << endl; >+ return ilist; >+ } >+ if ( storageFormat( f ) != StorageIcalVcard ) { >+ kdError(5006) << "incidences(" << type << "," << folder << ") : Folder has wrong storage format " << storageFormat( f ) << endl; >+ return ilist; >+ } >+ >+ f->open(); >+ QString s; >+ for( int i=0; i<f->count(); ++i ) { >+ bool unget = !f->isMessage(i); >+ if( KMGroupware::vPartFoundAndDecoded( f->getMsg( i ), s ) ) >+ ilist << s; >+ if( unget ) f->unGetMsg(i); > } >+ > return ilist; > } > >-void KMailICalIfaceImpl::slotMessageRetrieved( KMMessage* msg ) >+QMap<Q_UINT32, QString> KMailICalIfaceImpl::incidencesKolab( const QString& mimetype, >+ const QString& resource ) > { >- if( !msg ) return; >+ /// Get the mimetype attachments from this folder. Returns a >+ /// QMap with serialNumber/attachment pairs. >+ /// (serial numbers of the mail are provided for easier later update) > >- KMFolder *parent = msg->parent(); >- Q_ASSERT( parent ); >- Q_UINT32 sernum = msg->getMsgSerNum(); >- >- // do we have an accumulator for this folder? >- Accumulator *ac = mAccumulators.find( parent->location() ); >- if( ac ) { >- QString s; >- if ( !KMGroupware::vPartFoundAndDecoded( msg, s ) ) return; >- QString uid( "UID" ); >- vPartMicroParser( s, uid ); >- const Q_UINT32 sernum = msg->getMsgSerNum(); >- mUIDToSerNum.insert( uid, sernum ); >- ac->add( s ); >- if( ac->isFull() ) { >- /* if this was the last one we were waiting for, tell the resource >- * about the new incidences and clean up. */ >- asyncLoadResult( ac->incidences, ac->type, ac->folder ); >- mAccumulators.remove( ac->folder ); // autodelete >- } >- } else { >- /* We are not accumulating for this folder, so this one was added >- * by KMail. Do your thang. */ >- slotIncidenceAdded( msg->parent(), msg->getMsgSerNum() ); >- } >+ QMap<Q_UINT32, QString> aMap; >+ if( !mUseResourceIMAP ) >+ return aMap; > >- if ( mTheUnGetMes.contains( sernum ) ) { >- mTheUnGetMes.remove( sernum ); >- int i = 0; >- KMFolder* folder = 0; >- kmkernel->msgDict()->getLocation( sernum, &folder, &i ); >- folder->unGetMsg( i ); >+ kdDebug(5006) << "KMailICalIfaceImpl::incidencesKolab( " << mimetype << ", " >+ << resource << " )" << endl; >+ >+ KMFolder* f = findResourceFolder( resource ); >+ if( !f ) { >+ kdError(5006) << "incidencesKolab(" << resource << ") : Not an IMAP resource folder" << endl; >+ return aMap; >+ } >+ if ( storageFormat( f ) != StorageXML ) { >+ kdError(5006) << "incidencesKolab(" << resource << ") : Folder has wrong storage format " << storageFormat( f ) << endl; >+ return aMap; >+ } >+ >+ f->open(); >+ QString s; >+ for( int i=0; i<f->count(); ++i ) { >+ bool unget = !f->isMessage(i); >+ KMMessage* msg = f->getMsg( i ); >+ if( msg ){ >+ const int iSlash = mimetype.find('/'); >+ const QCString sType = mimetype.left( iSlash ).latin1(); >+ const QCString sSubtype = mimetype.mid( iSlash+1 ).latin1(); >+ if ( sType.isEmpty() || sSubtype.isEmpty() ) { >+ kdError(5006) << mimetype << " not an type/subtype combination" << endl; >+ } else { >+ DwBodyPart* dwPart = findBodyPartByMimeType( *msg, sType, sSubtype ); >+ if ( dwPart ) { >+ KMMessagePart msgPart; >+ KMMessage::bodyPart(dwPart, &msgPart); >+ aMap.insert(msg->getMsgSerNum(), msgPart.bodyToUnicode()); >+ } else { >+ // This is *not* an error: it may be that not all of the messages >+ // have a message part that is matching the wanted MIME type >+ } >+ } >+ if( unget ) f->unGetMsg(i); >+ } > } >+ return aMap; > } > > QStringList KMailICalIfaceImpl::subresources( const QString& type ) >@@ -274,19 +607,52 @@ > > // Add the default one > KMFolder* f = folderFromType( type, QString::null ); >- if ( f ) >+ if ( f && storageFormat( f ) == StorageIcalVcard ) > lst << f->location(); > > // Add the extra folders > KMail::FolderContentsType t = folderContentsType( type ); > QDictIterator<ExtraFolder> it( mExtraFolders ); >- for ( ; it.current(); ++it ) >- if ( it.current()->type == t ) >- lst << it.current()->folder->location(); >+ for ( ; it.current(); ++it ) { >+ f = it.current()->folder; >+ if ( f && f->storage()->contentsType() == t >+ && storageFormat( f ) == StorageIcalVcard ) >+ lst << f->location(); >+ } > > return lst; > } > >+QValueList<KMailICalIfaceImpl::SubResource> KMailICalIfaceImpl::subresourcesKolab( const QString& contentsType ) >+{ >+ QValueList<SubResource> subResources; >+ >+ // Add the default one >+ KMFolder* f = folderFromType( contentsType, QString::null ); >+ if ( f && storageFormat( f ) == StorageXML ) { >+ subResources.append( SubResource( f->location(), f->prettyURL(), !f->isReadOnly() ) ); >+ kdDebug(5006) << "Adding(1) folder " << f->location() << " " << >+ ( f->isReadOnly() ? "readonly" : "" ) << endl; >+ } >+ >+ // get the extra ones >+ const KMail::FolderContentsType t = folderContentsType( contentsType ); >+ QDictIterator<ExtraFolder> it( mExtraFolders ); >+ for ( ; it.current(); ++it ){ >+ f = it.current()->folder; >+ if ( f && f->storage()->contentsType() == t >+ && storageFormat( f ) == StorageXML ) { >+ subResources.append( SubResource( f->location(), f->prettyURL(), !f->isReadOnly() ) ); >+ kdDebug(5006) << "Adding(2) folder " << f->location() << " " << >+ ( f->isReadOnly() ? "readonly" : "" ) << endl; >+ } >+ } >+ >+ if ( subResources.isEmpty() ) >+ kdDebug(5006) << "subresourcesKolab: No folder found for " << contentsType << endl; >+ return subResources; >+} >+ > bool KMailICalIfaceImpl::isWritableFolder( const QString& type, > const QString& resource ) > { >@@ -336,44 +702,223 @@ > return false; > > kdDebug(5006) << "Update( " << type << ", " << folder << ", " << uid << ")\n"; >- bool rc = true; > >- if ( !mInTransit.contains( uid ) ) { >- mInTransit.insert( uid, true ); >+ // Find the folder and the incidence in it >+ KMFolder* f = folderFromType( type, folder ); >+ if( !f ) { >+ kdError(5006) << "update(" << type << "," << folder << ") : Not an IMAP resource folder" << endl; >+ return false; >+ } >+ if ( storageFormat( f ) != StorageIcalVcard ) { >+ kdError(5006) << "update(" << type << "," << folder << ") : Folder has wrong storage format " << storageFormat( f ) << endl; >+ return false; >+ } >+ >+ bool rc = true; >+ bool quiet = mResourceQuiet; >+ mResourceQuiet = true; >+ KMMessage* msg = findMessageByUID( uid, f ); >+ if( msg ) { >+ // Message found - update it >+ deleteMsg( msg ); >+ addIncidence( type, folder, uid, entry ); >+ rc = true; > } else { >- // this is reentrant, if a new update comes in, we'll just >- // replace older ones >- mPendingUpdates.insert( uid, entry ); >+ kdDebug(5006) << type << " not found, cannot update uid " << uid << endl; >+ // Since it doesn't seem to be there, save it instead >+ addIncidence( type, folder, uid, entry ); >+ } >+ mResourceQuiet = quiet; >+ return rc; >+} >+ >+Q_UINT32 KMailICalIfaceImpl::update( const QString& resource, >+ Q_UINT32 sernum, >+ const QString& subject, >+ const QStringList& attachmentURLs, >+ const QStringList& attachmentMimetypes, >+ const QStringList& attachmentNames, >+ const QStringList& deletedAttachments ) >+{ >+ Q_UINT32 rc = 0; >+ >+ // This finds the message with serial number "sernum", sets the >+ // xml attachments to hold the contents of "xml", and updates all >+ // attachments. >+ // The mail can have additional attachments, and these are not >+ // touched! They belong to other clients - like Outlook >+ // So we delete all the attachments listed in the >+ // "deletedAttachments" arg, and then update/add all the attachments >+ // given by the urllist attachments. >+ >+ // If the mail does not already exist, id will not be a valid serial >+ // number, and the mail is just added instead. In this case >+ // the deletedAttachments can be forgotten. >+ if( !mUseResourceIMAP ) >+ return rc; >+ >+ Q_ASSERT( !resource.isEmpty() ); >+ >+ kdDebug(5006) << "KMailICalIfaceImpl::update( " << resource << ", " << sernum << " )\n"; >+ kdDebug(5006) << attachmentURLs << "\n"; >+ kdDebug(5006) << attachmentMimetypes << "\n"; >+ kdDebug(5006) << attachmentNames << "\n"; >+ kdDebug(5006) << "deleted attachments:" << deletedAttachments << "\n"; >+ >+ // Find the folder >+ KMFolder* f = findResourceFolder( resource ); >+ if( !f ) { >+ kdError(5006) << "update(" << resource << ") : Not an IMAP resource folder" << endl; >+ return rc; >+ } >+ if ( storageFormat( f ) != StorageXML ) { >+ kdError(5006) << "update(" << resource << ") : Folder has wrong storage format " << storageFormat( f ) << endl; > return rc; > } > >- // Find the folder and the incidence in it >- KMFolder* f = folderFromType( type, folder ); >- if( f ) { >- KMMessage* msg = findMessageByUID( uid, f ); >- if( msg ) { >- // Message found - update it >- deleteMsg( msg ); >- mUIDToSerNum.remove( uid ); >- } else { >- kdDebug(5006) << type << " not found, cannot update uid " << uid << endl; >+ f->open(); >+ bool quiet = mResourceQuiet; >+ mResourceQuiet = true; >+ >+ kdDebug(5006) << "Updating in folder " << f << " " << f->location() << endl; >+ KMMessage* msg = 0; >+ if ( sernum != 0 ) >+ msg = findMessageBySerNum( sernum, f ); >+ if ( msg ) { >+ // Message found - make a copy and update it: >+ KMMessage* newMsg = new KMMessage( *msg ); >+ newMsg->setSubject( subject ); >+ newMsg->setParent( 0 ); // workaround strange line in KMMsgBase::assign. newMsg is not in any folder yet. >+ >+ // Delete some attachments according to list >+ for( QStringList::ConstIterator it = deletedAttachments.begin(); >+ it != deletedAttachments.end(); >+ ++it ){ >+ if( !deleteAttachment( *newMsg, *it ) ){ >+ // Note: It is _not_ an error if an attachment was already deleted. >+ } > } >- addIncidence( type, folder, uid, entry ); >- } else { >- kdError(5006) << "Not an IMAP resource folder" << endl; >- rc = false; >+ >+ // Add all attachments by reading them from their temp. files >+ QStringList::ConstIterator iturl = attachmentURLs.begin(); >+ QStringList::ConstIterator itmime = attachmentMimetypes.begin(); >+ QStringList::ConstIterator itname = attachmentNames.begin(); >+ for( ; >+ iturl != attachmentURLs.end() >+ && itmime != attachmentMimetypes.end() >+ && itname != attachmentNames.end(); >+ ++iturl, ++itname, ++itmime ){ >+ bool bymimetype = (*itname).startsWith( "application/x-vnd.kolab." ); >+ if( !updateAttachment( *newMsg, *iturl, *itname, *itmime, bymimetype ) ){ >+ kdDebug(5006) << "Attachment error, can not update attachment " << *iturl << endl; >+ break; >+ } >+ } >+ >+ //debugBodyParts( "in update, before cleanup", *newMsg ); >+ >+ // This is necessary for the headers to be readable later on >+ newMsg->cleanupHeader(); >+ >+ //debugBodyParts( "in update, after cleanup", *newMsg ); >+ >+ deleteMsg( msg ); >+ if ( f->addMsg( newMsg ) == 0 ) { >+ // Message stored >+ rc = newMsg->getMsgSerNum(); >+ kdDebug(5006) << "forget about " << sernum << ", it's " << rc << " now" << endl; >+ } >+ >+ }else{ >+ // Message not found - store it newly >+ rc = addIncidenceKolab( *f, subject, >+ attachmentURLs, >+ attachmentNames, >+ attachmentMimetypes ); > } >+ >+ f->close(); >+ >+ mResourceQuiet = quiet; > return rc; > } > >+KURL KMailICalIfaceImpl::getAttachment( const QString& resource, >+ Q_UINT32 sernum, >+ const QString& filename ) >+{ >+ // This finds the attachment with the filename, saves it to a >+ // temp file and returns a URL to it. It's up to the resource >+ // to delete the tmp file later. >+ if( !mUseResourceIMAP ) >+ return KURL(); >+ >+ kdDebug(5006) << "KMailICalIfaceImpl::getAttachment( " >+ << resource << ", " << sernum << ", " << filename << " )\n"; >+ >+ // Find the folder >+ KMFolder* f = findResourceFolder( resource ); >+ if( !f ) { >+ kdError(5006) << "getAttachment(" << resource << ") : Not an IMAP resource folder" << endl; >+ return KURL(); >+ } >+ if ( storageFormat( f ) != StorageXML ) { >+ kdError(5006) << "getAttachment(" << resource << ") : Folder has wrong storage format " << storageFormat( f ) << endl; >+ return KURL(); >+ } >+ >+ KURL url; >+ >+ bool bOK = false; >+ bool quiet = mResourceQuiet; >+ mResourceQuiet = true; >+ >+ KMMessage* msg = findMessageBySerNum( sernum, f ); >+ if( msg ) { >+ // Message found - look for the attachment: >+ >+ DwBodyPart* part = findBodyPart( *msg, filename ); >+ if ( part ) { >+ // Save the contents of the attachment. >+ KMMessagePart aPart; >+ msg->bodyPart( part, &aPart ); >+ QByteArray rawData( aPart.bodyDecodedBinary() ); >+ >+ KTempFile file; >+ file.file()->writeBlock( rawData.data(), rawData.size() ); >+ >+ url.setPath( file.name() ); >+ >+ bOK = true; >+ } >+ >+ if( !bOK ){ >+ kdDebug(5006) << "Attachment " << filename << " not found." << endl; >+ } >+ }else{ >+ kdDebug(5006) << "Message not found." << endl; >+ } >+ >+ mResourceQuiet = quiet; >+ return url; >+} >+ >+ >+void KMailICalIfaceImpl::slotFolderRemoved( KMFolder* folder ) >+{ >+ // pretend the folder just changed back to the mail type, which >+ // does the right thing, namely remove resource >+ folderContentsTypeChanged( folder, KMail::ContentsTypeMail ); >+} >+ > // KMail added a file to one of the groupware folders > void KMailICalIfaceImpl::slotIncidenceAdded( KMFolder* folder, > Q_UINT32 sernum ) > { >- if( !mUseResourceIMAP ) >+ if( mResourceQuiet || !mUseResourceIMAP ) > return; > >- QString type = icalFolderType( folder ); >+ QString type = folderContentsType( folder->storage()->contentsType() ); > if( !type.isEmpty() ) { > // Get the index of the mail > int i = 0; >@@ -381,41 +926,26 @@ > kmkernel->msgDict()->getLocation( sernum, &aFolder, &i ); > assert( folder == aFolder ); > >- // Read the iCal or vCard > bool unget = !folder->isMessage( i ); > QString s; >- KMMessage *msg = folder->getMsg( i ); >- if( !msg ) return; >- if( msg->isComplete() ) { >- if ( !KMGroupware::vPartFoundAndDecoded( msg, s ) ) return; >+ bool ok = false; >+ KMMessage* msg = folder->getMsg( i ); >+ StorageFormat format = storageFormat( folder ); >+ switch( format ) { >+ case StorageIcalVcard: >+ // Read the iCal or vCard >+ ok = KMGroupware::vPartFoundAndDecoded( msg, s ); >+ break; >+ case StorageXML: >+ // Read the XML from the attachment with the given mimetype >+ ok = kolabXMLFoundAndDecoded( *msg, folderKolabMimeType( folder->storage()->contentsType() ), s ); >+ break; >+ } >+ if ( ok ) { > kdDebug(5006) << "Emitting DCOP signal incidenceAdded( " << type >- << ", " << folder->location() << ", " << s << " )" << endl; >- QString uid( "UID" ); >- vPartMicroParser( s, uid ); >- const Q_UINT32 sernum = msg->getMsgSerNum(); >- kdDebug(5006) << "Insert uid: " << uid << endl; >- mUIDToSerNum.insert( uid, sernum ); >- // tell the resource if we didn't trigger this ourselves >- if( !mInTransit.contains( uid ) ) >- incidenceAdded( type, folder->location(), s ); >- else >- mInTransit.remove( uid ); >- >- // Check if new updates have since arrived, if so, trigger them >- if ( mPendingUpdates.contains( uid ) ) { >- kdDebug(5006) << "KMailICalIfaceImpl::slotIncidenceAdded - Pending Update" << endl; >- QString entry = mPendingUpdates[ uid ]; >- mPendingUpdates.remove( uid ); >- update( type, folder->location(), uid, entry ); >- } >- } else { >- // go get the rest of it, then try again >- if ( unget ) mTheUnGetMes.insert( msg->getMsgSerNum(), true ); >- FolderJob *job = msg->parent()->createJob( msg ); >- connect( job, SIGNAL( messageRetrieved( KMMessage* ) ), >- this, SLOT( slotMessageRetrieved( KMMessage* ) ) ); >- job->start(); >- return; >+ << ", " << folder->location() << ", " << s << " )" << endl; >+ incidenceAdded( type, folder->location(), s ); >+ incidenceAdded( type, folder->location(), sernum, format, s ); > } > if( unget ) folder->unGetMsg(i); > } else >@@ -426,10 +956,11 @@ > void KMailICalIfaceImpl::slotIncidenceDeleted( KMFolder* folder, > Q_UINT32 sernum ) > { >- if( !mUseResourceIMAP ) >+ if( mResourceQuiet || !mUseResourceIMAP ) > return; > >- QString type = icalFolderType( folder ); >+ QString type = folderContentsType( folder->storage()->contentsType() ); >+ kdDebug(5006) << folder << " " << type << " " << sernum << endl; > if( !type.isEmpty() ) { > // Get the index of the mail > int i = 0; >@@ -440,13 +971,36 @@ > // Read the iCal or vCard > bool unget = !folder->isMessage( i ); > QString s; >- if( KMGroupware::vPartFoundAndDecoded( folder->getMsg( i ), s ) ) { >- QString uid( "UID" ); >- vPartMicroParser( s, uid ); >- kdDebug(5006) << "Emitting DCOP signal incidenceDeleted( " >- << type << ", " << folder->location() << ", " << uid >- << " )" << endl; >- if( !mInTransit.contains( uid ) ) // we didn't delete it ourselves >+ bool ok = false; >+ KMMessage* msg = folder->getMsg( i ); >+ QString uid( "UID" ); >+ switch( storageFormat( folder ) ) { >+ case StorageIcalVcard: >+ if( KMGroupware::vPartFoundAndDecoded( msg, s ) ) { >+ vPartMicroParser( s, uid ); >+ ok = true; >+ } >+ break; >+ case StorageXML: >+ if ( kolabXMLFoundAndDecoded( *msg, folderKolabMimeType( folder->storage()->contentsType() ), s ) ) { >+ QDomDocument doc; >+ if ( doc.setContent( s ) ) { >+ QDomElement top = doc.documentElement(); >+ for ( QDomNode n = top.firstChild(); !n.isNull(); n = n.nextSibling() ) { >+ QDomElement e = n.toElement(); >+ if ( e.tagName() == "uid" ) { >+ uid = e.text(); >+ ok = true; >+ } >+ } >+ } >+ } >+ break; >+ } >+ if ( ok ) { >+ kdDebug(5006) << "Emitting DCOP signal incidenceDeleted( " >+ << type << ", " << folder->location() << ", " << uid >+ << " )" << endl; > incidenceDeleted( type, folder->location(), uid ); > } > if( unget ) folder->unGetMsg(i); >@@ -472,9 +1026,12 @@ > const QString& folder ) > { > if( mUseResourceIMAP ) { >- KMFolder* f = extraFolder( type, folder ); >- if ( f ) >- return f; >+ KMFolder* f = 0; >+ if ( !folder.isEmpty() ) { >+ f = extraFolder( type, folder ); >+ if ( f ) >+ return f; >+ } > > if( type == "Calendar" ) f = mCalendar; > else if( type == "Contact" ) f = mContacts; >@@ -499,6 +1056,7 @@ > return mUseResourceIMAP && folder && > ( folder == mCalendar || folder == mTasks || folder == mJournals || > folder == mNotes || folder == mContacts ); >+ // Extra folders are not checked here, since those can't be hidden (right?) > } > > bool KMailICalIfaceImpl::hideResourceImapFolder( KMFolder* folder ) const >@@ -524,36 +1082,15 @@ > return KFolderTreeItem::Other; > } > >- >-QString KMailICalIfaceImpl::icalFolderType( KMFolder* folder ) const >-{ >- if( mUseResourceIMAP && folder ) { >- if( folder == mCalendar ) >- return "Calendar"; >- else if( folder == mContacts ) >- return "Contact"; >- else if( folder == mNotes ) >- return "Note"; >- else if( folder == mTasks ) >- return "Task"; >- else if( folder == mJournals ) >- return "Journal"; >- else { >- ExtraFolder* ef = mExtraFolders.find( folder->location() ); >- if ( ef != 0 ) >- return folderContentsType( ef->type ); >- } >- } >- >- return QString::null; >-} >- >- > // Global tables of foldernames is different languages > // For now: 0->English, 1->German, 2->French, 3->Dutch > static QMap<KFolderTreeItem::Type,QString> folderNames[4]; > QString KMailICalIfaceImpl::folderName( KFolderTreeItem::Type type, int language ) const > { >+ // With the XML storage, folders are always (internally) named in English >+ if ( GlobalSettings::theIMAPResourceStorageFormat() == GlobalSettings::EnumTheIMAPResourceStorageFormat::XML ) >+ language = 0; >+ > static bool folderNamesSet = false; > if( !folderNamesSet ) { > folderNamesSet = true; >@@ -601,12 +1138,44 @@ > // Find message matching a given UID > KMMessage *KMailICalIfaceImpl::findMessageByUID( const QString& uid, KMFolder* folder ) > { >- if( !folder || !mUIDToSerNum.contains( uid ) ) return 0; >- int i; >- KMFolder *aFolder; >- kmkernel->msgDict()->getLocation( mUIDToSerNum[uid], &aFolder, &i ); >- Q_ASSERT( aFolder == folder ); >- return folder->getMsg( i ); >+ if( !folder ) return 0; >+ >+ for( int i=0; i<folder->count(); ++i ) { >+ bool unget = !folder->isMessage(i); >+ KMMessage* msg = folder->getMsg( i ); >+ if( msg ) { >+ QString vCal; >+ if( KMGroupware::vPartFoundAndDecoded( msg, vCal ) ) { >+ QString msgUid( "UID" ); >+ vPartMicroParser( vCal, msgUid ); >+ if( msgUid == uid ) >+ return msg; >+ } >+ } >+ if( unget ) folder->unGetMsg(i); >+ } >+ >+ return 0; >+} >+ >+// Find message matching a given UID >+KMMessage *KMailICalIfaceImpl::findMessageBySerNum( Q_UINT32 serNum, KMFolder* folder ) >+{ >+ if( !folder ) return 0; >+ >+ KMMessage *message = 0; >+ KMFolder* aFolder = 0; >+ int index; >+ kmkernel->msgDict()->getLocation( serNum, &aFolder, &index ); >+ if( aFolder && aFolder != folder ){ >+ kdWarning(5006) << "findMessageBySerNum( " << serNum << " ) found it in folder " << aFolder->location() << ", expected " << folder->location() << endl; >+ }else{ >+ if( aFolder ) >+ message = aFolder->getMsg( index ); >+ if (!message) >+ kdWarning(5006) << "findMessageBySerNum( " << serNum << " ) invalid serial number\n" << endl; >+ } >+ return message; > } > > void KMailICalIfaceImpl::deleteMsg( KMMessage *msg ) >@@ -624,39 +1193,39 @@ > void KMailICalIfaceImpl::folderContentsTypeChanged( KMFolder* folder, > KMail::FolderContentsType contentsType ) > { >+ if ( !mUseResourceIMAP ) >+ return; > kdDebug(5006) << "folderContentsTypeChanged( " << folder->name() > << ", " << contentsType << ")\n"; > >- // Find previous type of this folder >- ExtraFolder* ef = mExtraFolders.find( folder->location() ); >- if ( ( ef && ef->type == contentsType ) || ( !ef && contentsType == 0 ) ) >- // Nothing to tell! >+ if ( isResourceImapFolder( folder ) ) > return; > >- if ( ef ) { >+ // Check if already know that 'extra folder' >+ const QString location = folder->location(); >+ ExtraFolder* ef = mExtraFolders.find( location ); >+ if ( ef && ef->folder ) { > // Notify that the old folder resource is no longer available >- subresourceDeleted(folderContentsType( ef->type ), folder->location() ); >+ subresourceDeleted(folderContentsType( folder->storage()->contentsType() ), location ); > > if ( contentsType == 0 ) { > // Delete the old entry, stop listening and stop here >- mExtraFolders.remove( folder->location() ); >+ mExtraFolders.remove( location ); > folder->disconnect( this ); > return; > } > >- // So the type changed to another groupware type. >- // Set the entry to the new type >- ef->type = contentsType; >+ // So the type changed to another groupware type, ok. > } else { >- // Make a new entry for the list >- ef = new ExtraFolder( folder, contentsType ); >- mExtraFolders.insert( folder->location(), ef ); >+ if ( ef && !ef->folder ) // deleted folder, clean up >+ mExtraFolders.remove( location ); >+ if ( contentsType == 0 ) >+ return; > >- // avoid multiple connections >- disconnect( folder, SIGNAL( msgAdded( KMFolder*, Q_UINT32 ) ), >- this, SLOT( slotIncidenceAdded( KMFolder*, Q_UINT32 ) ) ); >- disconnect( folder, SIGNAL( msgRemoved( KMFolder*, Q_UINT32 ) ), >- this, SLOT( slotIncidenceDeleted( KMFolder*, Q_UINT32 ) ) ); >+ kdDebug(5006) << "registering " << location << " as extra folder" << endl; >+ // Make a new entry for the list >+ ef = new ExtraFolder( folder ); >+ mExtraFolders.insert( location, ef ); > > // And listen to changes from it > connect( folder, SIGNAL( msgAdded( KMFolder*, Q_UINT32 ) ), >@@ -666,27 +1235,72 @@ > } > > // Tell about the new resource >- subresourceAdded( folderContentsType( contentsType ), folder->location() ); >+ /* FIXME merge once we are back in HEAD. IMAP Resource still uses the other one. */ >+ subresourceAdded( folderContentsType( contentsType ), location, folder->prettyURL() ); >+ subresourceAdded( folderContentsType( contentsType ), location ); > } > > KMFolder* KMailICalIfaceImpl::extraFolder( const QString& type, > const QString& folder ) > { >- // If an extra folder exists that match the type and folder location, >+ // If an extra folder exists that matches the type and folder location, > // use that > int t = folderContentsType( type ); > if ( t < 1 || t > 5 ) > return 0; > >- QDictIterator<ExtraFolder> it( mExtraFolders ); >- for ( ; it.current(); ++it ) >- if ( it.current()->type == t && >- it.current()->folder->location() == folder ) >- return it.current()->folder; >+ ExtraFolder* ef = mExtraFolders.find( folder ); >+ if ( ef && ef->folder && ef->folder->storage()->contentsType() == t ) >+ return ef->folder; > > return 0; > } > >+KMailICalIfaceImpl::StorageFormat KMailICalIfaceImpl::storageFormat( KMFolder* folder ) const >+{ >+ FolderInfoMap::ConstIterator it = mFolderInfoMap.find( folder ); >+ if ( it != mFolderInfoMap.end() ) >+ return (*it).mStorageFormat; >+ return GlobalSettings::theIMAPResourceStorageFormat() == GlobalSettings::EnumTheIMAPResourceStorageFormat::XML ? StorageXML : StorageIcalVcard; >+} >+ >+void KMailICalIfaceImpl::setStorageFormat( KMFolder* folder, StorageFormat format ) >+{ >+ FolderInfoMap::Iterator it = mFolderInfoMap.find( folder ); >+ if ( it != mFolderInfoMap.end() ) >+ (*it).mStorageFormat = format; >+ else { >+ FolderInfo info; >+ info.mStorageFormat = format; >+ mFolderInfoMap.insert( folder, info ); >+ } >+ KConfigGroup configGroup( kmkernel->config(), "GroupwareFolderInfo" ); >+ configGroup.writeEntry( folder->idString() + "-storageFormat", >+ format == StorageXML ? "xml" : "icalvcard" ); >+} >+ >+KMFolder* KMailICalIfaceImpl::findResourceFolder( const QString& resource ) >+{ >+ // Try the standard folders >+ if( mCalendar->location() == resource ) >+ return mCalendar; >+ if ( mContacts->location() == resource ) >+ return mContacts; >+ if ( mNotes->location() == resource ) >+ return mNotes; >+ if ( mTasks->location() == resource ) >+ return mTasks; >+ if ( mJournals->location() == resource ) >+ return mJournals; >+ >+ // No luck. Try the extrafolders >+ ExtraFolder* ef = mExtraFolders.find( resource ); >+ if ( ef ) >+ return ef->folder; >+ >+ // No luck at all >+ return 0; >+} > > /**************************** > * The config stuff >@@ -710,6 +1324,8 @@ > const bool hideFolders = GlobalSettings::hideGroupwareFolders(); > unsigned int folderLanguage = GlobalSettings::theIMAPResourceFolderLanguage(); > if( folderLanguage > 3 ) folderLanguage = 0; >+ if ( GlobalSettings::theIMAPResourceStorageFormat() == GlobalSettings::EnumTheIMAPResourceStorageFormat::XML ) >+ folderLanguage = 0; // xml storage -> English > QString parentName = GlobalSettings::theIMAPResourceFolderParent(); > > // Find the folder parent >@@ -722,7 +1338,6 @@ > kdDebug(5006) << "Groupware folder " << parentName << " not found. Groupware functionality disabled" << endl; > // Or maybe the inbox simply wasn't created on the first startup > KMAccount* account = kmkernel->acctMgr()->find( GlobalSettings::theIMAPResourceAccount() ); >- Q_ASSERT( account ); > if ( account ) { > // just in case we were connected already > disconnect( account, SIGNAL( finishedCheck( bool, CheckStatus ) ), >@@ -731,6 +1346,12 @@ > this, SLOT( slotCheckDone() ) ); > } > mUseResourceIMAP = false; >+ // We can't really call cleanup(), if those folders were completely deleted. >+ mCalendar = 0; >+ mTasks = 0; >+ mJournals = 0; >+ mContacts = 0; >+ mNotes = 0; > return; > } else { > folderParentDir = folderParent->createChildFolder(); >@@ -774,7 +1395,6 @@ > > GlobalSettings::setTheIMAPResourceEnabled( false ); > mUseResourceIMAP = false; >- mFolderParentDir = 0; > mFolderParent = 0; > reloadFolderTree(); > return; >@@ -782,7 +1402,7 @@ > } > > // Check if something changed >- if( mUseResourceIMAP && !makeSubFolders && mFolderParentDir == folderParentDir >+ if( mUseResourceIMAP && !makeSubFolders && mFolderParent == folderParentDir > && mFolderType == folderType ) { > // Nothing changed > if ( hideFolders != mHideFolders ) { >@@ -796,8 +1416,7 @@ > // Make the new settings work > mUseResourceIMAP = true; > mFolderLanguage = folderLanguage; >- mFolderParentDir = folderParentDir; >- mFolderParent = folderParent; >+ mFolderParent = folderParentDir; > mFolderType = folderType; > mHideFolders = hideFolders; > >@@ -805,11 +1424,17 @@ > cleanup(); > > // Set the new folders >- mCalendar = initFolder( KFolderTreeItem::Calendar, "GCa" ); >- mTasks = initFolder( KFolderTreeItem::Tasks, "GTa" ); >- mJournals = initFolder( KFolderTreeItem::Journals, "GTa" ); >- mContacts = initFolder( KFolderTreeItem::Contacts, "GCo" ); >- mNotes = initFolder( KFolderTreeItem::Notes, "GNo" ); >+ mCalendar = initFolder( KFolderTreeItem::Calendar, "GCa", KMail::ContentsTypeCalendar ); >+ mTasks = initFolder( KFolderTreeItem::Tasks, "GTa", KMail::ContentsTypeTask ); >+ mJournals = initFolder( KFolderTreeItem::Journals, "GTa", KMail::ContentsTypeJournal ); >+ mContacts = initFolder( KFolderTreeItem::Contacts, "GCo", KMail::ContentsTypeContact ); >+ mNotes = initFolder( KFolderTreeItem::Notes, "GNo", KMail::ContentsTypeNote ); >+ >+ mCalendar->setLabel( i18n( "Calendar" ) ); >+ mTasks->setLabel( i18n( "Tasks" ) ); >+ mJournals->setLabel( i18n( "Journal" ) ); >+ mContacts->setLabel( i18n( "Contacts" ) ); >+ mNotes->setLabel( i18n( "Notes" ) ); > > // Connect the expunged signal > connect( mCalendar, SIGNAL( expunged() ), this, SLOT( slotRefreshCalendar() ) ); >@@ -821,13 +1446,52 @@ > // Bad hack > connect( mNotes, SIGNAL( changed() ), this, SLOT( slotRefreshNotes() ) ); > >+ kdDebug() << k_funcinfo << "mCalendar=" << mCalendar << " " << mCalendar->location() << endl; >+ kdDebug() << k_funcinfo << "mNotes=" << mNotes << " " << mNotes->location() << endl; >+ >+ // Find all extra folders >+ QStringList folderNames; >+ QValueList<QGuardedPtr<KMFolder> > folderList; >+ kmkernel->dimapFolderMgr()->createFolderList(&folderNames, &folderList); >+ for(QValueList<QGuardedPtr<KMFolder> >::iterator it = folderList.begin(); >+ it != folderList.end(); ++it) >+ { >+ FolderStorage* storage = (*it)->storage(); >+ if ( storage->contentsType() != 0 ) { >+ folderContentsTypeChanged( *it, storage->contentsType() ); >+ } >+ } >+ >+ // If we just created them, they might have been registered as extra folders temporarily. >+ // -> undo that. >+ mExtraFolders.remove( mCalendar->location() ); >+ mExtraFolders.remove( mTasks->location() ); >+ mExtraFolders.remove( mJournals->location() ); >+ mExtraFolders.remove( mContacts->location() ); >+ mExtraFolders.remove( mNotes->location() ); >+ >+ > // Make KOrganizer re-read everything >+#if 0 // old way, not enough finegrained (and most resources don't call doOpen, so they miss the subresources anyway) > slotRefresh( "Calendar" ); > slotRefresh( "Task" ); > slotRefresh( "Journal" ); > slotRefresh( "Contact" ); > slotRefresh( "Notes" ); >- >+#else >+ subresourceAdded( folderContentsType( KMail::ContentsTypeCalendar ), mCalendar->location(), mCalendar->label() ); >+ subresourceAdded( folderContentsType( KMail::ContentsTypeCalendar ), mCalendar->location() ); >+ subresourceAdded( folderContentsType( KMail::ContentsTypeTask ), mTasks->location(), mTasks->label() ); >+ subresourceAdded( folderContentsType( KMail::ContentsTypeTask ), mTasks->location() ); >+ subresourceAdded( folderContentsType( KMail::ContentsTypeJournal ), mJournals->location(), mJournals->label() ); >+ subresourceAdded( folderContentsType( KMail::ContentsTypeJournal ), mJournals->location() ); >+ subresourceAdded( folderContentsType( KMail::ContentsTypeContact ), mContacts->location(), mContacts->label() ); >+ subresourceAdded( folderContentsType( KMail::ContentsTypeContact ), mContacts->location() ); >+ subresourceAdded( folderContentsType( KMail::ContentsTypeNote ), mNotes->location(), mNotes->label() ); >+ subresourceAdded( folderContentsType( KMail::ContentsTypeNote ), mNotes->location() ); >+ // This also shows that we might even get rid of the mCalendar etc. special >+ // case and just use ExtraFolder for all >+#endif > reloadFolderTree(); > } > >@@ -835,6 +1499,7 @@ > { > QString parentName = GlobalSettings::theIMAPResourceFolderParent(); > KMFolder* folderParent = kmkernel->findFolderById( parentName ); >+ kdDebug() << k_funcinfo << " folderParent=" << folderParent << endl; > if ( folderParent ) // cool it exists now > { > KMAccount* account = kmkernel->acctMgr()->find( GlobalSettings::theIMAPResourceAccount() ); >@@ -852,7 +1517,8 @@ > void KMailICalIfaceImpl::slotRefreshNotes() { slotRefresh( "Notes" ); } > > KMFolder* KMailICalIfaceImpl::initFolder( KFolderTreeItem::Type itemType, >- const char* typeString ) >+ const char* typeString, >+ KMail::FolderContentsType contentsType ) > { > // Figure out what type of folder this is supposed to be > KMFolderType type = mFolderType; >@@ -860,17 +1526,26 @@ > > // Find the folder > KMFolder* folder = 0; >- KMFolderNode* node = mFolderParentDir->hasNamedFolder( folderName( itemType ) ); >+ KMFolderNode* node = mFolderParent->hasNamedFolder( folderName( itemType ) ); > if( node && !node->isDir() ) folder = static_cast<KMFolder*>(node); > if( !folder ) { > // The folder isn't there yet - create it > folder = >- mFolderParentDir->createFolder( folderName( itemType ), false, type ); >- if( mFolderType == KMFolderTypeImap ) { >- KMFolderImap* parentFolder = static_cast<KMFolderImap*>( mFolderParent->storage() ); >- parentFolder->createFolder( folderName( itemType ) ); >- static_cast<KMFolderImap*>( folder->storage() )->setAccount( parentFolder->account() ); >- } >+ mFolderParent->createFolder( folderName( itemType ), false, type ); >+ if( mFolderType == KMFolderTypeImap ) >+ static_cast<KMFolderImap*>( folder->storage() )-> >+ createFolder( folderName( itemType ) ); >+ >+ // Groupware folder created, use the global setting for storage format >+ setStorageFormat( folder, GlobalSettings::theIMAPResourceStorageFormat() == GlobalSettings::EnumTheIMAPResourceStorageFormat::XML ? StorageXML : StorageIcalVcard ); >+ } else { >+ KConfigGroup configGroup( kmkernel->config(), "GroupwareFolderInfo" ); >+ QString str = configGroup.readEntry( folder->idString() + "-storageFormat", "icalvcard" ); >+ FolderInfo info; >+ info.mStorageFormat = ( str == "xml" ) ? StorageXML : StorageIcalVcard; >+ mFolderInfoMap.insert( folder, info ); >+ >+ //kdDebug(5006) << "Found existing folder type " << itemType << " : " << folder->location() << endl; > } > > if( folder->canAccess() != 0 ) { >@@ -879,13 +1554,11 @@ > return 0; > } > folder->setType( typeString ); >+ folder->storage()->setContentsType( contentsType ); >+ > folder->setSystemFolder( true ); > folder->open(); >- // avoid multiple connections >- disconnect( folder, SIGNAL( msgAdded( KMFolder*, Q_UINT32 ) ), >- this, SLOT( slotIncidenceAdded( KMFolder*, Q_UINT32 ) ) ); >- disconnect( folder, SIGNAL( msgRemoved( KMFolder*, Q_UINT32 ) ), >- this, SLOT( slotIncidenceDeleted( KMFolder*, Q_UINT32 ) ) ); >+ > // Setup the signals to listen for changes > connect( folder, SIGNAL( msgAdded( KMFolder*, Q_UINT32 ) ), > this, SLOT( slotIncidenceAdded( KMFolder*, Q_UINT32 ) ) ); >@@ -992,5 +1665,4 @@ > s.truncate(0); > } > >- > #include "kmailicalifaceimpl.moc" >diff -u -r kdepim/kmail/kmailicalifaceimpl.h proko2/kmail/kmailicalifaceimpl.h >--- kdepim/kmail/kmailicalifaceimpl.h 2004-07-27 00:05:27.000000000 +0200 >+++ proko2/kmail/kmailicalifaceimpl.h 2004-08-31 12:36:31.861546608 +0200 >@@ -41,41 +41,12 @@ > > #include <qdict.h> > #include <qguardedptr.h> >-#include <qmap.h> > > class KMFolder; > class KMMessage; > class KMFolderDir; > class KMFolderTreeItem; > >-namespace { >- >-// Local helper classes >-class ExtraFolder { >-public: >- ExtraFolder( KMFolder* f, KMail::FolderContentsType t ) : folder( f ), type( t ) {} >- KMFolder* folder; >- KMail::FolderContentsType type; >-}; >- >-class Accumulator { >-public: >- Accumulator( const QString& t, const QString& f, int c ) >- :type( t ), folder( f ), count( c ) {} >- >- void add( const QString& incidence ) { >- incidences << incidence; >- count--; >- } >- bool isFull() { return count == 0; } >- >- const QString type; >- const QString folder; >- QStringList incidences; >- int count; >-}; >- >-} > > class KMailICalIfaceImpl : public QObject, virtual public KMailICalIface { > Q_OBJECT >@@ -101,6 +72,33 @@ > bool update( const QString& type, const QString& folder, > const QString& uid, const QString& entry ); > >+ /// Update a kolab storage entry. >+ /// If message is not there, it is added and >+ /// given the subject as Subject: header. >+ /// Returns the new mail serial number, >+ /// or 0 if something went wrong, >+ Q_UINT32 update( const QString& resource, >+ Q_UINT32 sernum, >+ const QString& subject, >+ const QStringList& attachmentURLs, >+ const QStringList& attachmentMimetypes, >+ const QStringList& attachmentNames, >+ const QStringList& deletedAttachments ); >+ >+ bool deleteIncidenceKolab( const QString& resource, >+ Q_UINT32 sernum ); >+ QMap<Q_UINT32, QString> incidencesKolab( const QString& mimetype, >+ const QString& resource ); >+ >+ QValueList<SubResource> subresourcesKolab( const QString& contentsType ); >+ >+ // "Get" an attachment. This actually saves the attachment in a file >+ // and returns a URL to it >+ KURL getAttachment( const QString& resource, >+ Q_UINT32 sernum, >+ const QString& filename ); >+ >+ > // tell KOrganizer about messages to be deleted > void msgRemoved( KMFolder*, KMMessage* ); > >@@ -141,11 +139,11 @@ > /** Get the folder that holds *type* entries */ > KMFolder* folderFromType( const QString& type, const QString& folder ); > >- /** Return the ical type of a folder */ >- QString icalFolderType( KMFolder* folder ) const; >- > /** Find message matching a given UID. */ >- KMMessage* findMessageByUID( const QString& uid, KMFolder* folder ); >+ static KMMessage* findMessageByUID( const QString& uid, KMFolder* folder ); >+ >+ /** Find message matching a given serial number. */ >+ static KMMessage* findMessageBySerNum( Q_UINT32 serNum, KMFolder* folder ); > > /** Convenience function to delete a message. */ > static void deleteMsg( KMMessage* msg ); >@@ -155,9 +153,15 @@ > /** Called when a folders contents have changed */ > void folderContentsTypeChanged( KMFolder*, KMail::FolderContentsType ); > >+ /// @return the storage format of a given folder >+ StorageFormat storageFormat( KMFolder* folder ) const; >+ /// Set the storage format of a given folder. Called when seeing the kolab annotation. >+ void setStorageFormat( KMFolder* folder, StorageFormat format ); >+ > public slots: > /* (Re-)Read configuration file */ > void readConfig(); >+ void slotFolderRemoved( KMFolder* folder ); > > void slotIncidenceAdded( KMFolder* folder, Q_UINT32 sernum ); > void slotIncidenceDeleted( KMFolder* folder, Q_UINT32 sernum ); >@@ -171,14 +175,29 @@ > void slotRefreshNotes(); > > void slotCheckDone(); >- void slotMessageRetrieved( KMMessage* ); > > private: > /** Helper function for initFolders. Initializes a single folder. */ >- KMFolder* initFolder( KFolderTreeItem::Type itemType, const char* typeString ); >+ KMFolder* initFolder( KFolderTreeItem::Type itemType, const char* typeString, >+ KMail::FolderContentsType contentsType ); > > KMFolder* extraFolder( const QString& type, const QString& folder ); > >+ KMFolder* findResourceFolder( const QString& resource ); >+ >+ bool updateAttachment( KMMessage& msg, >+ const QString& attachmentURL, >+ const QString& attachmentName, >+ const QString& attachmentMimetype, >+ bool lookupByName ); >+ bool deleteAttachment( KMMessage& msg, >+ const QString& attachmentURL ); >+ Q_UINT32 addIncidenceKolab( KMFolder& folder, >+ const QString& subject, >+ const QStringList& attachmentURLs, >+ const QStringList& attachmentNames, >+ const QStringList& attachmentMimetypes ); >+ static bool kolabXMLFoundAndDecoded( const KMMessage& msg, const QString& mimetype, QString& s ); > void loadPixmaps() const; > > QGuardedPtr<KMFolder> mContacts; >@@ -188,34 +207,29 @@ > QGuardedPtr<KMFolder> mJournals; > > // The extra IMAP resource folders >+ // Key: folder location. Data: folder. >+ class ExtraFolder; > QDict<ExtraFolder> mExtraFolders; > >- // used for collecting incidences during async loading >- QDict<Accumulator> mAccumulators; >+ // More info for each folder we care about (mContacts etc. as well as the extra folders) >+ struct FolderInfo { >+ StorageFormat mStorageFormat; >+ }; >+ // The storage format used for each folder that we care about >+ typedef QMap<KMFolder*, FolderInfo> FolderInfoMap; >+ FolderInfoMap mFolderInfoMap; > > unsigned int mFolderLanguage; > >- KMFolderDir* mFolderParentDir; >- KMFolder* mFolderParent; >+ KMFolderDir* mFolderParent; > KMFolderType mFolderType; > > // groupware folder icons: > static QPixmap *pixContacts, *pixCalendar, *pixNotes, *pixTasks; > > bool mUseResourceIMAP; >+ bool mResourceQuiet; > bool mHideFolders; >- >- /* >- * Bunch of maps to keep track of incidents currently in transfer, ones >- * which need to be ungotten, once we are done, once with updates pending. >- * Since these are transient attributes of only a small but changing number >- * of incidences they are not encapsulated in a struct or somesuch. >- */ >- QMap<QString, Q_UINT32> mUIDToSerNum; >- QMap<Q_UINT32, bool> mTheUnGetMes; >- QMap<QString, QString> mPendingUpdates; >- QMap<QString, bool> mInTransit; >- > }; > > #endif // KMAILICALIFACEIMPL_H >diff -u -r kdepim/kmail/kmfoldercachedimap.cpp proko2/kmail/kmfoldercachedimap.cpp >--- kdepim/kmail/kmfoldercachedimap.cpp 2004-08-18 11:34:12.000000000 +0200 >+++ proko2/kmail/kmfoldercachedimap.cpp 2004-08-31 12:36:39.222427584 +0200 >@@ -67,6 +67,9 @@ > #include <qlabel.h> > #include <qlayout.h> > #include <qvaluelist.h> >+#include "annotationjobs.h" >+using namespace KMail; >+#include <globalsettings.h> > > #define UIDCACHE_VERSION 1 > >@@ -139,10 +142,13 @@ > // Only write configuration when the folder haven't been deleted > KConfig* config = KMKernel::config(); > KConfigGroupSaver saver( config, "Folder-" + folder()->idString() ); >+ Q_ASSERT( !mImapPath.isEmpty() ); > config->writeEntry( "ImapPath", mImapPath ); > config->writeEntry( "NoContent", mNoContent ); > config->writeEntry( "ReadOnly", mReadOnly ); > config->writeEntry( "StatusChangedLocally", mStatusChangedLocally ); >+ config->writeEntry( "ContentsTypeChanged", mContentsTypeChanged ); >+ config->writeEntry( "Annotation-FolderType", mAnnotationFolderType ); > > writeUidCache(); > } >@@ -173,10 +179,18 @@ > mNoContent = config->readBoolEntry( "NoContent", false ); > mReadOnly = config->readBoolEntry( "ReadOnly", false ); > >+ // must be done before so that setContentsType can see the storageformat >+ mAnnotationFolderType = config->readEntry( "Annotation-FolderType" ); >+ if ( !mAnnotationFolderType.isEmpty() ) >+ kmkernel->iCalIface().setStorageFormat( folder(), KMailICalIfaceImpl::StorageXML ); >+ > KMFolderMaildir::readConfig(); >- mContentsTypeChanged = false; >+ > mStatusChangedLocally = > config->readBoolEntry( "StatusChangedLocally", false ); >+ >+ // Must be done afterwards since FolderStorage::readConfig sets mContentsTypeChanged >+ mContentsTypeChanged = config->readBoolEntry( "ContentsTypeChanged", false ); > } > > void KMFolderCachedImap::remove() >@@ -444,6 +458,17 @@ > } > } > >+// Name used for the various folder-contents-types in the folder annotations >+// The index in this array is the KMail::FolderContentsType enum >+static const char* s_contentsType2Annotation[] = { >+ "mail", >+ "event", >+ "contact", >+ "note", >+ "task", >+ "journal" >+}; >+ > void KMFolderCachedImap::serverSync( bool recurse ) > { > if( mSyncState != SYNC_STATE_INITIAL ) { >@@ -492,6 +517,8 @@ > case SYNC_STATE_EXPUNGE_MESSAGES: return "SYNC_STATE_EXPUNGE_MESSAGES"; > case SYNC_STATE_HANDLE_INBOX: return "SYNC_STATE_HANDLE_INBOX"; > case SYNC_STATE_GET_USERRIGHTS: return "SYNC_STATE_GET_USERRIGHTS"; >+ case SYNC_STATE_GET_ANNOTATIONS: return "SYNC_STATE_GET_ANNOTATIONS"; >+ case SYNC_STATE_SET_ANNOTATIONS: return "SYNC_STATE_SET_ANNOTATIONS"; > case SYNC_STATE_GET_ACLS: return "SYNC_STATE_GET_ACLS"; > case SYNC_STATE_SET_ACLS: return "SYNC_STATE_SET_ACLS"; > case SYNC_STATE_FIND_SUBFOLDERS: return "SYNC_STATE_FIND_SUBFOLDERS"; >@@ -520,8 +547,10 @@ > delete_messages 10 > expunge_messages 5 > get_messages variable (remaining-5) i.e. minimum 15. >+ set_annotations 0 (rare) >+ get_annotations 2 > set_acls 0 (rare) >- get_acls 5 >+ get_acls 3 > > noContent folders have only a few of the above steps > (permissions, and all subfolder stuff), so its steps should be given more span >@@ -752,8 +781,62 @@ > serverSyncInternal(); > break; > } else >- // Continue with the ACLs >- mSyncState = SYNC_STATE_SET_ACLS; >+ mSyncState = SYNC_STATE_GET_ANNOTATIONS; >+ >+ case SYNC_STATE_GET_ANNOTATIONS: >+#define KOLAB_FOLDERTYPE "/vendor/kolab/folder-type" >+//#define KOLAB_FOLDERTYPE "/comment" //for testing, while cyrus-imap doesn't support /vendor/* >+ mSyncState = SYNC_STATE_SET_ANNOTATIONS; >+ >+ // First retrieve the annotation, so that we know we have to set it if it's not set. >+ // On the other hand, if the user changed the contentstype, there's no need to get first. >+ if( !noContent() && mAccount->hasAnnotationSupport() && >+ ( !mContentsTypeChanged || mAnnotationFolderType.isEmpty() ) ) { >+ newState( mProgress, i18n("Retrieving annotations")); >+ // If in the future we want to retrieve more annotations, we should then write >+ // a multiGetAnnotation job in annotationjobs.* >+ KURL url = mAccount->getUrl(); >+ url.setPath( imapPath() ); >+ QStringList attributes; >+ attributes << "value"; >+ AnnotationJobs::GetAnnotationJob* job = >+ AnnotationJobs::getAnnotation( mAccount->slave(), url, KOLAB_FOLDERTYPE, attributes ); >+ ImapAccountBase::jobData jd( url.url(), folder() ); >+ jd.cancellable = true; >+ mAccount->insertJob(job, jd); >+ >+ connect(job, SIGNAL(result(KIO::Job *)), >+ SLOT(slotGetAnnotationResult(KIO::Job *))); >+ break; >+ } >+ >+ case SYNC_STATE_SET_ANNOTATIONS: >+ >+ mSyncState = SYNC_STATE_SET_ACLS; >+ if ( mAccount->hasAnnotationSupport() && >+ ( mUserRights <= 0 || ( mUserRights & ACLJobs::Administer ) ) ) { >+ newState( mProgress, i18n("Setting annotations")); >+ // If in the future we want to set more annotations, we should then write >+ // a multiSetAnnotation job in annotationjobs.* >+ KURL url = mAccount->getUrl(); >+ url.setPath( imapPath() ); >+ QMap<QString, QString> attributes; >+ if ( mContentsTypeChanged && !mAnnotationFolderType.isEmpty() ) { >+ attributes.insert( "value.shared", mAnnotationFolderType ); >+ kdDebug(5006) << "Setting annotation for " << label() << " to " << mAnnotationFolderType << endl; >+ } >+ if ( !attributes.isEmpty() ) { >+ KIO::SimpleJob* job = >+ AnnotationJobs::setAnnotation( mAccount->slave(), url, KOLAB_FOLDERTYPE, attributes ); >+ ImapAccountBase::jobData jd( url.url(), folder() ); >+ jd.cancellable = true; // we can always do so later >+ mAccount->insertJob(job, jd); >+ >+ connect(job, SIGNAL(result(KIO::Job *)), >+ SLOT(slotSetAnnotationResult(KIO::Job *))); >+ break; >+ } >+ } > > case SYNC_STATE_SET_ACLS: > mSyncState = SYNC_STATE_GET_ACLS; >@@ -1649,6 +1732,96 @@ > FolderStorage::setContentsType( type ); > mContentsTypeChanged = true; > } >+ // We want to store an annotation on the folder only if using the kolab storage. >+ if ( kmkernel->iCalIface().storageFormat( folder() ) == KMailICalIfaceImpl::StorageXML ) >+ mAnnotationFolderType = s_contentsType2Annotation[mContentsType]; >+ else >+ mAnnotationFolderType = QString::null; >+} >+ >+void KMFolderCachedImap::slotGetAnnotationResult( KIO::Job* job ) >+{ >+ KMAcctCachedImap::JobIterator it = mAccount->findJob(job); >+ Q_ASSERT( it != mAccount->jobsEnd() ); >+ if ( it == mAccount->jobsEnd() ) return; // Shouldn't happen >+ Q_ASSERT( (*it).parent == folder() ); >+ if ( (*it).parent != folder() ) return; // Shouldn't happen >+ AnnotationJobs::GetAnnotationJob* annjob = static_cast<AnnotationJobs::GetAnnotationJob *>( job ); >+ if ( annjob->error() ) { >+ if ( job->error() == KIO::ERR_UNSUPPORTED_ACTION ) { >+ // that's when the imap server doesn't support annotations >+ if ( GlobalSettings::theIMAPResourceStorageFormat() == GlobalSettings::EnumTheIMAPResourceStorageFormat::XML >+ && GlobalSettings::theIMAPResourceAccount() == mAccount->id() ) >+ KMessageBox::error( 0, i18n( "The IMAP server %1 doesn't have support for imap annotations. The XML storage cannot be used on this server, please re-configure KMail differently" ).arg( mAccount->host() ) ); >+ mAccount->setHasNoAnnotationSupport(); >+ } >+ else >+ kdWarning(5006) << "slotGetAnnotationResult: " << job->errorString() << endl; >+ } else { >+ AnnotationList lst = annjob->annotations(); >+ // There are four cases. >+ // 1) no content-type on server -> set it >+ // 2) different content-type on server, locally changed -> set it (we don't even come here) >+ // 3) different (known) content-type on server, no local change -> get it >+ // 4) different unknown content-type on server, probably some older version -> set it >+ bool foundContentType = !lst.isEmpty(); >+ for ( unsigned int i = 0 ; i < lst.size() ; ++ i ) { >+ kdDebug(5006) << "Found annotation: " << lst[i].name << " = " << lst[i].value << endl; >+ if ( lst[i].name.startsWith( "value." ) ) { // value.priv or value.shared >+ QString value = lst[i].value; >+ QString type = value; >+ QString subtype; >+ int dot = value.find( '.' ); >+ if ( dot != -1 ) { >+ type.truncate( dot ); >+ subtype = value.mid( dot + 1 ); >+ } >+ bool foundKnownType = false; >+ for ( uint i = 0 ; i < sizeof s_contentsType2Annotation / sizeof *s_contentsType2Annotation; ++i ) { >+ if ( type == s_contentsType2Annotation[i] ) { >+ // Case 3: known content-type on server, get it >+ kmkernel->iCalIface().setStorageFormat( folder(), KMailICalIfaceImpl::StorageXML ); >+ setContentsType( static_cast<KMail::FolderContentsType>( i ) ); >+ mContentsTypeChanged = false; // we changed it, not the user >+ foundKnownType = true; >+ break; >+ } >+ } >+ if ( !foundKnownType && !mReadOnly ) { >+ // Case 4: server has strange content-type, set it to what we need >+ mContentsTypeChanged = true; >+ } >+ >+ // TODO handle subtype (inbox, drafts, sentitems, junkemail) >+ } >+ } >+ if ( !foundContentType && !mReadOnly ) { >+ // Case 1: server doesn't have content-type, set it >+ mContentsTypeChanged = true; >+ } >+ } >+ >+ if (mAccount->slave()) mAccount->removeJob(job); >+ mProgress += 2; >+ serverSyncInternal(); >+} >+ >+void >+KMFolderCachedImap::slotSetAnnotationResult(KIO::Job *job) >+{ >+ KMAcctCachedImap::JobIterator it = mAccount->findJob(job); >+ if ( it == mAccount->jobsEnd() ) return; // Shouldn't happen >+ if ( (*it).parent != folder() ) return; // Shouldn't happen >+ >+ bool cont = true; >+ if ( job->error() ) { >+ cont = mAccount->handleJobError( job, i18n( "Error while setting annotation: " ) + '\n' ); >+ } else { >+ mContentsTypeChanged = false; >+ if (mAccount->slave()) mAccount->removeJob(job); >+ } >+ if ( cont ) >+ serverSyncInternal(); > } > > void KMFolderCachedImap::slotUpdateLastUid() >diff -u -r kdepim/kmail/kmfoldercachedimap.h proko2/kmail/kmfoldercachedimap.h >--- kdepim/kmail/kmfoldercachedimap.h 2004-08-18 11:34:12.000000000 +0200 >+++ proko2/kmail/kmfoldercachedimap.h 2004-08-31 12:36:39.233425912 +0200 >@@ -237,8 +237,9 @@ > // Connected to the imap account > void slotConnectionResult( int errorCode, const QString& errorMsg ); > >- void slotCheckUidValidityResult( KMail::FolderJob* job ); >- >+ void slotCheckUidValidityResult( KMail::FolderJob* job ); >+ void slotGetAnnotationResult( KIO::Job* ); >+ void slotSetAnnotationResult(KIO::Job *job); > void slotReceivedUserRights( KMFolder* ); > void slotReceivedACL( KMFolder*, KIO::Job*, const KMail::ACLList& ); > >@@ -323,6 +324,8 @@ > SYNC_STATE_GET_MESSAGES, > SYNC_STATE_HANDLE_INBOX, > SYNC_STATE_GET_USERRIGHTS, >+ SYNC_STATE_GET_ANNOTATIONS, >+ SYNC_STATE_SET_ANNOTATIONS, > SYNC_STATE_GET_ACLS, > SYNC_STATE_SET_ACLS, > SYNC_STATE_FIND_SUBFOLDERS, >@@ -339,6 +342,7 @@ > imapState mContentState, mSubfolderState; > QStringList mSubfolderNames, mSubfolderPaths, > mSubfolderMimeTypes, mSubfolderAttributes; >+ QString mAnnotationFolderType; > > bool mHasInbox; > bool mIsSelected; >diff -u -r kdepim/kmail/kmversion.h proko2/kmail/kmversion.h >--- kdepim/kmail/kmversion.h 2004-08-04 18:22:16.000000000 +0200 >+++ proko2/kmail/kmversion.h 2004-08-31 12:36:31.885542960 +0200 >@@ -3,6 +3,6 @@ > #ifndef kmversion_h > #define kmversion_h > >-#define KMAIL_VERSION "1.7" >+#define KMAIL_VERSION "1.7 (proko2 branch)" > > #endif /*kmversion_h*/ >diff -u -r kdepim/korganizer/CVS/Entries proko2/korganizer/CVS/Entries >--- kdepim/korganizer/CVS/Entries 2004-08-31 11:39:25.000000000 +0200 >+++ proko2/korganizer/CVS/Entries 2004-08-31 12:37:01.861985848 +0200 >@@ -58,7 +58,6 @@ > /filteredit_base.ui/1.9/Wed Oct 15 22:06:55 2003//TKDE_3_3_BRANCH > /filtereditdialog.cpp/1.22/Mon Apr 26 00:06:13 2004//TKDE_3_3_BRANCH > /filtereditdialog.h/1.14/Mon Apr 26 00:06:13 2004//TKDE_3_3_BRANCH >-/freebusymanager.cpp/1.25/Mon Aug 2 16:31:45 2004//TKDE_3_3_BRANCH > /freebusymanager.h/1.9/Tue Jun 8 12:10:07 2004//TKDE_3_3_BRANCH > /freebusyurldialog.cpp/1.4/Mon Jun 7 16:37:41 2004//TKDE_3_3_BRANCH > /freebusyurldialog.h/1.3/Mon Jun 7 16:37:41 2004//TKDE_3_3_BRANCH >@@ -205,8 +204,6 @@ > /publishdialog.cpp/1.11/Tue Jun 8 12:31:58 2004//TKDE_3_3_BRANCH > /publishdialog.h/1.5/Tue Jun 8 12:31:58 2004//TKDE_3_3_BRANCH > /publishdialog_base.ui/1.16/Mon Jun 14 13:51:51 2004//TKDE_3_3_BRANCH >-/resourceview.cpp/1.50.2.2/Wed Aug 25 14:04:58 2004//TKDE_3_3_BRANCH >-/resourceview.h/1.21.2.2/Wed Aug 25 14:04:58 2004//TKDE_3_3_BRANCH > /searchdialog.cpp/1.43/Tue Jun 8 12:31:58 2004//TKDE_3_3_BRANCH > /searchdialog.h/1.29/Tue Jun 8 12:31:58 2004//TKDE_3_3_BRANCH > /statusdialog.cpp/1.8/Tue Jun 8 12:31:58 2004//TKDE_3_3_BRANCH >@@ -221,7 +218,6 @@ > /tips/1.16/Fri Jul 2 10:57:34 2004//TKDE_3_3_BRANCH > /urihandler.cpp/1.8/Tue Jun 8 12:31:58 2004//TKDE_3_3_BRANCH > /urihandler.h/1.3/Tue Jun 8 12:31:58 2004//TKDE_3_3_BRANCH >-/version.h/1.66/Wed Aug 4 08:20:36 2004//TKDE_3_3_BRANCH > /webcal.protocol/1.1/Wed Oct 9 20:48:02 2002//TKDE_3_3_BRANCH > D/attic//// > D/interfaces//// >@@ -230,3 +226,7 @@ > D/pixmaps//// > D/plugins//// > D/sounds//// >+/freebusymanager.cpp/1.25.4.1/Tue Aug 31 10:37:01 2004//Tproko2 >+/version.h/1.66.4.1/Tue Aug 31 10:37:01 2004//Tproko2 >+/resourceview.cpp/1.51.2.8/Tue Aug 31 10:37:01 2004//Tproko2 >+/resourceview.h/1.21.4.5/Tue Aug 31 10:37:01 2004//Tproko2 >diff -u -r kdepim/korganizer/freebusymanager.cpp proko2/korganizer/freebusymanager.cpp >--- kdepim/korganizer/freebusymanager.cpp 2004-08-02 18:31:45.000000000 +0200 >+++ proko2/korganizer/freebusymanager.cpp 2004-08-31 12:37:01.481043760 +0200 >@@ -395,10 +395,6 @@ > // Build the URL > KURL sourceURL; > sourceURL = KOPrefs::instance()->mFreeBusyRetrieveUrl; >- >- // Don't try to fetch free/busy data for users not on the specified servers >- if ( sourceURL.host() != email.mid( emailpos + 1 ) ) return KURL(); >- > if ( KOPrefs::instance()->mFreeBusyFullDomainRetrieval ) > sourceURL.setFileName( email + ".ifb" ); > else >diff -u -r kdepim/korganizer/resourceview.cpp proko2/korganizer/resourceview.cpp >--- kdepim/korganizer/resourceview.cpp 2004-08-25 16:04:58.000000000 +0200 >+++ proko2/korganizer/resourceview.cpp 2004-08-31 12:37:01.852987216 +0200 >@@ -1,3 +1,5 @@ >+#ifndef RESOURCEVIEW.CPP >+#define RESOURCEVIEW.CPP > /* > This file is part of KOrganizer. > >@@ -41,6 +43,8 @@ > #include <qpushbutton.h> > #include <qpopupmenu.h> > >+#include "koprefs.h" >+ > using namespace KCal; > > ResourceViewFactory::ResourceViewFactory( KCal::CalendarResources *calendar, >@@ -83,10 +87,17 @@ > KListView *parent ) > : QCheckListItem( parent, resource->resourceName(), CheckBox ), > mResource( resource ), mView( view ), mBlockStateChange( false ), >- mIsSubresource( false ) >+ mIsSubresource( false ), mResourceIdentifier( QString::null ), >+ mSubItemsCreated( false ) > { > setGuiState(); > >+ if ( mResource->isActive() ) { >+ createSubresourceItems(); >+ } >+} >+ >+void ResourceItem::createSubresourceItems() { > const QStringList subresources = mResource->subresources(); > if ( !subresources.isEmpty() ) { > setOpen( true ); >@@ -94,17 +105,23 @@ > // This resource has subresources > QStringList::ConstIterator it; > for ( it=subresources.begin(); it!=subresources.end(); ++it ) { >- ( void )new ResourceItem( mResource, *it, mView, this ); >+ ( void )new ResourceItem( mResource, *it, mResource->labelForSubresource( *it ), >+ mView, this ); > } > } >+ mSubItemsCreated = true; > } > > ResourceItem::ResourceItem( KCal::ResourceCalendar *resource, >- const QString& sub, ResourceView *view, >- ResourceItem* parent ) >+ const QString& sub, const QString& label, >+ ResourceView *view, ResourceItem* parent ) >+ > : QCheckListItem( parent, sub, CheckBox ), mResource( resource ), >- mView( view ), mBlockStateChange( false ), mIsSubresource( true ) >+ mView( view ), mBlockStateChange( false ), mIsSubresource( true ), >+ mSubItemsCreated( false ) > { >+ mResourceIdentifier = sub; >+ setText( 0, label ); > setGuiState(); > } > >@@ -112,7 +129,7 @@ > { > mBlockStateChange = true; > if ( mIsSubresource ) >- setOn( mResource->subresourceActive( text( 0 ) ) ); >+ setOn( mResource->subresourceActive( mResourceIdentifier ) ); > else > setOn( mResource->isActive() ); > mBlockStateChange = false; >@@ -123,10 +140,14 @@ > if ( mBlockStateChange ) return; > > if ( mIsSubresource ) { >- mResource->setSubresourceActive( text( 0 ), active ); >+ mResource->setSubresourceActive( mResourceIdentifier, active ); > } else { > if ( active ) { >- if ( mResource->load() ) mResource->setActive( true ); >+ if ( mResource->load() ) { >+ mResource->setActive( true ); >+ if ( !mSubItemsCreated ) >+ createSubresourceItems(); >+ } > } else { > if ( mResource->save() ) mResource->setActive( false ); > mView->requestClose( mResource ); >@@ -177,7 +198,6 @@ > const QPoint &, int ) ), > SLOT( contextMenuRequested( QListViewItem *, const QPoint &, > int ) ) ); >- > updateView(); > } > >@@ -231,11 +251,11 @@ > "KRES::ConfigDialog" ); > > if ( dlg.exec() ) { >+ resource->setTimeZoneId( KOPrefs::instance()->mTimeZoneId ); > if ( resource->isActive() ) { > resource->open(); > resource->load(); > } >- > manager->add( resource ); > addResourceItem( resource ); > } else { >@@ -250,9 +270,17 @@ > > connect( resource, SIGNAL( signalSubresourceAdded( ResourceCalendar *, > const QString &, >+ const QString &, >+ const QString & ) ), >+ SLOT( slotSubresourceAdded( ResourceCalendar *, const QString &, >+ const QString &, const QString & ) ) ); >+ >+ connect( resource, SIGNAL( signalSubresourceAdded( ResourceCalendar *, >+ const QString &, > const QString & ) ), > SLOT( slotSubresourceAdded( ResourceCalendar *, const QString &, > const QString & ) ) ); >+ > connect( resource, SIGNAL( signalSubresourceRemoved( ResourceCalendar *, > const QString &, > const QString & ) ), >@@ -265,10 +293,20 @@ > emitResourcesChanged(); > } > >+ >+// FIXME proko2: merge once we are back in HEAD by porting imap resource >+void ResourceView::slotSubresourceAdded( ResourceCalendar *calendar, >+ const QString& type, >+ const QString& resource ) >+{ >+ slotSubresourceAdded( calendar, type, resource, resource ); >+} >+ > // Add a new entry > void ResourceView::slotSubresourceAdded( ResourceCalendar *calendar, >- const QString &/*type*/, >- const QString &resource ) >+ const QString& /*type*/, >+ const QString& resource, >+ const QString& label) > { > QListViewItem *i = mListView->findItem( calendar->resourceName(), 0 ); > if ( !i ) >@@ -276,7 +314,7 @@ > return; > > ResourceItem *item = static_cast<ResourceItem *>( i ); >- ( void )new ResourceItem( calendar, resource, this, item ); >+ ( void )new ResourceItem( calendar, resource, label, this, item ); > } > > // Remove an entry >@@ -284,7 +322,8 @@ > const QString &/*type*/, > const QString &resource ) > { >- delete mListView->findItem( resource, 0 ); >+ delete findItemByIdentifier( resource ); >+ emitResourcesChanged(); > } > > void ResourceView::closeResource( ResourceCalendar *r ) >@@ -317,7 +356,7 @@ > > int km = KMessageBox::warningContinueCancel( this, > i18n("<qt>Do you really want to remove the resource <b>%1</b>?</qt>") >- .arg( item->resource()->resourceName() ), "", >+ .arg( item->text( 0 ) ), "", > KGuiItem( i18n("&Remove" ), "editdelete") ); > if ( km == KMessageBox::Cancel ) return; > >@@ -329,11 +368,13 @@ > return; > } > #endif >- >- mCalendar->resourceManager()->remove( item->resource() ); >- >- mListView->takeItem( item ); >- delete item; >+ if ( item->isSubresource() ) { >+ // TODO delete the folder in KMail >+ } else { >+ mCalendar->resourceManager()->remove( item->resource() ); >+ mListView->takeItem( item ); >+ delete item; >+ } > emitResourcesChanged(); > } > >@@ -355,10 +396,14 @@ > > void ResourceView::currentChanged( QListViewItem *item) > { >- bool selected = true; >- if ( !item ) selected = false; >- mDeleteButton->setEnabled( selected ); >- mEditButton->setEnabled( selected ); >+ ResourceItem *i = currentItem(); >+ if ( !item || i->isSubresource() ) { >+ mDeleteButton->setEnabled( false ); >+ mEditButton->setEnabled( false ); >+ } else { >+ mDeleteButton->setEnabled( true ); >+ mEditButton->setEnabled( true ); >+ } > } > > ResourceItem *ResourceView::findItem( ResourceCalendar *r ) >@@ -372,6 +417,19 @@ > return i; > } > >+ResourceItem *ResourceView::findItemByIdentifier( const QString& id ) >+{ >+ QListViewItem *item; >+ ResourceItem *i = 0; >+ for( item = mListView->firstChild(); item; item = item->itemBelow() ) { >+ i = static_cast<ResourceItem *>( item ); >+ if ( i->resourceIdentifier() == id ) >+ return i; >+ } >+ return 0; >+} >+ >+ > void ResourceView::contextMenuRequested ( QListViewItem *i, > const QPoint &pos, int ) > { >@@ -391,7 +449,7 @@ > menu->insertItem( i18n("Edit..."), this, SLOT( editResource() ) ); > menu->insertItem( i18n("Remove"), this, SLOT( removeResource() ) ); > menu->insertSeparator(); >- } >+ } > menu->insertItem( i18n("Add..."), this, SLOT( addResource() ) ); > > menu->popup( pos ); >@@ -443,3 +501,4 @@ > } > > #include "resourceview.moc" >+#endif // RESOURCEVIEW.CPP >diff -u -r kdepim/korganizer/resourceview.h proko2/korganizer/resourceview.h >--- kdepim/korganizer/resourceview.h 2004-08-25 16:04:58.000000000 +0200 >+++ proko2/korganizer/resourceview.h 2004-08-31 12:37:01.860986000 +0200 >@@ -60,9 +60,13 @@ > ResourceItem( KCal::ResourceCalendar *resource, ResourceView *view, > KListView *parent ); > ResourceItem( KCal::ResourceCalendar *resource, const QString& sub, >- ResourceView *view, ResourceItem* parent ); >+ const QString& label, ResourceView *view, >+ ResourceItem* parent ); > > KCal::ResourceCalendar *resource() { return mResource; } >+ const QString& resourceIdentifier() { return mResourceIdentifier; } >+ bool isSubresource() const { return mIsSubresource; } >+ void createSubresourceItems(); > > void update(); > >@@ -76,6 +80,8 @@ > ResourceView *mView; > bool mBlockStateChange; > bool mIsSubresource; >+ QString mResourceIdentifier; >+ bool mSubItemsCreated; > }; > > /** >@@ -108,6 +114,7 @@ > > protected: > ResourceItem *findItem( ResourceCalendar * ); >+ ResourceItem *findItemByIdentifier( const QString& id ); > ResourceItem *currentItem(); > > protected slots: >@@ -116,7 +123,11 @@ > void editResource(); > void currentChanged( QListViewItem* ); > void slotSubresourceAdded( ResourceCalendar *, const QString &, >+ const QString &resource,const QString& label ); >+ // FIXME proko2: merge once we are back in head by porting imap resource >+ void slotSubresourceAdded( ResourceCalendar *, const QString &, > const QString &resource ); >+ > void slotSubresourceRemoved( ResourceCalendar *, const QString &, > const QString &resource ); > void closeResource( ResourceCalendar * ); >@@ -136,5 +147,4 @@ > QPushButton *mEditButton; > QPtrList<ResourceCalendar> mResourcesToClose; > }; >- > #endif >diff -u -r kdepim/korganizer/version.h proko2/korganizer/version.h >--- kdepim/korganizer/version.h 2004-08-04 10:20:36.000000000 +0200 >+++ proko2/korganizer/version.h 2004-08-31 12:37:01.489042544 +0200 >@@ -53,6 +53,6 @@ > 3.2 alpha1 > */ > >-static const char korgVersion[] = "3.3"; >+static const char korgVersion[] = "3.3 (proko2 branch)"; > > #endif >diff -u -r kdepim/kresources/Makefile.am proko2/kresources/Makefile.am >--- kdepim/kresources/Makefile.am 2004-06-17 09:50:43.000000000 +0200 >+++ proko2/kresources/Makefile.am 2004-08-31 12:36:13.406352224 +0200 >@@ -2,4 +2,4 @@ > EXCHANGE_SUBDIR=exchange > endif > >-SUBDIRS = remote egroupware $(EXCHANGE_SUBDIR) imap slox >+SUBDIRS = kolab remote egroupware $(EXCHANGE_SUBDIR) imap slox >diff -u -r kdepim/libkcal/resourcecalendar.h proko2/libkcal/resourcecalendar.h >--- kdepim/libkcal/resourcecalendar.h 2004-07-16 14:03:50.000000000 +0200 >+++ proko2/libkcal/resourcecalendar.h 2004-08-31 12:37:04.790540640 +0200 >@@ -190,8 +190,12 @@ > /** > This signal is emitted when a subresource is added. > */ >- void signalSubresourceAdded( ResourceCalendar *, const QString &, >- const QString & ); >+ void signalSubresourceAdded( ResourceCalendar *, const QString& type, >+ const QString& subresource, const QString& label ); >+ >+ // FIXME proko2: merge once we are back in HEAD by porting imap resource >+ void signalSubresourceAdded( ResourceCalendar *, const QString& type, >+ const QString& subresource ); > > /** > This signal is emitted when a subresource is removed. >@@ -281,6 +285,15 @@ > Is this subresource active or not? > */ > virtual bool subresourceActive( const QString& ) const { return true; } >+ >+ /** >+ What is the label for this subresource? >+ */ >+ virtual const QString labelForSubresource( const QString& resource ) const >+ { >+ // the resource identifier is a sane fallback >+ return resource; >+ }; > > public slots: > /** >diff -u -r kdepim/libkdepim/addresseelineedit.cpp proko2/libkdepim/addresseelineedit.cpp >--- kdepim/libkdepim/addresseelineedit.cpp 2004-08-09 22:08:04.000000000 +0200 >+++ proko2/libkdepim/addresseelineedit.cpp 2004-08-31 12:36:54.658081008 +0200 >@@ -344,6 +344,7 @@ > m_previousAddresses = prevAddr; > QStringList items = s_completion->allMatches( s ); > items += s_completion->allMatches( "\"" + s ); >+ //kdDebug(5300) << " AddresseeLineEdit::doCompletion() found: " << items.join(" AND ") << endl; > uint beforeDollarCompletionCount = items.count(); > > if ( s.find( ' ' ) == -1 ) // one word, possibly given name >@@ -478,7 +479,44 @@ > //kdDebug(5300) << " AddresseeLineEdit::addContact() \"" << tmp << "\"" << endl; > QString fullEmail = addr.fullEmail( tmp ); > //kdDebug(5300) << " \"" << fullEmail << "\"" << endl; >+ //kdDebug(5300) << " " << weight << endl; > s_completion->addItem( fullEmail.simplifyWhiteSpace(), weight ); >+ // Try to guess the last name: if found, we add an extra >+ // entry to the list to make sure completion works even >+ // if the user starts by typing in the last name. >+ QString name( addr.realName().simplifyWhiteSpace() ); >+ if( name.endsWith("\"") ) >+ name.truncate( name.length()-1 ); >+ if( name.startsWith("\"") ) >+ name = name.mid( 1 ); >+ bool bDone = false; >+ int i = 1; >+ do{ >+ i = name.findRev(' '); >+ if( 1 < i ){ >+ QString sLastName( name.mid(i+1) ); >+ if( ! sLastName.isEmpty() && >+ 2 <= sLastName.length() && // last names must be at least 2 chars long >+ ! sLastName.endsWith(".") ){ // last names must not end with a dot (like "Jr." or "Sr.") >+ name.truncate( i ); >+ if( !name.isEmpty() ){ >+ sLastName.prepend( "\"" ); >+ sLastName.append( ", " + name + "\" <" ); >+ } >+ QString sExtraEntry( sLastName ); >+ sExtraEntry.append( tmp.isEmpty() ? addr.preferredEmail() : tmp ); >+ sExtraEntry.append( ">" ); >+ //kdDebug(5300) << " AddresseeLineEdit::addContact() added extra \"" << sExtraEntry.simplifyWhiteSpace() << "\"" << endl; >+ s_completion->addItem( sExtraEntry.simplifyWhiteSpace(), weight ); >+ bDone = true; >+ } >+ } >+ if( !bDone ){ >+ name.truncate( i ); >+ if( name.endsWith("\"") ) >+ name.truncate( name.length()-1 ); >+ } >+ }while( 1 < i && !bDone ); > } > } > >diff -u -r kdepim/wizards/Makefile.am proko2/wizards/Makefile.am >--- kdepim/wizards/Makefile.am 2004-07-25 16:24:54.000000000 +0200 >+++ proko2/wizards/Makefile.am 2004-08-31 12:36:50.694683536 +0200 >@@ -2,8 +2,7 @@ > > INCLUDES = -I$(top_srcdir)/libkdepim -I$(top_srcdir)/libkpimidentities -I$(top_srcdir)/libkcal \ > -I$(top_srcdir)/kresources/imap/shared -I$(top_srcdir) \ >- -I$(top_srcdir)/knotes \ >- -I$(top_srcdir)/certmanager/lib \ >+ -I$(top_srcdir)/knotes -I$(top_srcdir)/certmanager/lib \ > $(all_includes) > > bin_PROGRAMS = groupwarewizard egroupwarewizard sloxwizard kolabwizard >@@ -16,13 +15,12 @@ > > # Kolab > libkolabwizard_la_LDFLAGS = $(all_libraries) -no-undefined >-libkolabwizard_la_LIBADD = $(top_builddir)/kresources/imap/kcal/libkcal_imap.la \ >- $(top_builddir)/kresources/imap/kabc/libkabc_imap.la \ >- $(top_builddir)/kresources/imap/knotes/libknotes_imap.la \ >+libkolabwizard_la_LIBADD = $(top_builddir)/kresources/kolab/kcal/libkcalkolab.la \ >+ $(top_builddir)/kresources/kolab/kabc/libkabckolab.la \ >+ $(top_builddir)/kresources/kolab/knotes/libknoteskolab.la \ > $(top_builddir)/libkcal/libkcal.la \ > $(top_builddir)/libkdepim/libkdepim.la \ > $(top_builddir)/libkpimidentities/libkpimidentities.la >- > libkolabwizard_la_SOURCES = kolabwizard.cpp kmailchanges.cpp kolabconfig.kcfgc > > kolabwizard_LDADD = libkolabwizard.la $(LIB_KDEUI) >diff -u -r kdepim/wizards/kmailchanges.cpp proko2/wizards/kmailchanges.cpp >--- kdepim/wizards/kmailchanges.cpp 2004-07-22 02:02:02.000000000 +0200 >+++ proko2/wizards/kmailchanges.cpp 2004-08-31 12:36:51.091623192 +0200 >@@ -52,6 +52,17 @@ > > void apply() > { >+ QString email; >+ QString user = KolabConfig::self()->user(); >+ int pos = user.find( "@" ); >+ // with kolab the userid _is_ the full email >+ if ( pos > 0 ) >+ // The user typed in a full email address. Assume it's correct >+ email = user; >+ else >+ // Construct the email address. And use it for the username also >+ user = email = user+"@"+KolabConfig::self()->server(); >+ > KConfig c( "kmailrc" ); > c.setGroup( "General" ); > uint accCnt = c.readNumEntry( "accounts", 0 ); >@@ -68,19 +79,7 @@ > c.writeEntry( "Name", "Kolab Server" ); > c.writeEntry( "host", KolabConfig::self()->server() ); > >- c.writeEntry( "login", KolabConfig::self()->user() ); >- >- c.writeEntry( "sieve-support", "true" ); >- >- QString user = KolabConfig::self()->user(); >- int pos = user.find( "@" ); >- if ( pos > 0 ) user = user.left( pos ); >- >- QString email = user+"@"+KolabConfig::self()->server(); >- user = email; // with kolab the userid _is_ the full email >- >- c.setGroup( QString("Folder-%1").arg( uid ) ); >- c.writeEntry( "isOpen", true ); >+ c.writeEntry( "login", user ); > > if ( KolabConfig::self()->savePassword() ) { > c.writeEntry( "pass", encryptStr(KolabConfig::self()->password()) ); >@@ -89,6 +88,11 @@ > c.writeEntry( "port", "993" ); > c.writeEntry( "use-ssl", true ); > >+ c.writeEntry( "sieve-support", "true" ); >+ >+ c.setGroup( QString("Folder-%1").arg( uid ) ); >+ c.writeEntry( "isOpen", true ); >+ > c.setGroup( QString("Transport %1").arg(transCnt+1) ); > c.writeEntry( "name", "Kolab Server" ); > c.writeEntry( "host", KolabConfig::self()->server() ); >@@ -178,8 +182,8 @@ > c = new KConfigPropagator::ChangeConfig; > c->file = "kmailrc"; > c->group = "IMAP Resource"; >- c->name = "Folder Language"; >- c->value = "0"; // TODO: Fix the language >+ c->name = "TheIMAPResourceStorageFormat"; >+ c->value = "XML"; > changes.append( c ); > > changes.append( new CreateDisconnectedImapAccount ); >diff -u -r kdepim/wizards/kolabwizard.cpp proko2/wizards/kolabwizard.cpp >--- kdepim/wizards/kolabwizard.cpp 2004-08-04 10:06:21.000000000 +0200 >+++ proko2/wizards/kolabwizard.cpp 2004-08-31 12:36:50.697683080 +0200 >@@ -28,9 +28,9 @@ > #include <libkcal/resourcecalendar.h> > #include <kabc/resource.h> > >-#include "kresources/imap/kcal/resourceimap.h" >-#include "kresources/imap/kabc/resourceimap.h" >-#include "kresources/imap/knotes/resourceimap.h" >+#include "kresources/kolab/kcal/resourcekolab.h" >+#include "kresources/kolab/kabc/resourcekolab.h" >+#include "kresources/kolab/knotes/resourcekolab.h" > > #include <qwhatsthis.h> > #include <klineedit.h> >@@ -50,11 +50,24 @@ > > void apply() > { >- QString host = KolabConfig::self()->server(); >+ const QString host = KolabConfig::self()->server(); >+ >+ // Figure out the basedn > QString basedn = host; >+ // If the user gave a full email address, the domain name >+ // of that overrides the server name for the ldap dn >+ const QString user = KolabConfig::self()->user(); >+ int pos = user.find( "@" ); >+ if ( pos > 0 ) { >+ const QString h = user.mid( pos+1 ); >+ if ( !h.isEmpty() ) >+ // The user did type in a domain on the email address. Use that >+ basedn = h; >+ } > basedn.replace(".",",dc="); > basedn.prepend("dc="); > >+ // Set the changes > KConfig c( "kabldaprc" ); > c.setGroup( "LDAP" ); > bool hasMyServer = false; >@@ -72,11 +85,11 @@ > > }; > >-class CreateCalendarImapResource : public KConfigPropagator::Change >+class CreateCalendarKolabResource : public KConfigPropagator::Change > { > public: >- CreateCalendarImapResource() >- : KConfigPropagator::Change( i18n("Create Calendar IMAP Resource") ) >+ CreateCalendarKolabResource() >+ : KConfigPropagator::Change( i18n("Create Calendar Kolab Resource") ) > { > } > >@@ -84,18 +97,19 @@ > { > KCal::CalendarResourceManager m( "calendar" ); > m.readConfig(); >- KCal::ResourceIMAP *r = new KCal::ResourceIMAP(); >+ KCal::ResourceKolab *r = new KCal::ResourceKolab( 0 ); > r->setResourceName( i18n("Kolab Server") ); >+ r->setName( "kolab-resource" ); > m.add( r ); > m.writeConfig(); > } > }; > >-class CreateContactImapResource : public KConfigPropagator::Change >+class CreateContactKolabResource : public KConfigPropagator::Change > { > public: >- CreateContactImapResource() >- : KConfigPropagator::Change( i18n("Create Contact IMAP Resource") ) >+ CreateContactKolabResource() >+ : KConfigPropagator::Change( i18n("Create Contact Kolab Resource") ) > { > } > >@@ -103,19 +117,20 @@ > { > KRES::Manager<KABC::Resource> m( "contact" ); > m.readConfig(); >- KABC::ResourceIMAP *r = new KABC::ResourceIMAP( 0 ); >+ KABC::ResourceKolab *r = new KABC::ResourceKolab( 0 ); > r->setResourceName( i18n("Kolab Server") ); >+ r->setName( "kolab-resource" ); > m.add( r ); > m.writeConfig(); > } > > }; > >-class CreateNotesImapResource : public KConfigPropagator::Change >+class CreateNotesKolabResource : public KConfigPropagator::Change > { > public: >- CreateNotesImapResource() >- : KConfigPropagator::Change( i18n("Create Notes IMAP Resource") ) >+ CreateNotesKolabResource() >+ : KConfigPropagator::Change( i18n("Create Notes Kolab Resource") ) > { > } > >@@ -123,8 +138,9 @@ > { > KRES::Manager<ResourceNotes> m( "notes" ); > m.readConfig(); >- KNotesIMAP::ResourceIMAP *r = new KNotesIMAP::ResourceIMAP( 0 ); >+ Kolab::ResourceKolab *r = new Kolab::ResourceKolab( 0 ); > r->setResourceName( i18n("Kolab Server") ); >+ r->setName( "kolab-resource" ); > m.add( r ); > m.writeConfig(); > } >@@ -200,12 +216,12 @@ > m.readConfig(); > KCal::CalendarResourceManager::Iterator it; > for ( it = m.begin(); it != m.end(); ++it ) { >- if ( (*it)->type() == "imap" ) break; >+ if ( (*it)->type() == "kolab" ) break; > } > if ( it == m.end() ) { >- changes.append( new CreateCalendarImapResource ); >- changes.append( new CreateContactImapResource ); >- changes.append( new CreateNotesImapResource ); >+ changes.append( new CreateCalendarKolabResource ); >+ changes.append( new CreateContactKolabResource ); >+ changes.append( new CreateNotesKolabResource ); > } > } > }; >@@ -245,7 +261,11 @@ > > topLayout->setRowStretch( 4, 1 ); > >- setupRulesPage(); >+ //DF: I don't see the point in showing the user those pages. >+ //They are very 'internal' and of no use to anyone other than developers. >+ //(This is even more true for the rules page. The changes page is sort of OK) >+ >+ //setupRulesPage(); > setupChangesPage(); > > setInitialSize( QSize( 600, 300 ) );
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 62382
:
38578
| 38579