TDE personal information management applications
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1207 lines
35 KiB

  1. /*
  2. This file is part of tdepim.
  3. Copyright (c) 2003 - 2004 Tobias Koenig <tokoe@kde.org>
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public
  6. License as published by the Free Software Foundation; either
  7. version 2 of the License, or (at your option) any later version.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Library General Public License for more details.
  12. You should have received a copy of the GNU Library General Public License
  13. along with this library; see the file COPYING.LIB. If not, write to
  14. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  15. Boston, MA 02110-1301, USA.
  16. */
  17. #include <stdlib.h>
  18. #include <typeinfo>
  19. #include <tqapplication.h>
  20. #include <tqdatetime.h>
  21. #include <tqptrlist.h>
  22. #include <tqstringlist.h>
  23. #include <tqtimer.h>
  24. #include <tdeabc/locknull.h>
  25. #include <kdebug.h>
  26. #include <tdelocale.h>
  27. #include <tderesources/configwidget.h>
  28. #include <kstandarddirs.h>
  29. #include <kstringhandler.h>
  30. #include <kurl.h>
  31. #include <libtdepim/kpimprefs.h>
  32. #include "libkcal/vcaldrag.h"
  33. #include "libkcal/vcalformat.h"
  34. #include "libkcal/icalformat.h"
  35. #include "libkcal/exceptions.h"
  36. #include "libkcal/incidence.h"
  37. #include "libkcal/event.h"
  38. #include "libkcal/todo.h"
  39. #include "libkcal/journal.h"
  40. #include "libkcal/filestorage.h"
  41. #include "libkcal/alarm.h"
  42. #include "kcal_egroupwareprefs.h"
  43. #include "kcal_resourcexmlrpcconfig.h"
  44. #include "kcal_resourcexmlrpc.h"
  45. #include "access.h"
  46. #include "synchronizer.h"
  47. #include "xmlrpciface.h"
  48. #define CAL_PRIO_LOW 1
  49. #define CAL_PRIO_NORMAL 2
  50. #define CAL_PRIO_HIGH 3
  51. #define CAL_RECUR_NONE 0
  52. #define CAL_RECUR_DAILY 1
  53. #define CAL_RECUR_WEEKLY 2
  54. #define CAL_RECUR_MONTHLY_MDAY 3
  55. #define CAL_RECUR_MONTHLY_WDAY 4
  56. #define CAL_RECUR_YEARLY 5
  57. #define CAL_SUNDAY 1
  58. #define CAL_MONDAY 2
  59. #define CAL_TUESDAY 4
  60. #define CAL_WEDNESDAY 8
  61. #define CAL_THURSDAY 16
  62. #define CAL_FRIDAY 32
  63. #define CAL_SATURDAY 64
  64. #define CAL_WEEKDAYS 62
  65. #define CAL_WEEKEND 65
  66. #define CAL_ALLDAYS 127
  67. using namespace KCal;
  68. typedef KRES::PluginFactory<ResourceXMLRPC, ResourceXMLRPCConfig> XMLRPCFactory;
  69. K_EXPORT_COMPONENT_FACTORY( kcal_xmlrpc, XMLRPCFactory )
  70. static const TQString SearchEventsCommand = "calendar.bocalendar.search";
  71. static const TQString AddEventCommand = "calendar.bocalendar.write";
  72. static const TQString DeleteEventCommand = "calendar.bocalendar.delete";
  73. static const TQString LoadEventCategoriesCommand = "calendar.bocalendar.categories";
  74. static const TQString SearchTodosCommand = "infolog.boinfolog.search";
  75. static const TQString AddTodoCommand = "infolog.boinfolog.write";
  76. static const TQString DeleteTodoCommand = "infolog.boinfolog.delete";
  77. static const TQString LoadTodoCategoriesCommand = "infolog.boinfolog.categories";
  78. static void setRights( Incidence *incidence, int rights )
  79. {
  80. incidence->setCustomProperty( "EGWRESOURCE", "RIGHTS", TQString::number( rights ) );
  81. }
  82. static int rights( Incidence *incidence )
  83. {
  84. return incidence->customProperty( "EGWRESOURCE", "RIGHTS" ).toInt();
  85. }
  86. ResourceXMLRPC::ResourceXMLRPC( const TDEConfig* config )
  87. : ResourceCached( config ), mServer( 0 ), mLock( 0 )
  88. {
  89. init();
  90. mPrefs->addGroupPrefix( identifier() );
  91. if ( config ) {
  92. readConfig( config );
  93. } else {
  94. setResourceName( i18n( "eGroupware Server" ) );
  95. }
  96. initEGroupware();
  97. }
  98. ResourceXMLRPC::ResourceXMLRPC( )
  99. : ResourceCached( 0 ), mServer( 0 ), mLock( 0 )
  100. {
  101. init();
  102. mPrefs->addGroupPrefix( identifier() );
  103. initEGroupware();
  104. }
  105. ResourceXMLRPC::~ResourceXMLRPC()
  106. {
  107. disableChangeNotification();
  108. delete mServer;
  109. mServer = 0;
  110. delete mLock;
  111. mLock = 0;
  112. delete mPrefs;
  113. mPrefs = 0;
  114. delete mSynchronizer;
  115. mSynchronizer = 0;
  116. }
  117. void ResourceXMLRPC::init()
  118. {
  119. setType( "xmlrpc" );
  120. mTodoStateMapper.setPath( "kcal/todostatemap/" );
  121. mPrefs = new EGroupwarePrefs;
  122. mLoaded = 0;
  123. mLock = new TDEABC::LockNull( true );
  124. mSynchronizer = new Synchronizer();
  125. }
  126. void ResourceXMLRPC::initEGroupware()
  127. {
  128. KURL url( mPrefs->url() );
  129. }
  130. void ResourceXMLRPC::readConfig( const TDEConfig* config )
  131. {
  132. mPrefs->readConfig();
  133. ResourceCached::readConfig( config );
  134. }
  135. void ResourceXMLRPC::writeConfig( TDEConfig* config )
  136. {
  137. ResourceCalendar::writeConfig( config );
  138. mPrefs->writeConfig();
  139. ResourceCached::writeConfig( config );
  140. }
  141. bool ResourceXMLRPC::doOpen()
  142. {
  143. kdDebug(5800) << "ResourceXMLRPC::doOpen()" << endl;
  144. if ( mServer )
  145. delete mServer;
  146. mServer = new KXMLRPC::Server( KURL(), this );
  147. mServer->setUrl( KURL( mPrefs->url() ) );
  148. mServer->setUserAgent( "KDE-Calendar" );
  149. TQStringVariantMap args;
  150. args.insert( "domain", mPrefs->domain() );
  151. args.insert( "username", mPrefs->user() );
  152. args.insert( "password", mPrefs->password() );
  153. mServer->call( "system.login", TQVariant( args ),
  154. this, TQT_SLOT( loginFinished( const TQValueList<TQVariant>&, const TQVariant& ) ),
  155. this, TQT_SLOT( fault( int, const TQString&, const TQVariant& ) ) );
  156. mSynchronizer->start();
  157. return true;
  158. }
  159. void ResourceXMLRPC::doClose()
  160. {
  161. kdDebug(5800) << "ResourceXMLRPC::doClose()" << endl;
  162. TQStringVariantMap args;
  163. args.insert( "sessionid", mSessionID );
  164. args.insert( "kp3", mKp3 );
  165. mServer->call( "system.logout", TQVariant( args ),
  166. this, TQT_SLOT( logoutFinished( const TQValueList<TQVariant>&, const TQVariant& ) ),
  167. this, TQT_SLOT( fault( int, const TQString&, const TQVariant& ) ) );
  168. mSynchronizer->start();
  169. }
  170. bool ResourceXMLRPC::doLoad()
  171. {
  172. kdDebug() << "ResourceXMLRPC::load()" << endl;
  173. mCalendar.close();
  174. disableChangeNotification();
  175. loadCache();
  176. enableChangeNotification();
  177. emit resourceChanged( this );
  178. clearChanges();
  179. loadCache();
  180. mTodoStateMapper.setIdentifier( type() + "_" + identifier() );
  181. mTodoStateMapper.load();
  182. TQStringVariantMap args, columns;
  183. args.insert( "start", TQDateTime( TQDate::currentDate().addDays( -12 ) ) );
  184. args.insert( "end", TQDateTime( TQDate::currentDate().addDays( 2000 ) ) );
  185. mServer->call( SearchEventsCommand, args,
  186. this, TQT_SLOT( listEventsFinished( const TQValueList<TQVariant>&, const TQVariant& ) ),
  187. this, TQT_SLOT( fault( int, const TQString&, const TQVariant& ) ) );
  188. args.clear();
  189. columns.insert( "type", "task" );
  190. args.insert( "filter", "none" );
  191. args.insert( "col_filter", columns );
  192. args.insert( "order", "id_parent" );
  193. mServer->call( SearchTodosCommand, args,
  194. this, TQT_SLOT( listTodosFinished( const TQValueList<TQVariant>&, const TQVariant& ) ),
  195. this, TQT_SLOT( fault( int, const TQString&, const TQVariant& ) ) );
  196. mServer->call( LoadEventCategoriesCommand, TQVariant( TQStringVariantMap() ),
  197. this, TQT_SLOT( loadEventCategoriesFinished( const TQValueList<TQVariant>&, const TQVariant& ) ),
  198. this, TQT_SLOT( fault( int, const TQString&, const TQVariant& ) ) );
  199. mServer->call( LoadTodoCategoriesCommand, TQVariant( false ),
  200. this, TQT_SLOT( loadTodoCategoriesFinished( const TQValueList<TQVariant>&, const TQVariant& ) ),
  201. this, TQT_SLOT( fault( int, const TQString&, const TQVariant& ) ) );
  202. return true;
  203. }
  204. bool ResourceXMLRPC::doSave()
  205. {
  206. if ( readOnly() || !hasChanges() ) {
  207. emit resourceSaved( this );
  208. return true;
  209. }
  210. saveCache();
  211. const Event::List events = mCalendar.rawEvents();
  212. Event::List::ConstIterator evIt;
  213. uint counter = 0;
  214. for ( evIt = events.begin(); evIt != events.end(); ++evIt ) {
  215. if ( !(*evIt)->isReadOnly() ) {
  216. TQStringVariantMap args;
  217. writeEvent( (*evIt), args );
  218. args.insert( "id", idMapper().remoteId( (*evIt)->uid() ).toInt() );
  219. mServer->call( AddEventCommand, TQVariant( args ),
  220. this, TQT_SLOT( updateEventFinished( const TQValueList<TQVariant>&, const TQVariant& ) ),
  221. this, TQT_SLOT( fault( int, const TQString&, const TQVariant& ) ) );
  222. counter++;
  223. }
  224. }
  225. const Todo::List todos = mCalendar.rawTodos();
  226. Todo::List::ConstIterator todoIt;
  227. for ( todoIt = todos.begin(); todoIt != todos.end(); ++todoIt ) {
  228. if ( !(*todoIt)->isReadOnly() ) {
  229. TQStringVariantMap args;
  230. writeTodo( (*todoIt), args );
  231. args.insert( "id", idMapper().remoteId( (*todoIt)->uid() ).toInt() );
  232. mServer->call( AddTodoCommand, TQVariant( args ),
  233. this, TQT_SLOT( updateTodoFinished( const TQValueList<TQVariant>&, const TQVariant& ) ),
  234. this, TQT_SLOT( fault( int, const TQString&, const TQVariant& ) ) );
  235. counter++;
  236. }
  237. }
  238. if ( counter != 0 )
  239. mSynchronizer->start();
  240. mTodoStateMapper.save();
  241. return true;
  242. }
  243. bool ResourceXMLRPC::isSaving()
  244. {
  245. return false;
  246. }
  247. TDEABC::Lock *ResourceXMLRPC::lock()
  248. {
  249. return mLock;
  250. }
  251. bool ResourceXMLRPC::addEvent( Event* ev )
  252. {
  253. TQStringVariantMap args;
  254. disableChangeNotification();
  255. setRights( ev, EGW_ACCESS_ALL );
  256. Event *oldEvent = mCalendar.event( ev->uid() );
  257. if ( oldEvent ) { // already exists
  258. if ( !oldEvent->isReadOnly() ) {
  259. writeEvent( ev, args );
  260. args.insert( "id", idMapper().remoteId( ev->uid() ).toInt() );
  261. mServer->call( AddEventCommand, TQVariant( args ),
  262. this, TQT_SLOT( updateEventFinished( const TQValueList<TQVariant>&, const TQVariant& ) ),
  263. this, TQT_SLOT( fault( int, const TQString&, const TQVariant& ) ) );
  264. mCalendar.deleteIncidence( oldEvent );
  265. mCalendar.addIncidence( ev );
  266. saveCache();
  267. }
  268. } else { // new event
  269. writeEvent( ev, args );
  270. mServer->call( AddEventCommand, TQVariant( args ),
  271. this, TQT_SLOT( addEventFinished( const TQValueList<TQVariant>&, const TQVariant& ) ),
  272. this, TQT_SLOT( fault( int, const TQString&, const TQVariant& ) ),
  273. TQVariant( ev->uid() ) );
  274. mCalendar.addEvent( ev );
  275. saveCache();
  276. }
  277. enableChangeNotification();
  278. return true;
  279. }
  280. bool ResourceXMLRPC::deleteEvent( Event* ev )
  281. {
  282. if ( !(rights( ev ) & EGW_ACCESS_DELETE) && rights( ev ) != -1 )
  283. return false;
  284. mServer->call( DeleteEventCommand, idMapper().remoteId( ev->uid() ).toInt(),
  285. this, TQT_SLOT( deleteEventFinished( const TQValueList<TQVariant>&,
  286. const TQVariant& ) ),
  287. this, TQT_SLOT( fault( int, const TQString&, const TQVariant& ) ),
  288. TQVariant( ev->uid() ) );
  289. return true;
  290. }
  291. Event *ResourceXMLRPC::event( const TQString& uid )
  292. {
  293. return mCalendar.event( uid );
  294. }
  295. Event::List ResourceXMLRPC::rawEventsForDate( const TQDate& qd,
  296. EventSortField sortField,
  297. SortDirection sortDirection )
  298. {
  299. return mCalendar.rawEventsForDate( qd, sortField, sortDirection );
  300. }
  301. Event::List ResourceXMLRPC::rawEvents( const TQDate& start, const TQDate& end,
  302. bool inclusive )
  303. {
  304. return mCalendar.rawEvents( start, end, inclusive );
  305. }
  306. Event::List ResourceXMLRPC::rawEventsForDate( const TQDateTime& qdt )
  307. {
  308. return mCalendar.rawEventsForDate( qdt.date() );
  309. }
  310. Event::List ResourceXMLRPC::rawEvents()
  311. {
  312. return mCalendar.rawEvents();
  313. }
  314. bool ResourceXMLRPC::addTodo( Todo *todo )
  315. {
  316. TQStringVariantMap args;
  317. disableChangeNotification();
  318. setRights( todo, EGW_ACCESS_ALL );
  319. Todo *oldTodo = mCalendar.todo( todo->uid() );
  320. if ( oldTodo ) { // already exists
  321. if ( !oldTodo->isReadOnly() ) {
  322. writeTodo( todo, args );
  323. args.insert( "id", idMapper().remoteId( todo->uid() ).toInt() );
  324. mServer->call( AddTodoCommand, TQVariant( args ),
  325. this, TQT_SLOT( updateTodoFinished( const TQValueList<TQVariant>&, const TQVariant& ) ),
  326. this, TQT_SLOT( fault( int, const TQString&, const TQVariant& ) ) );
  327. mCalendar.deleteIncidence( oldTodo );
  328. mCalendar.addIncidence( todo );
  329. saveCache();
  330. }
  331. } else { // new todo
  332. writeTodo( todo, args );
  333. mServer->call( AddTodoCommand, TQVariant( args ),
  334. this, TQT_SLOT( addTodoFinished( const TQValueList<TQVariant>&, const TQVariant& ) ),
  335. this, TQT_SLOT( fault( int, const TQString&, const TQVariant& ) ),
  336. TQVariant( todo->uid() ) );
  337. mCalendar.addTodo( todo );
  338. saveCache();
  339. }
  340. enableChangeNotification();
  341. return true;
  342. }
  343. bool ResourceXMLRPC::deleteTodo( Todo *todo )
  344. {
  345. if ( !(rights( todo ) & EGW_ACCESS_DELETE) && rights( todo ) != -1 )
  346. return false;
  347. mServer->call( DeleteTodoCommand, idMapper().remoteId( todo->uid() ).toInt(),
  348. this, TQT_SLOT( deleteTodoFinished( const TQValueList<TQVariant>&,
  349. const TQVariant& ) ),
  350. this, TQT_SLOT( fault( int, const TQString&, const TQVariant& ) ),
  351. TQVariant( todo->uid() ) );
  352. return true;
  353. }
  354. Todo::List ResourceXMLRPC::rawTodos()
  355. {
  356. return mCalendar.rawTodos();
  357. }
  358. Todo *ResourceXMLRPC::todo( const TQString& uid )
  359. {
  360. return mCalendar.todo( uid );
  361. }
  362. Todo::List ResourceXMLRPC::rawTodosForDate( const TQDate& date )
  363. {
  364. return mCalendar.rawTodosForDate( date );
  365. }
  366. bool ResourceXMLRPC::addJournal( Journal* journal )
  367. {
  368. return mCalendar.addJournal( journal );
  369. }
  370. bool ResourceXMLRPC::deleteJournal( Journal* journal )
  371. {
  372. return mCalendar.deleteJournal( journal );
  373. }
  374. Journal::List ResourceXMLRPC::journals( const TQDate& date )
  375. {
  376. return mCalendar.journals( date );
  377. }
  378. Journal *ResourceXMLRPC::journal( const TQString& uid )
  379. {
  380. return mCalendar.journal( uid );
  381. }
  382. Alarm::List ResourceXMLRPC::alarmsTo( const TQDateTime& to )
  383. {
  384. return mCalendar.alarmsTo( to );
  385. }
  386. Alarm::List ResourceXMLRPC::alarms( const TQDateTime& from, const TQDateTime& to )
  387. {
  388. return mCalendar.alarms( from, to );
  389. }
  390. void ResourceXMLRPC::dump() const
  391. {
  392. ResourceCalendar::dump();
  393. }
  394. void ResourceXMLRPC::reload()
  395. {
  396. load();
  397. }
  398. void ResourceXMLRPC::loginFinished( const TQValueList<TQVariant>& variant,
  399. const TQVariant& )
  400. {
  401. TQStringVariantMap map = variant[ 0 ].toMap();
  402. KURL url = KURL( mPrefs->url() );
  403. if ( map[ "GOAWAY" ].toString() == "XOXO" ) { // failed
  404. mSessionID = mKp3 = "";
  405. } else {
  406. mSessionID = map[ "sessionid" ].toString();
  407. mKp3 = map[ "kp3" ].toString();
  408. }
  409. url.setUser( mSessionID );
  410. url.setPass( mKp3 );
  411. mServer->setUrl( url );
  412. mSynchronizer->stop();
  413. }
  414. void ResourceXMLRPC::logoutFinished( const TQValueList<TQVariant>& variant,
  415. const TQVariant& )
  416. {
  417. TQStringVariantMap map = variant[ 0 ].toMap();
  418. if ( map[ "GOODBYE" ].toString() != "XOXO" )
  419. kdError() << "logout failed" << endl;
  420. KURL url = KURL( mPrefs->url() );
  421. mSessionID = mKp3 = "";
  422. url.setUser( mSessionID );
  423. url.setPass( mKp3 );
  424. mServer->setUrl( url );
  425. mSynchronizer->stop();
  426. }
  427. void ResourceXMLRPC::listEventsFinished( const TQValueList<TQVariant>& list,
  428. const TQVariant& )
  429. {
  430. const TQValueList<TQVariant> eventList = list[ 0 ].toList();
  431. TQValueList<TQVariant>::ConstIterator eventIt;
  432. disableChangeNotification();
  433. Event::List retrievedEvents;
  434. bool changed = false;
  435. for ( eventIt = eventList.begin(); eventIt != eventList.end(); ++eventIt ) {
  436. TQStringVariantMap map = (*eventIt).toMap();
  437. Event *event = new Event;
  438. event->setFloats( false );
  439. TQString uid;
  440. readEvent( map, event, uid );
  441. // do we already have this event?
  442. Event *oldEvent = 0;
  443. TQString localUid = idMapper().localId( uid );
  444. if ( !localUid.isEmpty() )
  445. oldEvent = mCalendar.event( localUid );
  446. if ( oldEvent ) {
  447. event->setUid( oldEvent->uid() );
  448. event->setCreated( oldEvent->created() );
  449. if ( !(*oldEvent == *event) ) {
  450. mCalendar.deleteEvent( oldEvent );
  451. mCalendar.addEvent( event );
  452. retrievedEvents.append( event );
  453. changed = true;
  454. } else
  455. delete event;
  456. } else {
  457. if ( !localUid.isEmpty() )
  458. event->setUid( localUid );
  459. idMapper().setRemoteId( event->uid(), uid );
  460. mCalendar.addEvent( event );
  461. retrievedEvents.append( event );
  462. changed = true;
  463. }
  464. }
  465. enableChangeNotification();
  466. clearChanges();
  467. if ( changed ) {
  468. cleanUpEventCache( retrievedEvents );
  469. saveCache();
  470. emit resourceChanged( this );
  471. }
  472. checkLoadingFinished();
  473. }
  474. void ResourceXMLRPC::deleteEventFinished( const TQValueList<TQVariant>&,
  475. const TQVariant& id )
  476. {
  477. idMapper().removeRemoteId( idMapper().remoteId( id.toString() ) );
  478. Event *ev = mCalendar.event( id.toString() );
  479. disableChangeNotification();
  480. mCalendar.deleteEvent( ev );
  481. saveCache();
  482. enableChangeNotification();
  483. emit resourceChanged( this );
  484. }
  485. void ResourceXMLRPC::updateEventFinished( const TQValueList<TQVariant>&,
  486. const TQVariant& )
  487. {
  488. mSynchronizer->stop();
  489. }
  490. void ResourceXMLRPC::addEventFinished( const TQValueList<TQVariant>& list,
  491. const TQVariant& id )
  492. {
  493. idMapper().setRemoteId( id.toString(), list[ 0 ].toString() );
  494. emit resourceChanged( this );
  495. }
  496. void ResourceXMLRPC::loadEventCategoriesFinished( const TQValueList<TQVariant> &mapList, const TQVariant& )
  497. {
  498. mEventCategoryMap.clear();
  499. const TQStringVariantMap map = mapList[ 0 ].toMap();
  500. TQStringVariantMap::ConstIterator it;
  501. KPimPrefs prefs( "korganizerrc" );
  502. for ( it = map.begin(); it != map.end(); ++it ) {
  503. mEventCategoryMap.insert( it.data().toString(), it.key().toInt() );
  504. if ( prefs.mCustomCategories.find( it.data().toString() ) == prefs.mCustomCategories.end() )
  505. prefs.mCustomCategories.append( it.data().toString() );
  506. }
  507. prefs.usrWriteConfig();
  508. prefs.config()->sync();
  509. checkLoadingFinished();
  510. }
  511. void ResourceXMLRPC::listTodosFinished( const TQValueList<TQVariant>& list,
  512. const TQVariant& )
  513. {
  514. const TQValueList<TQVariant> todoList = list[ 0 ].toList();
  515. TQValueList<TQVariant>::ConstIterator todoIt;
  516. disableChangeNotification();
  517. Todo::List retrievedTodos;
  518. bool changed = false;
  519. for ( todoIt = todoList.begin(); todoIt != todoList.end(); ++todoIt ) {
  520. TQStringVariantMap map = (*todoIt).toMap();
  521. Todo *todo = new Todo;
  522. TQString uid;
  523. readTodo( map, todo, uid );
  524. // do we already have this todo?
  525. Todo *oldTodo = 0;
  526. TQString localUid = idMapper().localId( uid );
  527. if ( !localUid.isEmpty() )
  528. oldTodo = mCalendar.todo( localUid );
  529. if ( oldTodo ) {
  530. todo->setUid( oldTodo->uid() );
  531. todo->setCreated( oldTodo->created() );
  532. if ( !(*oldTodo == *todo) ) {
  533. mCalendar.deleteTodo( oldTodo );
  534. mCalendar.addTodo( todo );
  535. retrievedTodos.append( todo );
  536. changed = true;
  537. } else
  538. delete todo;
  539. } else {
  540. idMapper().setRemoteId( todo->uid(), uid );
  541. mCalendar.addTodo( todo );
  542. retrievedTodos.append( todo );
  543. changed = true;
  544. }
  545. }
  546. enableChangeNotification();
  547. if ( changed ) {
  548. cleanUpTodoCache( retrievedTodos );
  549. saveCache();
  550. emit resourceChanged( this );
  551. }
  552. checkLoadingFinished();
  553. }
  554. void ResourceXMLRPC::deleteTodoFinished( const TQValueList<TQVariant>&,
  555. const TQVariant& id )
  556. {
  557. idMapper().removeRemoteId( idMapper().remoteId( id.toString() ) );
  558. mTodoStateMapper.remove( idMapper().remoteId( id.toString() ) );
  559. Todo *todo = mCalendar.todo( id.toString() );
  560. disableChangeNotification();
  561. mCalendar.deleteTodo( todo );
  562. saveCache();
  563. enableChangeNotification();
  564. emit resourceChanged( this );
  565. }
  566. void ResourceXMLRPC::addTodoFinished( const TQValueList<TQVariant>& list,
  567. const TQVariant& id )
  568. {
  569. idMapper().setRemoteId( id.toString(), list[ 0 ].toString() );
  570. emit resourceChanged( this );
  571. }
  572. void ResourceXMLRPC::updateTodoFinished( const TQValueList<TQVariant>&,
  573. const TQVariant& )
  574. {
  575. mSynchronizer->stop();
  576. }
  577. void ResourceXMLRPC::loadTodoCategoriesFinished( const TQValueList<TQVariant> &mapList, const TQVariant& )
  578. {
  579. mTodoCategoryMap.clear();
  580. const TQStringVariantMap map = mapList[ 0 ].toMap();
  581. TQStringVariantMap::ConstIterator it;
  582. KPimPrefs prefs( "korganizerrc" );
  583. for ( it = map.begin(); it != map.end(); ++it ) {
  584. mTodoCategoryMap.insert( it.data().toString(), it.key().toInt() );
  585. if ( prefs.mCustomCategories.find( it.data().toString() ) == prefs.mCustomCategories.end() )
  586. prefs.mCustomCategories.append( it.data().toString() );
  587. }
  588. prefs.usrWriteConfig();
  589. prefs.config()->sync();
  590. checkLoadingFinished();
  591. }
  592. void ResourceXMLRPC::fault( int error, const TQString& errorMsg,
  593. const TQVariant& )
  594. {
  595. kdError() << "Server send error " << error << ": " << errorMsg << endl;
  596. mSynchronizer->stop();
  597. }
  598. void ResourceXMLRPC::readEvent( const TQStringVariantMap &args, Event *event,
  599. TQString &uid )
  600. {
  601. // for recurrence
  602. int rType = CAL_RECUR_NONE;
  603. int rInterval = 1;
  604. int rData = 0;
  605. int rights = 0;
  606. TQDateTime rEndDate;
  607. TQValueList<TQDateTime> rExceptions;
  608. TQStringVariantMap::ConstIterator it;
  609. for ( it = args.begin(); it != args.end(); ++it ) {
  610. if ( it.key() == "id" ) {
  611. uid = it.data().toString();
  612. } else if ( it.key() == "rights" ) {
  613. rights = it.data().toInt();
  614. } else if ( it.key() == "start" ) {
  615. event->setDtStart( it.data().toDateTime() );
  616. } else if ( it.key() == "end" ) {
  617. TQDateTime start = args[ "start" ].toDateTime();
  618. TQDateTime end = it.data().toDateTime();
  619. if ( start.time() == end.time() &&
  620. start.time().hour() == 0 && start.time().minute() == 0 &&
  621. start.time().second() == 0 ) {
  622. event->setDtEnd( end.addDays( -1 ) );
  623. event->setFloats( true );
  624. } else {
  625. event->setDtEnd( end );
  626. event->setHasEndDate( true );
  627. }
  628. } else if ( it.key() == "modtime" ) {
  629. event->setLastModified( it.data().toDateTime() );
  630. } else if ( it.key() == "title" ) {
  631. event->setSummary( it.data().toString() );
  632. } else if ( it.key() == "description" ) {
  633. event->setDescription( it.data().toString() );
  634. } else if ( it.key() == "location" ) {
  635. event->setLocation( it.data().toString() );
  636. } else if ( it.key() == "access" ) {
  637. event->setSecrecy( (it.data().toString() == "public" ?
  638. Incidence::SecrecyPublic : Incidence::SecrecyPrivate) );
  639. } else if ( it.key() == "category" ) {
  640. const TQStringVariantMap categories = it.data().toMap();
  641. TQStringVariantMap::ConstIterator catIt;
  642. TQStringList eventCategories;
  643. for ( catIt = categories.begin(); catIt != categories.end(); ++catIt ) {
  644. mEventCategoryMap.insert( catIt.data().toString(), catIt.key().toInt() );
  645. eventCategories.append( catIt.data().toString() );
  646. }
  647. event->setCategories( eventCategories );
  648. } else if ( it.key() == "priority" ) {
  649. int priority = 0;
  650. switch( it.data().toInt() ) {
  651. case CAL_PRIO_LOW:
  652. priority = 10;
  653. break;
  654. case CAL_PRIO_NORMAL:
  655. priority = 5;
  656. break;
  657. case CAL_PRIO_HIGH:
  658. priority = 1;
  659. }
  660. event->setPriority( priority );
  661. } else if ( it.key() == "recur_type" ) {
  662. rType = it.data().toInt();
  663. } else if ( it.key() == "recur_interval" ) {
  664. rInterval = it.data().toInt();
  665. } else if ( it.key() == "recur_enddate" ) {
  666. rEndDate = it.data().toDateTime();
  667. } else if ( it.key() == "recur_data" ) {
  668. rData = it.data().toInt();
  669. } else if ( it.key() == "recur_exception" ) {
  670. const TQStringVariantMap dateList = it.data().toMap();
  671. TQStringVariantMap::ConstIterator dateIt;
  672. for ( dateIt = dateList.begin(); dateIt != dateList.end(); ++dateIt )
  673. rExceptions.append( (*dateIt).toDateTime() );
  674. } else if ( it.key() == "participants" ) {
  675. const TQStringVariantMap persons = it.data().toMap();
  676. TQStringVariantMap::ConstIterator personsIt;
  677. for ( personsIt = persons.begin(); personsIt != persons.end(); ++personsIt ) {
  678. TQStringVariantMap person = (*personsIt).toMap();
  679. Attendee::PartStat status = Attendee::InProcess;
  680. if ( person[ "status" ] == "A" )
  681. status = Attendee::Accepted;
  682. else if ( person[ "status" ] == "R" )
  683. status = Attendee::Declined;
  684. else if ( person[ "status" ] == "T" )
  685. status = Attendee::Tentative;
  686. else if ( person[ "status" ] == "N" )
  687. status = Attendee::InProcess;
  688. Attendee *attendee = new Attendee( person[ "name" ].toString(),
  689. person[ "email" ].toString(),
  690. false, status );
  691. attendee->setUid( personsIt.key() );
  692. event->addAttendee( attendee );
  693. }
  694. } else if ( it.key() == "alarm" ) {
  695. const TQStringVariantMap alarmList = it.data().toMap();
  696. TQStringVariantMap::ConstIterator alarmIt;
  697. for ( alarmIt = alarmList.begin(); alarmIt != alarmList.end(); ++alarmIt ) {
  698. TQStringVariantMap alarm = (*alarmIt).toMap();
  699. Alarm *vAlarm = event->newAlarm();
  700. vAlarm->setText( event->summary() );
  701. vAlarm->setTime( alarm[ "time" ].toDateTime() );
  702. vAlarm->setStartOffset( alarm[ "offset" ].toInt() );
  703. vAlarm->setEnabled( alarm[ "enabled" ].toBool() );
  704. }
  705. }
  706. }
  707. if ( rType != CAL_RECUR_NONE && rInterval > 0 ) {
  708. Recurrence *re = event->recurrence();
  709. // re->setRecurStart( event->dtStart() );
  710. if ( rInterval == 0 ) // libkcal crashes with rInterval == 0
  711. rInterval = 1;
  712. switch ( rType ) {
  713. case CAL_RECUR_DAILY:
  714. re->setDaily( rInterval );
  715. break;
  716. case CAL_RECUR_WEEKLY: {
  717. TQBitArray weekMask( 7 );
  718. weekMask.setBit( 0, rData & CAL_MONDAY );
  719. weekMask.setBit( 1, rData & CAL_TUESDAY );
  720. weekMask.setBit( 2, rData & CAL_WEDNESDAY );
  721. weekMask.setBit( 3, rData & CAL_THURSDAY );
  722. weekMask.setBit( 4, rData & CAL_FRIDAY );
  723. weekMask.setBit( 5, rData & CAL_SATURDAY );
  724. weekMask.setBit( 6, rData & CAL_SUNDAY );
  725. re->setWeekly( rInterval, weekMask );
  726. break; }
  727. case CAL_RECUR_MONTHLY_MDAY:
  728. re->setMonthly( rInterval );
  729. break;
  730. case CAL_RECUR_MONTHLY_WDAY:
  731. re->setMonthly( rInterval );
  732. // TODO: Set the correct monthly pos
  733. break;
  734. case CAL_RECUR_YEARLY:
  735. re->setYearly( rInterval );
  736. break;
  737. }
  738. if ( rEndDate.date().isValid() )
  739. re->setEndDate( rEndDate.date() );
  740. TQValueList<TQDateTime>::ConstIterator exIt;
  741. for ( exIt = rExceptions.begin(); exIt != rExceptions.end(); ++exIt )
  742. re->addExDateTime( *exIt );
  743. }
  744. event->setReadOnly( !(rights & EGW_ACCESS_EDIT) );
  745. setRights( event, rights );
  746. }
  747. void ResourceXMLRPC::writeEvent( Event *event, TQStringVariantMap &args )
  748. {
  749. args.insert( "start", event->dtStart() );
  750. // handle all day events
  751. if ( event->doesFloat() )
  752. args.insert( "end", TQDateTime(event->dtEnd().addDays( 1 )) );
  753. else
  754. args.insert( "end", event->dtEnd() );
  755. args.insert( "modtime", event->lastModified() );
  756. args.insert( "title", event->summary() );
  757. args.insert( "description", event->description() );
  758. args.insert( "location", event->location() );
  759. // SECRECY
  760. args.insert( "access", (event->secrecy() == Incidence::SecrecyPublic ? "public" : "private") );
  761. // CATEGORY
  762. const TQStringList categories = event->categories();
  763. TQStringList::ConstIterator catIt;
  764. TQStringVariantMap catMap;
  765. int counter = 0;
  766. for ( catIt = categories.begin(); catIt != categories.end(); ++catIt ) {
  767. TQMap<TQString, int>::Iterator it = mEventCategoryMap.find( *catIt );
  768. if ( it == mEventCategoryMap.end() ) // new category
  769. catMap.insert( TQString::number( counter-- ), *catIt );
  770. else
  771. catMap.insert( TQString::number( it.data() ), *catIt );
  772. }
  773. args.insert( "category", catMap );
  774. // PRIORITY
  775. int priority = 0;
  776. if ( event->priority() == 1 )
  777. priority = CAL_PRIO_HIGH;
  778. else if ( event->priority() > 1 && event->priority() <= 5 )
  779. priority = CAL_PRIO_NORMAL;
  780. else
  781. priority = CAL_PRIO_LOW;
  782. args.insert( "priority", priority );
  783. // RECURRENCE
  784. Recurrence *rec = event->recurrence();
  785. if ( !rec->doesRecur() ) {
  786. args.insert( "recur_type", int( 0 ) );
  787. args.insert( "recur_interval", int( 0 ) );
  788. args.insert( "recur_enddate", TQDateTime() );
  789. args.insert( "recur_data", int( 0 ) );
  790. args.insert( "recur_exception", TQStringVariantMap() );
  791. } else {
  792. switch ( rec->recurrenceType() ) {
  793. case Recurrence::rDaily:
  794. args.insert( "recur_type", int( CAL_RECUR_DAILY ) );
  795. break;
  796. case Recurrence::rWeekly: {
  797. int weekMask = 0;
  798. if ( rec->days().testBit( 0 ) )
  799. weekMask += CAL_MONDAY;
  800. if ( rec->days().testBit( 1 ) )
  801. weekMask += CAL_TUESDAY;
  802. if ( rec->days().testBit( 2 ) )
  803. weekMask += CAL_WEDNESDAY;
  804. if ( rec->days().testBit( 3 ) )
  805. weekMask += CAL_THURSDAY;
  806. if ( rec->days().testBit( 4 ) )
  807. weekMask += CAL_FRIDAY;
  808. if ( rec->days().testBit( 5 ) )
  809. weekMask += CAL_SATURDAY;
  810. if ( rec->days().testBit( 6 ) )
  811. weekMask += CAL_SUNDAY;
  812. args.insert( "recur_data", weekMask );
  813. args.insert( "recur_type", int( CAL_RECUR_WEEKLY ) );
  814. }
  815. break;
  816. case Recurrence::rMonthlyPos:
  817. args.insert( "recur_type", int( CAL_RECUR_MONTHLY_MDAY ) );
  818. break;
  819. case Recurrence::rMonthlyDay:
  820. args.insert( "recur_type", int( CAL_RECUR_MONTHLY_WDAY ) );
  821. break;
  822. case Recurrence::rYearlyDay:
  823. args.insert( "recur_type", int( CAL_RECUR_YEARLY ) );
  824. break;
  825. default:
  826. break;
  827. }
  828. args.insert( "recur_interval", rec->frequency() );
  829. args.insert( "recur_enddate", rec->endDateTime() );
  830. // TODO: Also use exception dates!
  831. const TQValueList<TQDateTime> dates = event->recurrence()->exDateTimes();
  832. TQValueList<TQDateTime>::ConstIterator dateIt;
  833. TQStringVariantMap exMap;
  834. int counter = 0;
  835. for ( dateIt = dates.begin(); dateIt != dates.end(); ++dateIt, ++counter )
  836. exMap.insert( TQString::number( counter ), *dateIt );
  837. args.insert( "recur_exception", exMap );
  838. }
  839. // PARTICIPANTS
  840. const Attendee::List attendees = event->attendees();
  841. Attendee::List::ConstIterator attIt;
  842. TQStringVariantMap persons;
  843. for ( attIt = attendees.begin(); attIt != attendees.end(); ++attIt ) {
  844. TQStringVariantMap person;
  845. TQString status;
  846. if ( (*attIt)->status() == Attendee::Accepted )
  847. status = "A";
  848. else if ( (*attIt)->status() == Attendee::Declined )
  849. status = "R";
  850. else if ( (*attIt)->status() == Attendee::Tentative )
  851. status = "T";
  852. else
  853. status = "N";
  854. person.insert( "status", status );
  855. person.insert( "name", (*attIt)->name() );
  856. person.insert( "email", (*attIt)->email() );
  857. persons.insert( (*attIt)->uid(), person );
  858. }
  859. args.insert( "participants", persons );
  860. // ALARMS
  861. const Alarm::List alarms = event->alarms();
  862. Alarm::List::ConstIterator alarmIt;
  863. TQStringVariantMap alarmMap;
  864. for ( alarmIt = alarms.begin(); alarmIt != alarms.end(); ++alarmIt ) {
  865. TQStringVariantMap alarm;
  866. alarm.insert( "time", (*alarmIt)->time() );
  867. alarm.insert( "offset", (*alarmIt)->startOffset().asSeconds() );
  868. alarm.insert( "enabled", ( (*alarmIt)->enabled() ? int( 1 ) : int( 0 ) ) );
  869. alarmMap.insert( "id", alarm ); // that sucks...
  870. }
  871. args.insert( "alarm", alarmMap );
  872. }
  873. void ResourceXMLRPC::writeTodo( Todo* todo, TQStringVariantMap& args )
  874. {
  875. args.insert( "subject", todo->summary() );
  876. args.insert( "des", todo->description() );
  877. args.insert( "access",
  878. (todo->secrecy() == Todo::SecrecyPublic ? "public" : "private" ) );
  879. // CATEGORIES
  880. TQStringVariantMap catMap;
  881. const TQStringList categories = todo->categories();
  882. TQStringList::ConstIterator catIt;
  883. int counter = 0;
  884. for ( catIt = categories.begin(); catIt != categories.end(); ++catIt ) {
  885. TQMap<TQString, int>::Iterator it = mTodoCategoryMap.find( *catIt );
  886. if ( it == mTodoCategoryMap.end() )
  887. catMap.insert( TQString::number( counter-- ), *catIt );
  888. else
  889. catMap.insert( TQString::number( it.data() ), *catIt );
  890. }
  891. args.insert( "category", catMap );
  892. args.insert( "datemodified", todo->lastModified() );
  893. args.insert( "startdate", todo->dtStart() );
  894. args.insert( "enddate", todo->dtDue() );
  895. // SUBTODO
  896. Incidence *inc = todo->relatedTo();
  897. if ( inc ) {
  898. TQString parentUid = idMapper().remoteId( inc->uid() );
  899. args.insert( "id_parent", parentUid );
  900. }
  901. // STATE
  902. TQString remoteId = idMapper().remoteId( todo->uid() );
  903. TQString status = mTodoStateMapper.remoteState( remoteId, todo->percentComplete() );
  904. args.insert( "status", status );
  905. }
  906. void ResourceXMLRPC::readTodo( const TQStringVariantMap& args, Todo *todo, TQString &uid )
  907. {
  908. uid = args[ "id" ].toString();
  909. /*
  910. info_from
  911. info_addr
  912. info_owner
  913. info_responsible
  914. info_modifier
  915. */
  916. todo->setSummary( args[ "subject" ].toString() );
  917. todo->setDescription( args[ "des" ].toString() );
  918. todo->setSecrecy( args[ "access" ].toString() == "public" ? Todo::SecrecyPublic : Todo::SecrecyPrivate );
  919. // CATEGORIES
  920. const TQStringVariantMap categories = args[ "category" ].toMap();
  921. TQStringVariantMap::ConstIterator it;
  922. TQStringList todoCategories;
  923. for ( it = categories.begin(); it != categories.end(); ++it ) {
  924. mTodoCategoryMap.insert( it.data().toString(), it.key().toInt() );
  925. todoCategories.append( it.data().toString() );
  926. }
  927. todo->setCategories( todoCategories );
  928. todo->setLastModified( args[ "datemodified" ].toDateTime() );
  929. todo->setFloats( true );
  930. TQDateTime dateTime = args[ "startdate" ].toDateTime();
  931. if ( dateTime.isValid() ) {
  932. todo->setDtStart( dateTime );
  933. todo->setHasStartDate( true );
  934. if ( !dateTime.time().isNull() )
  935. todo->setFloats( false );
  936. }
  937. dateTime = args[ "enddate" ].toDateTime();
  938. if ( dateTime.isValid() ) {
  939. todo->setDtDue( dateTime );
  940. todo->setHasDueDate( true );
  941. if ( !dateTime.time().isNull() )
  942. todo->setFloats( false );
  943. }
  944. // SUBTODO
  945. TQString parentId = args[ "id_parent" ].toString();
  946. if ( parentId != "0" ) { // we are a sub todo
  947. TQString localParentUid = idMapper().localId( parentId );
  948. if ( !localParentUid.isEmpty() ) { // found parent todo
  949. Todo *parent = mCalendar.todo( localParentUid );
  950. if ( parent )
  951. todo->setRelatedTo( parent );
  952. }
  953. }
  954. // STATE
  955. TQString status = args[ "status" ].toString();
  956. int state = TodoStateMapper::toLocal( status );
  957. mTodoStateMapper.addTodoState( uid, state, status );
  958. todo->setPercentComplete( state );
  959. int rights = args[ "rights" ].toInt();
  960. todo->setReadOnly( !(rights & EGW_ACCESS_EDIT) );
  961. setRights( todo, rights );
  962. }
  963. void ResourceXMLRPC::checkLoadingFinished()
  964. {
  965. mLoaded++;
  966. if ( mLoaded == 4 ) {
  967. mLoaded = 0;
  968. emit resourceLoaded( this );
  969. }
  970. }
  971. #include "kcal_resourcexmlrpc.moc"