kpilot Library API Documentation

DOC-converter.cc

00001 /* DOC-converter.cc                           KPilot
00002 **
00003 ** Copyright (C) 2002-2003 by Reinhold Kainhofer
00004 **
00005 ** The doc converter synchronizes text files on the PC with DOC databases on the Palm
00006 */
00007 
00008 /*
00009 ** This program is free software; you can redistribute it and/or modify
00010 ** it under the terms of the GNU General Public License as published by
00011 ** the Free Software Foundation; either version 2 of the License, or
00012 ** (at your option) any later version.
00013 **
00014 ** This program is distributed in the hope that it will be useful,
00015 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00017 ** GNU General Public License for more details.
00018 **
00019 ** You should have received a copy of the GNU General Public License
00020 ** along with this program in a file called COPYING; if not, write to
00021 ** the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00022 ** MA 02111-1307, USA.
00023 */
00024  
00025 /*
00026 ** Bug reports and questions can be sent to kde-pim@kde.org
00027 */
00028 
00029 
00030 #include "options.h"
00031 #include "DOC-converter.moc"
00032 
00033 #include <qdir.h>
00034 #include <qfileinfo.h>
00035 #include <qregexp.h>
00036 #include <qsortedlist.h>
00037 
00038 #include <pilotDatabase.h>
00039 #include <pilotLocalDatabase.h>
00040 #include <pilotSerialDatabase.h>
00041 
00042 #include "pilotDOCHead.h"
00043 #include "pilotDOCEntry.h"
00044 #include "pilotDOCBookmark.h"
00045 
00046 
00047 
00048 // Something to allow us to check what revision
00049 // the modules are that make up a binary distribution.
00050 const char *doc_converter_id = "$Id: DOC-converter.cc,v 1.13 2003/08/12 18:11:51 mueller Exp $";
00051 
00052 #define min(a,b) (a<b)?(a):(b)
00053 
00054 
00055 
00056 /****************************************************************************************************
00057  *  various bookmark classes. Most important is the bmkList  findMatches(QString) function,
00058  *  which needs to return a list of all bookmarks found for the given bookmark expression.
00059  *  A bookmark usually consists of a bookmark text and an offset into the text document.
00060  ****************************************************************************************************/
00061 
00062 
00063 bool docBookmark::compare_pos=true;
00064 
00065 bool operator< ( const docBookmark &s1, const docBookmark &s2)
00066 {
00067     if (docBookmark::compare_pos) { return s1.position<s2.position;}
00068     else {return s2.bmkName<s2.bmkName;}
00069 }
00070 
00071 bool operator== ( const docBookmark &s1, const docBookmark &s2)
00072 {
00073     return (s1.position==s2.position) && (s1.bmkName==s2.bmkName);
00074 }
00075 
00076 
00077 int docMatchBookmark::findMatches(QString doctext, bmkList &fBookmarks) {
00078     FUNCTIONSETUP;
00079 //  bmkList res;
00080     int pos = 0, nr=0, found=0;
00081     DEBUGCONDUIT<<"Finding matches of "<<pattern<<endl;
00082 
00083     while (pos >= 0 && found<to) {
00084         pos = doctext.find(pattern, pos);
00085         DEBUGCONDUIT<<"Result of search: pos="<<pos<<endl;
00086         if (pos >= 0)
00087         {
00088             found++;
00089             if (found>=from && found<=to) {
00090                 fBookmarks.append(new docBookmark(pattern, pos));
00091                 nr++;
00092                 
00093             }
00094             pos++;
00095         }
00096     }
00097     return nr;
00098 }
00099 
00100 
00101 
00102 int docRegExpBookmark::findMatches(QString doctext, bmkList &fBookmarks) {
00103 //  bmkList res;
00104     QRegExp rx(pattern);
00105     int pos = 0, nr=0, found=0;
00106 
00107     while (pos>=0 && found<=to) {
00108         DEBUGCONDUIT<<"Searching for bookmark "<<pattern<<endl;
00109         pos=rx.search(doctext, pos);
00110         if (pos > -1) {
00111             found++;
00112             if (found>=from && found<to) {
00113                 if (capSubexpression>=0) {
00114                     fBookmarks.append(new docBookmark(/*bmkName.left(16)*/rx.cap(capSubexpression), pos));
00115                 } else {
00116                     // TODO: use the subexpressions from the regexp for the bmk name ($1..$9) (given as separate regexp)
00117                     QString bmkText(bmkName);
00118                     for (int i=0; i<=rx.numCaptures(); i++) {
00119                         bmkText.replace(QString("$%1").arg(i), rx.cap(i));
00120                         bmkText.replace(QString("\\%1").arg(i), rx.cap(i));
00121                     }
00122                     fBookmarks.append(new docBookmark(bmkText.left(16), pos));
00123                 }
00124                 nr++;
00125             }
00126             pos++;
00127         }
00128     }
00129     return nr;
00130 }
00131 
00132 
00133 
00134 
00135 
00136 
00137 
00138 
00139 /*********************************************************************
00140                         C O N S T R U C T O R
00141  *********************************************************************/
00142 
00143 
00144 DOCConverter::DOCConverter(QObject *parent, const char *name):QObject(parent,name) {
00145     FUNCTIONSETUP;
00146     docdb=0L;
00147     eSortBookmarks=eSortNone;
00148     fBookmarks.setAutoDelete( TRUE );
00149     (void) doc_converter_id;
00150 }
00151 
00152 
00153 
00154 DOCConverter::~DOCConverter() {
00155     FUNCTIONSETUP;
00156 }
00157 
00158 
00159 
00160 
00161 
00162 /*********************************************************************
00163                 S Y N C   S T R U C T U R E
00164  *********************************************************************/
00165 
00166 
00167 
00168 void DOCConverter::setTXTpath(QString path, QString file) {
00169     QDir dr(path);
00170     QFileInfo pth(dr, file);
00171     if (!file.isEmpty())
00172          txtfilename = pth.absFilePath();
00173 }
00174 
00175 
00176 
00177 void DOCConverter::setTXTpath(QString filename) {
00178     if (!filename.isEmpty()) txtfilename = filename;
00179 }
00180 
00181 
00182 
00183 void DOCConverter::setPDB(PilotDatabase * dbi) {
00184     if (dbi) docdb = dbi;
00185 }
00186 
00187  
00188 
00189 QString DOCConverter::readText() {
00190     FUNCTIONSETUP;
00191     if (txtfilename.isEmpty()) return QString();
00192     QFile docfile(txtfilename);
00193     if (!docfile.open(IO_ReadOnly))
00194     {
00195         emit logError(i18n("Unable to open text file %1 for reading.").arg(txtfilename));
00196         return QString();
00197     }
00198 
00199     QTextStream docstream(&docfile);
00200 
00201     QString doc = docstream.read();
00202     docfile.close();
00203     return doc;
00204 }
00205 
00206 
00207 
00208 int DOCConverter::findBmkEndtags(QString &text, bmkList&fBmks) {
00209     FUNCTIONSETUP;
00210     // Start from the end of the text
00211     int pos = text.length() - 1, nr=0;
00212     bool doSearch=true;
00213     while (pos >= 0/* && doSearch*/) {
00214         DEBUGCONDUIT<<"Current character is \'"<<text[pos].latin1()<<"\'"<<endl;
00215         // skip whitespace until we reach a >
00216         while (text[pos].isSpace() && pos >= 0) {
00217             DEBUGCONDUIT<<"Skipping whitespaces at the end of the file"<<endl;
00218             pos--;
00219         }
00220         // every other character than a > is assumed to belong to the text, so there are no more bookmarks.
00221         if (pos < 0 || text[pos] != '>') {
00222             DEBUGCONDUIT<<"Current character \'"<<text[pos].latin1()<<"\' at position "<<pos<<" is not and ending >. Finish searching for bookmarks."<<endl;
00223         
00224             pos=-1;
00225             break;
00226         } else {
00227             int endpos = pos;
00228             doSearch=true;
00229             DEBUGCONDUIT<<"Found the ending >, now looking for the opening <"<<endl;
00230             
00231             // Search for the opening <. There must not be a newline in the bookmark text.
00232             while (doSearch && pos > 0) {
00233 //              DEBUGCONDUIT<<"pos="<<pos<<", char="<<text[pos].latin1()<<endl;
00234                 pos--;
00235                 if (text[pos] == '\n') {
00236                     DEBUGCONDUIT<<"Found carriage return at position "<<pos<<" inside the bookmark text, assuming this is not a bookmark, and the text ends in a >"<<endl;
00237                     doSearch = false;
00238                     pos = -1;
00239                     break;
00240                 }
00241                 if (text[pos] == '<') {
00242                     fBmks.append(new docMatchBookmark(text.mid(pos + 1, endpos - pos - 1)));
00243                     nr++;
00244                     DEBUGCONDUIT<<"Found opening < at position "<<pos<<", bookmarktext ="<<text.mid(pos+1, endpos-pos-1)<<endl;
00245                     text.remove(pos, text.length());
00246                     pos--;
00247                     doSearch = false;
00248                 }
00249             }
00250         }
00251         DEBUGCONDUIT<<"Finished processing the next bookmark, current position: "<<pos<<endl;
00252     }
00253     return nr;
00254 }
00255         
00256 int DOCConverter::findBmkInline(QString &text, bmkList &fBmks) {
00257     FUNCTIONSETUP;
00258 //  bmkList res;
00259     int nr=0;
00260     QRegExp rx(CSL1("<\\*(.*)\\*>"));
00261 
00262     rx.setMinimal(TRUE);
00263     int pos = 0;
00264     while (pos >= 0) {
00265         pos = rx.search(text, pos);
00266         if (pos >= 0) {
00267             fBmks.append(new docBookmark(rx.cap(1), pos+1));
00268             nr++;
00269             text = text.remove(pos, rx.matchedLength());
00270         }
00271     }
00272     return nr;
00273 }
00274 
00275 int DOCConverter::findBmkFile(QString &, bmkList &fBmks) {
00276     FUNCTIONSETUP;
00277     int nr=0;
00278     
00279     QString bmkfilename = txtfilename;
00280     if (bmkfilename.endsWith(CSL1(".txt"))){
00281         bmkfilename.remove(bmkfilename.length()-4, 4);
00282     }
00283     QString oldbmkfilename=bmkfilename;
00284     bmkfilename+=CSL1(BMK_SUFFIX);
00285     QFile bmkfile(bmkfilename);
00286     if (!bmkfile.open(IO_ReadOnly))     {
00287         bmkfilename=oldbmkfilename+CSL1(PDBBMK_SUFFIX);
00288         bmkfile.setName(bmkfilename);
00289         if (!bmkfile.open(IO_ReadOnly)) {
00290             DEBUGCONDUIT<<"Unable to open bookmarks file "<<bmkfilename<<" for reading the bookmarks of "<<docdb ->dbPathName()<<endl;
00291             return 0;
00292         }
00293     }
00294     
00295     DEBUGCONDUIT<<"Bookmark file: "<<bmkfilename<<endl;
00296 
00297     QTextStream bmkstream(&bmkfile);
00298     QString line;
00299     while ( !(line=bmkstream.readLine()).isEmpty() ) {
00300         if (!line.isEmpty() && !line.startsWith(CSL1("#")) ) {
00301             QStringList bmkinfo=QStringList::split(CSL1(","), line);
00302             int fieldnr=bmkinfo.count();
00303             // We use the same syntax for the entries as MakeDocJ bookmark files:
00304             //   <bookmark>,<string-to-search>,<bookmark-name-string>,<starting-bookmark>,<ending-bookmark>
00305             // For an explanation see: http://home.kc.rr.com/krzysztow/PalmPilot/MakeDocJ/index.html
00306             if (fieldnr>0){
00307                 DEBUGCONDUIT<<"Working on bookmark \""<<line<<"\""<<endl;
00308                 docMatchBookmark*bmk=0L;
00309                 QString bookmark=bmkinfo[0];
00310                 bool ok;
00311                 int pos=bookmark.toInt(&ok);
00312                 if (ok) {
00313                     if (fieldnr>1) {
00314                         QString name(bmkinfo[1]);
00315                         DEBUGCONDUIT<<"Bookmark \""<<name<<"\" set at position "<<pos<<endl;
00316                         fBmks.append(new docBookmark(name, pos));
00317                     }
00318                 } else if (bookmark==CSL1("-") || bookmark==CSL1("+")) {
00319                     if (fieldnr>1) {
00320                         QString patt(bmkinfo[1]);
00321                         QString name(patt);
00322                         if (fieldnr>2) {
00323                             int cap=bmkinfo[2].toInt(&ok);
00324                             if (ok) {
00325                                 bmk=new docRegExpBookmark(patt, cap);
00326                             } else {
00327                                 name=bmkinfo[2];
00328                                 bmk=new docRegExpBookmark(patt, name);
00329                             }
00330                         } else{
00331                             bmk=new docRegExpBookmark(patt, name);
00332                         }
00333                         // The third entry in the line (optional) denotes the index of a capture subexpression (if an integer) or the bookmark text as regexp (if a string)
00334                         DEBUGCONDUIT<<"RegExp Bookmark, pattern="<<patt<<", name="<<name<<endl;
00335                         if (bmk) {
00336                             if (bookmark==CSL1("-")) {
00337                                 bmk->from=1;
00338                                 bmk->to=1;
00339                             } else {
00340                                 if (fieldnr>3) {
00341                                     bool ok;
00342                                     int tmp=bmkinfo[3].toInt(&ok);
00343                                     if (ok) bmk->from=tmp;
00344                                     if (fieldnr>4) {
00345                                         tmp=bmkinfo[4].toInt(&ok);
00346                                         if (ok) bmk->to=tmp;
00347                                     }
00348                                 }
00349                             }
00350                             fBmks.append(bmk);
00351                             bmk=0L;
00352                         } else {
00353                             DEBUGCONDUIT<<"Could not allocate bookmark "<<name<<endl;
00354                         }
00355                     } else {
00356                         DEBUGCONDUIT<<"RegExp bookmark found with no other information (no bookmark pattern nor name)"<<endl;
00357                     }
00358                 } else {
00359                     QString pattern(bookmark);
00360                     if (fieldnr>1) pattern=bmkinfo[1];
00361                     if (fieldnr>2) bookmark=bmkinfo[2];
00362                     DEBUGCONDUIT<<"RegExp Bookmark, pattern="<<pattern<<", name="<<bookmark<<endl;
00363                     bmk=new docRegExpBookmark(pattern, bookmark);
00364                     if (bmk) {
00365                         bmk->from=1;
00366                         bmk->to=1;
00367                         fBmks.append(bmk);
00368                     }
00369                 }
00370             } // fieldnr>0
00371         } // !line.isEmpty()
00372     } // while
00373     return nr;
00374 }
00375 
00376 bool DOCConverter::convertTXTtoPDB() {
00377     FUNCTIONSETUP;
00378     
00379     if (!docdb) {
00380         emit logError(i18n("Unable to open Database for writing"));
00381         return false;
00382     }
00383     
00384     QString text = readText();
00385 
00386     if (fBmkTypes & eBmkEndtags) {
00387         findBmkEndtags(text, fBookmarks);
00388     }   // end: EndTag Bookmarks
00389 
00390 
00391     // Search for all tags <* Bookmark text *> in the text. We have to delete them immediately, otherwise the later bookmarks will be off.
00392     if (fBmkTypes & eBmkInline) {
00393         findBmkInline(text, fBookmarks);
00394     }    // end: Inline Bookmarks
00395 
00396 
00397     // Read in regular expressions and positions from an external file (doc-filename with extension .bmk)
00398     if (fBmkTypes & eBmkFile)
00399     {
00400         findBmkFile(text, fBookmarks);
00401     }
00402 
00403     // Process the bookmarks: find the occurrences of the regexps, and sort them if requested:
00404     bmkSortedList pdbBookmarks;
00405     pdbBookmarks.setAutoDelete(TRUE);
00406     docBookmark*bmk;
00407     for (bmk = fBookmarks.first(); bmk; bmk = fBookmarks.next())
00408     {
00409         bmk->findMatches(text, pdbBookmarks);
00410     }
00411 
00412     switch (eSortBookmarks)
00413     {
00414         case eSortName:
00415             docBookmark::compare_pos=false;
00416 //          qHeapSort(pdbBookmarks);
00417             pdbBookmarks.sort();
00418             break;
00419         case eSortPos:
00420             docBookmark::compare_pos=true;
00421             pdbBookmarks.sort();
00422             break;
00423         case eSortNone:
00424         default:
00425             break;
00426     }
00427 
00428 #ifdef DEBUG
00429     DEBUGCONDUIT << "Bookmarks: "<<endl;
00430     for (bmk = pdbBookmarks.first(); bmk; bmk = pdbBookmarks.next())
00431     {
00432         DEBUGCONDUIT<<bmk->bmkName.left(20)<<" at position "<<bmk->position<<endl;
00433     }
00434 #endif
00435     
00436     if (!docdb->isDBOpen()) {
00437         emit logError(i18n("Unable to open palm doc database %1").arg(docdb->dbPathName()) );
00438         return false;
00439     }
00440     
00441     // Clean the whole database, otherwise the records would be just appended!
00442     docdb->deleteRecord(0, true);
00443 
00444     // Header record for the doc file format
00445     PilotDOCHead docHead;
00446     docHead.position=0;
00447     docHead.recordSize=4096;
00448     docHead.spare=0;
00449     docHead.storyLen=text.length();
00450     docHead.version=compress?DOC_COMPRESSED:DOC_UNCOMPRESSED;
00451     docHead.numRecords=(int)( (text.length()-1)/docHead.recordSize)+1;
00452     PilotRecord*rec=docHead.pack();
00453     docdb->writeRecord(rec);
00454     KPILOT_DELETE(rec);
00455     
00456     DEBUGCONDUIT << "Write header record: length="<<text.length()<<", compress="<<compress<<endl;
00457 
00458     // First compress the text, then write out the bookmarks and - if existing - also the annotations
00459     int len=text.length();
00460     int start=0,reclen=0;
00461     int recnum=0;
00462     while (start<len)
00463     {
00464         reclen=min(len-start, PilotDOCEntry::TEXT_SIZE);
00465         DEBUGCONDUIT << "Record #"<<recnum<<", reclen="<<reclen<<", compress="<<compress<<endl;
00466         
00467         PilotDOCEntry recText;
00468 //      recText.setText(text.mid(start, reclen), reclen);
00469         recText.setText(text.mid(start, reclen));
00470 //      if (compress) 
00471         recText.setCompress(compress);
00472         PilotRecord*textRec=recText.pack();
00473         docdb->writeRecord(textRec);
00474         recnum++;
00475         start+=reclen;
00476         KPILOT_DELETE(textRec);
00477     }
00478     
00479     recnum=0;
00480     // Finally, write out the bookmarks
00481     for (bmk = pdbBookmarks.first(); bmk; bmk = pdbBookmarks.next())
00482 //  for (bmkList::const_iterator it=pdbBookmarks.begin(); it!=pdbBookmarks.end(); it++)
00483     {
00484         recnum++;
00485         DEBUGCONDUIT << "Bookmark #"<<recnum<<", Name="<<bmk->bmkName.left(20)<<", Position="<<bmk->position<<endl;
00486         
00487         PilotDOCBookmark bmkEntry;
00488         bmkEntry.pos=bmk->position;
00489         strncpy(&bmkEntry.bookmarkName[0], bmk->bmkName.latin1(), 16);
00490         PilotRecord*bmkRecord=bmkEntry.pack();
00491         docdb->writeRecord(bmkRecord);
00492         KPILOT_DELETE(bmkRecord);
00493     }
00494 
00495     pdbBookmarks.clear();
00496     fBookmarks.clear();
00497 
00498     return true;
00499 }
00500 
00501 
00502 
00503 bool DOCConverter::convertPDBtoTXT()
00504 {
00505     FUNCTIONSETUP;
00506     if (txtfilename.isEmpty()) {
00507         emit logError(i18n("No filename set for the conversion"));
00508         return false;
00509     }
00510     
00511     if (!docdb) {
00512         emit logError(i18n("Unable to open Database for reading"));
00513         return false;
00514     }
00515 
00516     // The first record of the db is the document header containing information about the doc db
00517     PilotRecord*headerRec = docdb->readRecordByIndex(0);
00518     if (!headerRec)
00519     {
00520         emit logError(i18n("Unable to read database header for database %1.").arg(docdb->dbPathName()));
00521         KPILOT_DELETE(docdb);
00522         return false;
00523     }
00524     PilotDOCHead header(headerRec);
00525     KPILOT_DELETE(headerRec);
00526     
00527     DEBUGCONDUIT<<"Database "<<docdb->dbPathName()<<" has "<<header.numRecords<<" text records, "<<endl
00528         <<" total number of records: "<<docdb->recordCount()<<endl
00529         <<" position="<<header.position<<endl
00530         <<" recordSize="<<header.recordSize<<endl
00531         <<" spare="<<header.spare<<endl
00532         <<" storyLen="<<header.storyLen<<endl
00533 //      <<" textRecordSize="<<header.textRecordSize<<endl
00534         <<" version="<<header.version<<endl;
00535 
00536     // next come the header.numRecords real document records (might be compressed, see the version flag in the header)
00537     QFile docfile(txtfilename);
00538     if (!docfile.open(IO_WriteOnly))
00539     {
00540         emit logError(i18n("Unable to open output file %1.").arg(txtfilename));
00541         KPILOT_DELETE(docdb);
00542         return false;
00543     }
00544     QString doctext;
00545     for (int i=1; i<header.numRecords+1; i++)
00546     {
00547         PilotRecord*rec=docdb->readRecordByIndex(i);
00548         if (rec)
00549         {
00550             PilotDOCEntry recText(rec, header.version==DOC_COMPRESSED);
00551             doctext.append(recText.getText());
00552             DEBUGCONDUIT<<"Record "<<i<<endl;
00553             KPILOT_DELETE(rec);
00554         } else {
00555             emit logMessage(i18n("Could not read text record #%1 from Database %2").arg(i).arg(docdb->dbPathName()));
00556         }
00557     }
00558 
00559     // After the document records possibly come a few bookmark records, so read them in and put them in a separate bookmark file.
00560     // for the ztxt conduit there might be annotations after the bookmarks, so the upper bound needs to be adapted.
00561     int upperBmkRec=docdb->recordCount();
00562     bmkSortedList bmks;
00563     bmks.setAutoDelete(TRUE);
00564     for (int i=header.numRecords+1; i<upperBmkRec; i++)
00565     {
00566         PilotRecord*rec=docdb->readRecordByIndex(i);
00567         if (rec)
00568         {
00569             PilotDOCBookmark bookie(rec);
00570             docBookmark*bmk=new docBookmark(bookie.bookmarkName, bookie.pos);
00571             bmks.append(bmk);
00572             KPILOT_DELETE(rec);
00573         } else {
00574             emit logMessage(i18n("Could not read bookmark record #%1 from Database %2").arg(i).arg(docdb->dbPathName()));
00575         }
00576     }
00577     // TODO: Sort the list of bookmarks according to their position
00578     docBookmark::compare_pos=true;
00579     bmks.sort();
00580 
00581     if ((fBmkTypes & eBmkFile) && (bmks.count()>0))
00582     {
00583         QString bmkfilename = docfile.name();
00584         if (bmkfilename.endsWith(CSL1(".txt"))){
00585             bmkfilename.remove(bmkfilename.length()-4, 4);
00586         }
00587         bmkfilename+=CSL1(PDBBMK_SUFFIX);
00588         QFile bmkfile(bmkfilename);
00589         if (!bmkfile.open(IO_WriteOnly))
00590         {
00591             emit logError(i18n("Unable to open file %1 for the bookmarks of %2.")
00592                 .arg(bmkfilename).arg(docdb ->dbPathName()));
00593         }
00594         else
00595         {
00596             DEBUGCONDUIT<<"Writing "<<upperBmkRec-header.numRecords<<
00597                 "("<<upperBmkRec<<") bookmarks to file "<<bmkfilename<<endl;
00598             QTextStream bmkstream(&bmkfile);
00599             for (docBookmark*bmk=bmks.first(); bmk; bmk=bmks.next())
00600             {
00601                 bmkstream<<bmk->position<<", "<<bmk->bmkName<<endl;
00602             }
00603             //bmkstream.close();
00604             bmkfile.close();
00605         }
00606     }
00607     if (fBmkTypes & eBmkInline)
00608     {
00609         for (docBookmark*bmk=bmks.last(); bmk; bmk=bmks.prev())
00610         {
00611             doctext.insert(bmk->position, QString(CSL1("<*") +
00612                 bmk->bmkName +
00613                 CSL1("*>")));
00614         }
00615     }
00616 
00617     // Finally, write the actual text out to the file.
00618     QTextStream docstream(&docfile);
00619     docstream<<doctext;
00620     //docstream.close();
00621     docfile.close();
00622     docdb->cleanup();
00623     // reset all records to unchanged. I don't know if this is really such a wise idea?
00624     docdb->resetSyncFlags();
00625     return true;
00626 }
00627 
00628 
KDE Logo
This file is part of the documentation for kpilot Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat May 1 11:36:47 2004 by doxygen 1.2.15 written by Dimitri van Heesch, © 1997-2003