kpilot

knotes-action.cc

Go to the documentation of this file.
00001 /* KPilot
00002 **
00003 ** Copyright (C) 2001 by Dan Pilone
00004 ** Copyright (C) 2002,2003,2004 by Adriaan de Groot
00005 **
00006 ** This file defines the SyncAction for the knotes-conduit plugin.
00007 */
00008 
00009 /*
00010 ** This program is free software; you can redistribute it and/or modify
00011 ** it under the terms of the GNU General Public License as published by
00012 ** the Free Software Foundation; either version 2 of the License, or
00013 ** (at your option) any later version.
00014 **
00015 ** This program is distributed in the hope that it will be useful,
00016 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00018 ** GNU General Public License for more details.
00019 **
00020 ** You should have received a copy of the GNU General Public License
00021 ** along with this program in a file called COPYING; if not, write to
00022 ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00023 ** MA 02110-1301, USA.
00024 */
00025 
00026 /*
00027 ** Bug reports and questions can be sent to kde-pim@kde.org
00028 */
00029 
00030 #include "options.h"
00031 
00032 #include <qmap.h>
00033 #include <qtimer.h>
00034 
00035 #include <kapplication.h>
00036 
00037 #include <kurl.h>
00038 #include <libkcal/calendarlocal.h>
00039 #include <kstandarddirs.h>
00040 
00041 
00042 #include <kconfig.h>
00043 //#include <dcopclient.h>
00044 
00045 #include <time.h>  // required by pilot-link includes
00046 
00047 #include <pi-memo.h>
00048 
00049 #include "pilotMemo.h"
00050 #include "pilotSerialDatabase.h"
00051 
00052 //#include "KNotesIface_stub.h"
00053 
00054 #include "knotes-factory.h"
00055 
00056 #include "knotes-action.moc"
00057 #include "knotesconduitSettings.h"
00058 
00059 extern "C"
00060 {
00061 
00062 unsigned long version_conduit_knotes = Pilot::PLUGIN_API;
00063 
00064 }
00065 
00066 typedef QString KNoteID_t;
00067 typedef const QString &KNoteID_pt;
00068 
00069 class NoteAndMemo
00070 {
00071 public:
00072     NoteAndMemo() : noteId(),memoId(-1) { } ;
00073     NoteAndMemo(KNoteID_pt noteid,int memoid) : noteId(noteid),memoId(memoid) { } ;
00074     bool operator ==(const NoteAndMemo &p) const
00075     {
00076         return (p.memo()==memoId) && (p.note()==noteId);
00077     }
00078 
00079     int memo() const { return memoId; } ;
00080     KNoteID_t note() const { return noteId; } ;
00081     inline bool valid() const { return (memoId>0) && (!noteId.isEmpty()) ; } ;
00082     QString toString() const { return CSL1("<%1,%2>").arg(noteId).arg(memoId); } ;
00083 
00084     static NoteAndMemo findNote(const QValueList<NoteAndMemo> &,KNoteID_pt note);
00085     static NoteAndMemo findMemo(const QValueList<NoteAndMemo> &,int memo);
00086 
00087 protected:
00088     KNoteID_t noteId;
00089     int memoId;
00090 } ;
00091 
00092 NoteAndMemo NoteAndMemo::findNote(const QValueList<NoteAndMemo> &l ,KNoteID_pt note)
00093 {
00094     FUNCTIONSETUP;
00095 
00096     for (QValueList<NoteAndMemo>::ConstIterator it = l.begin();
00097         it != l.end();
00098         ++it)
00099     {
00100         if ((*it).note()==note) return *it;
00101     }
00102 
00103     return NoteAndMemo();
00104 }
00105 
00106 NoteAndMemo NoteAndMemo::findMemo(const QValueList<NoteAndMemo> &l , int memo)
00107 {
00108     FUNCTIONSETUP;
00109 
00110     for (QValueList<NoteAndMemo>::ConstIterator it =l.begin();
00111         it != l.end();
00112         ++it)
00113     {
00114         if ((*it).memo()==memo) return *it;
00115     }
00116 
00117     return NoteAndMemo();
00118 }
00119 
00120 class KNotesAction::KNotesActionPrivate
00121 {
00122 public:
00123     KNotesActionPrivate() :
00124         fNotesResource(0L),
00125         fTimer(0L),
00126         fDeleteCounter(0),
00127         fModifiedNotesCounter(0),
00128         fModifiedMemosCounter(0),
00129         fAddedNotesCounter(0),
00130         fAddedMemosCounter(0),
00131         fDeletedNotesCounter(0),
00132         fDeletedMemosCounter(0),
00133         fDeleteNoteForMemo(false)
00134     { } ;
00135     ~KNotesActionPrivate()
00136     {
00137         fNotesResource->save();
00138     
00139         KPILOT_DELETE(fNotesResource);
00140         KPILOT_DELETE(fTimer);
00141     }
00142 
00143     // The record index we're dealing with. Used by
00144     // CopyHHToPC sync only.
00145     int fRecordIndex;
00146 
00147     KCal::CalendarLocal *fNotesResource;
00148     // This is the collection of  notes held by KNotes and
00149     KCal::Journal::List fNotes;
00150     
00151     // This iterates through that list; it's in here because
00152     // we use slots to process one item at a time and need
00153     // to keep track of where we are between slot calls.
00154     KCal::Journal::List::ConstIterator fIndex;
00155     
00156     // The DCOP client for this application, and the KNotes stub.
00157     // DCOPClient *fDCOP;
00158     //KNotesIface_stub *fKNotes;
00159 
00160     // The timer for invoking process() to do some more work.
00161     QTimer *fTimer;
00162 
00163     // The database we're working with (MemoDB)
00164     // PilotSerialDatabase *fDatabase;
00165     // Some counter that needs to be preserved between calls to
00166     // process(). Typically used to note how much work is done.
00167     int fDeleteCounter; // Count deleted memos as well.
00168     unsigned int fModifiedNotesCounter; // Count modified KNotes.
00169     unsigned int fModifiedMemosCounter;
00170     unsigned int fAddedNotesCounter;
00171     unsigned int fAddedMemosCounter;
00172     unsigned int fDeletedNotesCounter;
00173     unsigned int fDeletedMemosCounter;
00174 
00175     // We need to translate between the ids that KNotes uses and
00176     // Pilot id's, so we make a list of pairs.
00177     //
00178     QValueList<NoteAndMemo> fIdList;
00179 
00180     // Setting to delete a KNote when the corresponding memo
00181     // has been deleted.
00182     bool fDeleteNoteForMemo;
00183 };
00184 
00185 
00186 
00187 KNotesAction::KNotesAction(KPilotLink *o,
00188     const char *n, const QStringList &a) :
00189     ConduitAction(o,n ? n : "knotes-conduit",a),
00190     fP(new KNotesActionPrivate)
00191 {
00192     FUNCTIONSETUP;
00193 
00194 /*
00195     if (fP) fP->fDCOP = KApplication::kApplication()->dcopClient();
00196 
00197     if (fP && !fP->fDCOP)
00198     {
00199         WARNINGKPILOT << "Can't get DCOP client." << endl;
00200     }
00201 */
00202 }
00203 
00204 /* virtual */ KNotesAction::~KNotesAction()
00205 {
00206     FUNCTIONSETUP;
00207 
00208     KPILOT_DELETE(fP);
00209 }
00210 
00211 /* virtual */ bool KNotesAction::exec()
00212 {
00213     FUNCTIONSETUP;
00214     DEBUGKPILOT << fname << ": Starting knotes conduit." << endl;
00215 
00216     if (syncMode().isTest())
00217     {
00218         test();
00219         delayDone();
00220         return true;
00221     }
00222 
00223     QString e;
00224     if (!openKNotesResource()) return false;
00225 
00226     // Database names seem to be latin1
00227     if (!openDatabases(CSL1("MemoDB")))
00228     {
00229 #ifdef DEBUG
00230         DEBUGKPILOT << fname << "Can not open databases." << endl;
00231 #endif
00232         emit logError(i18n("Could not open MemoDB on the handheld."));
00233         return false;
00234     }
00235 
00236     fP->fTimer = new QTimer(this);
00237     fActionStatus = Init;
00238     
00239     // this is not needed. As it is done in the initstate in process();
00240     // resetIndexes();
00241 
00242     connect(fP->fTimer,SIGNAL(timeout()),SLOT(process()));
00243     fP->fTimer->start(0,false);
00244 
00245     return true;
00246 }
00247 
00248 void KNotesAction::test()
00249 {
00250     if (!openKNotesResource()) return;
00251     listNotes();
00252 }
00253 
00254 bool KNotesAction::openKNotesResource()
00255 {
00256     FUNCTIONSETUP;
00257     
00258     KConfig korgcfg( locate( "config", CSL1("korganizerrc") ) );
00259     korgcfg.setGroup( "Time & Date" );
00260     QString tz(korgcfg.readEntry( "TimeZoneId" ) );
00261     
00262     fP->fNotesResource = new KCal::CalendarLocal(tz);
00263     KURL mURL = KGlobal::dirs()->saveLocation( "data", "knotes/" ) + "notes.ics";
00264     
00265     if( fP->fNotesResource->load( mURL.path() ) )
00266     {
00267         fP->fNotes = fP->fNotesResource->journals();
00268         return true;
00269     }
00270     else
00271     {
00272         emit logError( i18n("Could not load the resource at: %1").arg(mURL.path()) );
00273         return false;
00274     }
00275 }
00276 
00277 
00278 void KNotesAction::resetIndexes()
00279 {
00280     FUNCTIONSETUP;
00281 
00282     fP->fRecordIndex = 0;
00283     fP->fIndex = fP->fNotes.begin();
00284 }
00285 
00286 void KNotesAction::listNotes()
00287 {
00288     FUNCTIONSETUP;
00289     
00290     KCal::Journal::List notes = fP->fNotesResource->journals();
00291     DEBUGKPILOT << fname << ": the resource contains " << notes.size()
00292         << " note(s)." << endl;
00293         
00294     KCal::Journal::List::ConstIterator it;
00295     int i = 1;
00296     for ( it = notes.begin(); it != notes.end(); ++it )
00297     {
00298         DEBUGKPILOT << fname << ": note " << i << " has id " << (*it)->uid() 
00299             << endl;
00300         i++;
00301     }
00302 
00303     DEBUGKPILOT << fname << ": "
00304         << "Sync direction: " << syncMode().name() << endl;
00305 }
00306 
00307 /* slot */ void KNotesAction::process()
00308 {
00309     FUNCTIONSETUP;
00310 
00311     DEBUGKPILOT << fname << ": Now in state " << fActionStatus << endl;
00312 
00313     switch(fActionStatus)
00314     {
00315     case Init:
00316         resetIndexes();
00317         getAppInfo();
00318         getConfigInfo();
00319         switch(syncMode().mode())
00320         {
00321         case SyncAction::SyncMode::eBackup:
00322         case SyncAction::SyncMode::eRestore:
00323             // Impossible!
00324             fActionStatus = Done;
00325             break;
00326         case SyncAction::SyncMode::eCopyHHToPC :
00327             listNotes(); // Debugging
00328             fActionStatus = MemosToKNotes;
00329             break;
00330         case SyncAction::SyncMode::eHotSync:
00331         case SyncAction::SyncMode::eFullSync:
00332         case SyncAction::SyncMode::eCopyPCToHH:
00333             fActionStatus = ModifiedNotesToPilot;
00334             break;
00335         }
00336         break;
00337     case ModifiedNotesToPilot:
00338         if (modifyNoteOnPilot())
00339         {
00340             resetIndexes();
00341             fActionStatus = DeleteNotesOnPilot;
00342         }
00343         break;
00344     case DeleteNotesOnPilot:
00345         if (deleteNoteOnPilot())
00346         {
00347             resetIndexes();
00348             fActionStatus = NewNotesToPilot;
00349         }
00350         break;
00351     case NewNotesToPilot :
00352         if (addNewNoteToPilot())
00353         {
00354             resetIndexes();
00355             fDatabase->resetDBIndex();
00356             switch(syncMode().mode())
00357             {
00358             case SyncAction::SyncMode::eBackup:
00359             case SyncAction::SyncMode::eRestore:
00360             case SyncAction::SyncMode::eCopyHHToPC :
00361                 // Impossible!
00362                 fActionStatus = Done;
00363                 break;
00364             case SyncAction::SyncMode::eHotSync:
00365             case SyncAction::SyncMode::eFullSync:
00366                 fActionStatus = MemosToKNotes;
00367                 break;
00368             case SyncAction::SyncMode::eCopyPCToHH:
00369                 fActionStatus = Cleanup;
00370                 break;
00371             }
00372         }
00373         break;
00374     case MemosToKNotes :
00375         if (syncMemoToKNotes())
00376         {
00377             fActionStatus=Cleanup;
00378         }
00379         break;
00380     case Cleanup :
00381         cleanupMemos();
00382         break;
00383     default :
00384         if (fP->fTimer) fP->fTimer->stop();
00385         delayDone();
00386     }
00387 }
00388 
00389 
00390 void KNotesAction::getConfigInfo()
00391 {
00392     FUNCTIONSETUP;
00393 
00394     KNotesConduitSettings::self()->readConfig();
00395 
00396     fP->fDeleteNoteForMemo = KNotesConduitSettings::deleteNoteForMemo();
00397 
00398     QValueList<KNoteID_t> notes;
00399     QValueList<int> memos;
00400 
00401     // Make this match the type of KNoteID_t !
00402     notes=KNotesConduitSettings::noteIds();
00403     memos=KNotesConduitSettings::memoIds();
00404 
00405     if (notes.count() != memos.count())
00406     {
00407         WARNINGKPILOT
00408             << ": Notes and memo id lists don't match ("
00409             << notes.count()
00410             << ","
00411             << memos.count()
00412             << ")"
00413             << endl;
00414         notes.clear();
00415         memos.clear();
00416         setFirstSync( true );
00417     }
00418 
00419     QValueList<KNoteID_t>::ConstIterator iNotes = notes.begin();
00420     QValueList<int>::ConstIterator iMemos = memos.begin();
00421 
00422     while((iNotes != notes.end()) && (iMemos != memos.end()))
00423     {
00424         fP->fIdList.append(NoteAndMemo(*iNotes,*iMemos));
00425         ++iNotes;
00426         ++iMemos;
00427     }
00428 }
00429 
00430 void KNotesAction::getAppInfo()
00431 {
00432     FUNCTIONSETUP;
00433 
00434     resetIndexes();
00435 }
00436 
00437 
00438 bool KNotesAction::modifyNoteOnPilot()
00439 {
00440     FUNCTIONSETUP;
00441     return true;
00442     /*
00443     if (fP->fIndex == fP->fNotes.end())
00444     {
00445         return true;
00446     }
00447     */
00448 
00449     //TODO DCOP_REMOVAL
00450     /*
00451     if (fP->fKNotes->isModified(CSL1("kpilot"),fP->fIndex.key()))
00452     {
00453 #ifdef DEBUG
00454         DEBUGKPILOT << fname
00455             << ": The note #"
00456             << fP->fIndex.key()
00457             << " with name "
00458             << fP->fIndex.data()
00459             << " is modified in KNotes."
00460             << endl;
00461 #endif
00462 
00463         NoteAndMemo nm = NoteAndMemo::findNote(fP->fIdList,
00464             fP->fIndex.key());
00465 
00466         if (nm.valid())
00467         {
00468             QString text,title,body;
00469             title = fP->fIndex.data();
00470             body = fP->fKNotes->text(fP->fIndex.key());
00471             if (body.startsWith(title))
00472             {
00473                 text = body;
00474             }
00475             else
00476             {
00477                 text = title + CSL1("\n") + body;
00478             }
00479 
00480             PilotMemo *a = new PilotMemo(text);
00481             PilotRecord *r = a->pack();
00482             r->setID(nm.memo());
00483 
00484             int newid = fDatabase->writeRecord(r);
00485             fLocalDatabase->writeRecord(r);
00486 
00487             if (newid != nm.memo())
00488             {
00489                 WARNINGKPILOT
00490                     << ": Memo id changed during write? "
00491                     << "From "
00492                     << nm.memo()
00493                     << " to "
00494                     << newid
00495                     << endl;
00496             }
00497         }
00498         else
00499         {
00500             WARNINGKPILOT << "Modified note unknown to Pilot" << endl;
00501             // Add it anyway, with new PilotID.
00502             int newid = addNoteToPilot();
00503             fP->fIdList.remove(nm);
00504             fP->fIdList.append(NoteAndMemo(fP->fIndex.key(),newid));
00505         }
00506 
00507         ++(fP->fModifiedMemosCounter);
00508     }
00509     */
00510 
00511     //++(fP->fIndex);
00512     //return false;
00513 }
00514 
00515 bool KNotesAction::deleteNoteOnPilot()
00516 {
00517     FUNCTIONSETUP;
00518 
00519     /*
00520     QValueList<NoteAndMemo>::Iterator i = fP->fIdList.begin();
00521     while ( i != fP->fIdList.end() )
00522     {
00523         // TODO DCOP_REMOVE
00524         if (fP->fNotes.contains((*i).note()))
00525         {
00526 #ifdef DEBUG
00527             DEBUGKPILOT << fname << ": Note " << (*i).note() << " still exists." << endl;
00528 #endif
00529         }
00530         else
00531         {
00532 #ifdef DEBUG
00533             DEBUGKPILOT << fname << ": Note " << (*i).note() << " is deleted." << endl;
00534 #endif
00535             fDatabase->deleteRecord((*i).memo());
00536             fLocalDatabase->deleteRecord((*i).memo());
00537             i = fP->fIdList.remove(i);
00538             fP->fDeletedMemosCounter++;
00539             continue;
00540         }
00541         ++i;
00542     }
00543     */
00544     return true;
00545 }
00546 
00547 bool KNotesAction::addNewNoteToPilot()
00548 {
00549     FUNCTIONSETUP;
00550 
00551     if (fP->fIndex == fP->fNotes.end())
00552     {
00553         return true;
00554     }
00555 
00556     KCal::Journal *j = (*fP->fIndex);
00557 
00558     if( j->pilotId() == 0 )
00559     {
00560         DEBUGKPILOT << fname << ": Adding note with id " << j->uid() 
00561             << " to pilot." << endl;
00562         
00563         int newid = addNoteToPilot();
00564         
00565         ++(fP->fAddedMemosCounter);
00566     }
00567     //TODO DCOP_REMOVAL
00568     /*
00569     if (fP->fKNotes->isNew(CSL1("kpilot"),fP->fIndex.key()))
00570     {
00571         int newid = addNoteToPilot();
00572         fP->fIdList.append(NoteAndMemo(fP->fIndex.key(),newid));
00573         ++(fP->fAddedMemosCounter);
00574     }
00575     */
00576 
00577     ++(fP->fIndex);
00578     return false;
00579 }
00580 
00581 bool KNotesAction::syncMemoToKNotes()
00582 {
00583     FUNCTIONSETUP;
00584 
00585     PilotRecord *rec = 0L;
00586 
00587     if ( syncMode() == SyncAction::SyncMode::eCopyHHToPC )
00588     {
00589 #ifdef DEBUG
00590         DEBUGKPILOT << fname << ": Read record " << fP->fRecordIndex << endl;
00591 #endif
00592         rec = fDatabase->readRecordByIndex(fP->fRecordIndex);
00593         fP->fRecordIndex++;
00594     }
00595     else
00596     {
00597         rec = fDatabase->readNextModifiedRec();
00598     }
00599 
00600     if (!rec)
00601     {
00602         return true;
00603     }
00604 
00605     PilotMemo *memo = new PilotMemo(rec);
00606     NoteAndMemo m = NoteAndMemo::findMemo(fP->fIdList,memo->id());
00607 
00608 #ifdef DEBUG
00609     DEBUGKPILOT << fname << ": Looking at memo "
00610         << memo->id()
00611         << " which was found "
00612         << m.toString()
00613         << endl;
00614 #endif
00615 
00616     if (memo->isDeleted())
00617     {
00618 #ifdef DEBUG
00619         DEBUGKPILOT << fname << ": It's been deleted." << endl;
00620 #endif
00621         if (m.valid())
00622         {
00623             // We knew about the note already, but it
00624             // has changed on the Pilot.
00625             //
00626             //
00627             if (fP->fDeleteNoteForMemo)
00628             {
00629         //TODO DCOP_REMOVAL
00630     //fP->fKNotes->killNote(m.note(),KNotesConduitSettings::suppressKNotesConfirm()
00631     //) ;
00632                 fP->fDeletedNotesCounter++;
00633             }
00634         }
00635         else
00636         {
00637 #ifdef DEBUG
00638         DEBUGKPILOT << fname << ": It's new and deleted." << endl;
00639 #endif
00640         }
00641 
00642         fLocalDatabase->deleteRecord(rec->id());
00643     }
00644     else
00645     {
00646         if (m.valid())
00647         {
00648     #ifdef DEBUG
00649             DEBUGKPILOT << fname << ": It's just modified." << endl;
00650             DEBUGKPILOT << fname << ": <"
00651 //              << fP->fNotes[m.note()]
00652                 << "> <"
00653                 << memo->shortTitle()
00654                 << ">"
00655                 << endl;
00656     #endif
00657             // Check if KNotes still knows about this note
00658             //TODO DCOP_REMOVAL
00659             /*
00660             if (!(fP->fKNotes->name(m.note()).isEmpty()))
00661             {
00662                 updateNote(m,memo);
00663             }
00664             else
00665             {
00666                 uint c = fP->fIdList.remove(m);
00667                 if (!c)
00668                 {
00669                     WARNINGKPILOT
00670                         << "Tried to remove valid note and failed."
00671                         << endl;
00672                 }
00673                 addMemoToKNotes(memo);
00674             }
00675             */
00676         }
00677         else
00678         {
00679             addMemoToKNotes(memo);
00680         }
00681         fLocalDatabase->writeRecord(rec);
00682     }
00683 
00684     KPILOT_DELETE(memo);
00685     KPILOT_DELETE(rec);
00686 
00687     return false;
00688 }
00689 
00690 void KNotesAction::updateNote(const NoteAndMemo &m, const PilotMemo *memo)
00691 {
00692     FUNCTIONSETUP;
00693     //TODO DCOP_REMOVAL
00694     if (true/*fP->fNotes[m.note()] != memo->shortTitle()*/)
00695     {
00696         // Name changed. KNotes might complain though.
00697         //TODO DCOP_REMOVAL
00698         //fP->fKNotes->setName(m.note(), memo->shortTitle());
00699     }
00700     //TODO DCOP_REMOVAL
00701     //fP->fKNotes->setText(m.note(),memo->text());
00702     fP->fModifiedNotesCounter++;
00703 }
00704 
00705 void KNotesAction::addMemoToKNotes(const PilotMemo *memo)
00706 {
00707     FUNCTIONSETUP;
00708     // This note is new to KNotes
00709     //TODO DCOP_REMOVAL
00710     //KNoteID_t i = fP->fKNotes->newNote(memo->shortTitle(), memo->text());
00711     //fP->fIdList.append(NoteAndMemo(i,memo->id()));
00712     //fP->fAddedNotesCounter++;
00713 
00714 #ifdef DEBUG
00715     //TODO DCOP_REMOVAL
00716     //DEBUGKPILOT << fname << ": It's new with knote id " << i << endl;
00717 #endif
00718 }
00719 int KNotesAction::addNoteToPilot()
00720 {
00721     FUNCTIONSETUP;
00722     
00723     KCal::Journal *j = (*fP->fIndex);
00724     
00725 #ifdef DEBUG
00726     DEBUGKPILOT << fname
00727         << ": The note #"
00728         << j->uid()
00729         << " with name "
00730         << j->summary()
00731         << " is new to the Pilot."
00732         << endl;
00733 #endif
00734 
00735     QString text = j->summary() + CSL1("\n");
00736     text.append( j->description() );
00737     //TODO DCOP_REMOVAL
00738     //text.append(fP->fKNotes->text(fP->fIndex.key()));
00739 
00740     PilotMemo *a = new PilotMemo(text);
00741     PilotRecord *r = a->pack();
00742 
00743     int newid = fDatabase->writeRecord(r);
00744     fLocalDatabase->writeRecord(r);
00745     
00746     j->setPilotId( newid );
00747 
00748     delete r;
00749     delete a;
00750     delete j;
00751 
00752     fP->fAddedMemosCounter++;
00753 
00754     return newid;
00755 }
00756 
00757 
00758 void KNotesAction::cleanupMemos()
00759 {
00760     FUNCTIONSETUP;
00761 
00762     // Tell KNotes we're up-to-date
00763     //TODO DCOP_REMOVAL
00764     //fP->fKNotes->sync(CSL1("kpilot"));
00765 
00766 #ifdef DEBUG
00767     DEBUGKPILOT << fname
00768         << ": Writing "
00769         << fP->fIdList.count()
00770         << " pairs to the config file."
00771         << endl;
00772     DEBUGKPILOT << fname
00773         << ": The config file is read-only: "
00774         << KNotesConduitSettings::self()->config()->isReadOnly()
00775         << endl;
00776 #endif
00777 
00778     QValueList<KNoteID_t> notes;
00779     QValueList<int> memos;
00780 
00781     for (QValueList<NoteAndMemo>::ConstIterator i =
00782         fP->fIdList.begin();
00783         i!=fP->fIdList.end();
00784         ++i)
00785     {
00786         notes.append((*i).note());
00787         memos.append((*i).memo());
00788     }
00789 
00790     KNotesConduitSettings::setNoteIds(notes);
00791     KNotesConduitSettings::setMemoIds(memos);
00792     KNotesConduitSettings::self()->writeConfig();
00793 
00794     fActionStatus=Done;
00795     fDatabase->cleanup();
00796     fDatabase->resetSyncFlags();
00797     fLocalDatabase->cleanup();
00798     fLocalDatabase->resetSyncFlags();
00799 
00800     // Tell the user what happened. If no changes were
00801     // made, spoke remains false and we'll tack a
00802     // message on to the end saying so, so that
00803     // the user always gets at least one message.
00804     bool spoke = false;
00805     if (fP->fAddedMemosCounter)
00806     {
00807         addSyncLogEntry(i18n("Added one new memo.",
00808             "Added %n new memos.",
00809             fP->fAddedMemosCounter));
00810     }
00811     if (fP->fModifiedMemosCounter)
00812     {
00813         addSyncLogEntry(i18n("Modified one memo.",
00814             "Modified %n memos.",
00815             fP->fModifiedMemosCounter));
00816         spoke = true;
00817     }
00818     if (fP->fDeletedMemosCounter)
00819     {
00820         addSyncLogEntry(i18n("Deleted one memo.",
00821             "Deleted %n memos.",fP->fDeletedMemosCounter));
00822         spoke = true;
00823     }
00824     if (fP->fAddedNotesCounter)
00825     {
00826         addSyncLogEntry(i18n("Added one note to KNotes.",
00827             "Added %n notes to KNotes.",fP->fAddedNotesCounter));
00828         spoke = true;
00829     }
00830     if (fP->fModifiedNotesCounter)
00831     {
00832         addSyncLogEntry(i18n("Modified one note in KNotes.",
00833             "Modified %n notes in KNotes.",fP->fModifiedNotesCounter));
00834         spoke = true;
00835     }
00836     if (fP->fDeletedNotesCounter)
00837     {
00838         addSyncLogEntry(i18n("Deleted one note from KNotes.",
00839             "Deleted %n notes from KNotes.",fP->fDeletedNotesCounter));
00840         spoke = true;
00841     }
00842     if (!spoke)
00843     {
00844         addSyncLogEntry(i18n("No change to KNotes."));
00845     }
00846 }
00847 
00848 
00849 /* virtual */ QString KNotesAction::statusString() const
00850 {
00851     switch(fActionStatus)
00852     {
00853     case Init : return CSL1("Init");
00854     case NewNotesToPilot :
00855         return CSL1("NewNotesToPilot key=%1");
00856             // TODO DCOP_REMOVAL .arg(fP->fIndex.key());
00857     case ModifiedNotesToPilot :
00858         return CSL1("ModifiedNotesToPilot key=%1");
00859             //TODO DCOP_REMOVAL .arg(fP->fIndex.key());
00860     case MemosToKNotes :
00861         return CSL1("MemosToKNotes rec=%1")
00862             .arg(fP->fRecordIndex);
00863     case Cleanup : return CSL1("Cleanup");
00864     case Done :
00865         return CSL1("Done");
00866     default :
00867         return CSL1("Unknown (%1)").arg(fActionStatus);
00868     }
00869 }
00870 
00871 
00872