kpilot Library API Documentation

memoWidget.cc

00001 /* memoWidget.cc                        KPilot
00002 **
00003 ** Copyright (C) 1998-2001 by Dan Pilone
00004 **
00005 ** This is the memo-viewing widget (internal conduit) used by KPilot.
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 static const char *memowidget_id =
00029         "$Id: memoWidget.cc,v 1.49.2.12 2003/03/20 21:08:27 adridg Exp $";
00030 
00031 #include "options.h"
00032 
00033 #include <time.h>
00034 
00035 #include <pi-macros.h>
00036 #include <pi-dlp.h>
00037 
00038 #include <qdir.h>
00039 #include <qptrlist.h>
00040 #include <qlistbox.h>
00041 #include <qfile.h>
00042 #include <qpushbutton.h>
00043 #include <qlayout.h>
00044 #include <qdom.h>
00045 #include <qtextstream.h>
00046 #include <qwhatsthis.h>
00047 #include <qlabel.h>
00048 #include <qtextcodec.h>
00049 
00050 #include <kapplication.h>
00051 #include <kmessagebox.h>
00052 #include <kfiledialog.h>
00053 
00054 #include "kpilot.h"
00055 #include "kpilotConfig.h"
00056 #include "listItems.h"
00057 #include "pilotLocalDatabase.h"
00058 #include "pilotMemo.h"
00059 
00060 #include "memoWidget.moc"
00061 
00062 
00063 // This constant (0xffff) appears all over the place (mostly in
00064 // ::initialize(), but elsewhere as well. It seems to be inherited
00065 // from the pilot-link library.
00066 //
00067 // I've replaced instances of the constant with this #define
00068 //
00069 //
00070 #define PILOT_BUFFER_SIZE       (0xffff)
00071 
00072 
00073 
00074 MemoWidget::MemoWidget(QWidget * parent,
00075         const QString & path) :
00076         PilotComponent(parent, "component_memo", path),
00077         fTextWidget(0L),
00078         lastSelectedMemo(-1)
00079 {
00080         FUNCTIONSETUP;
00081 
00082         setGeometry(0, 0,
00083                 parent->geometry().width(), parent->geometry().height());
00084         setupWidget();
00085         fMemoList.setAutoDelete(true);
00086         slotUpdateButtons();
00087 
00088 #if 0
00089         connect(fTextWidget, SIGNAL(textChanged()),
00090                 this, SLOT(slotTextChanged()));
00091 #endif
00092 
00093         /* NOTREACHED */
00094         (void) memowidget_id;
00095 }
00096 
00097 MemoWidget::~MemoWidget()
00098 {
00099         FUNCTIONSETUP;
00100         saveChangedMemo();
00101 }
00102 
00103 
00104 // void MemoWidget::initializeMemos(PilotDatabase *memoDB)
00105 //
00106 // Reads all the memos from the local database and places them
00107 // in the selection screen.
00108 //
00109 
00110 void MemoWidget::initializeMemos(PilotDatabase * memoDB)
00111 {
00112         FUNCTIONSETUP;
00113 
00114 
00115         // ShowSecrets tells us to also list memos with an attribute of "Secret"
00116         // or "Private"
00117         //
00118         bool showSecrets = KPilotConfig::getConfig().getShowSecrets();
00119 
00120         fMemoList.clear();
00121 
00122 
00123 
00124 
00125 
00126         int currentRecord = 0;
00127         PilotRecord *pilotRec;
00128         PilotMemo *memo;
00129 
00130         while ((pilotRec = memoDB->readRecordByIndex(currentRecord)) != NULL)
00131         {
00132                 if (!pilotRec->isDeleted())
00133                 {
00134                         if ((!pilotRec->isSecret()) || showSecrets)
00135                         {
00136                                 memo = new PilotMemo(pilotRec);
00137                                 fMemoList.append(memo);
00138 
00139 #ifdef DEBUG
00140                                 DEBUGKPILOT << fname <<
00141                                         ": Added memo "
00142                                         << currentRecord << endl;
00143 #endif
00144                         }
00145                         else
00146                         {
00147 #ifdef DEBUG
00148                                 DEBUGKPILOT << fname <<
00149                                         ": Skipped secret record " <<
00150                                         currentRecord << endl;
00151 #endif
00152                         }
00153                 }
00154                 else
00155                 {
00156 #ifdef DEBUG
00157                         DEBUGKPILOT << fname <<
00158                                 ": Skipped deleted record " <<
00159                                 currentRecord << endl;
00160 #endif
00161                 }
00162 
00163                 delete pilotRec;
00164 
00165                 currentRecord++;
00166         }
00167 }
00168 
00169 
00170 void MemoWidget::initialize()
00171 {
00172         FUNCTIONSETUP;
00173 
00174 
00175         // Get the local database - assume the call may fail and return
00176         // NULL, or the database object may be returned but unopened.
00177         //
00178         //
00179         PilotLocalDatabase *memoDB =
00180                 new PilotLocalDatabase(dbPath(), CSL1("MemoDB"));
00181         if (memoDB == NULL || !memoDB->isDBOpen())
00182         {
00183                 kdWarning() << k_funcinfo <<
00184                         ": Can't open local database MemoDB\n";
00185 
00186                 populateCategories(fCatList, 0L);
00187                 updateWidget();
00188                 return;
00189         }
00190 
00191         // Normal case: there is a database so we can read it
00192         // and determine all the categories.
00193         //
00194         int appLen = memoDB->appInfoSize();
00195 
00196 #ifdef DEBUG
00197         DEBUGKPILOT << fname << ": Got appInfoLen " << appLen << endl;
00198 #endif
00199 
00200         unpack_MemoAppInfo(&fMemoAppInfo,
00201                 (unsigned char *) memoDB->appInfo(), appLen);
00202 
00203 #ifdef DEBUG
00204         DEBUGKPILOT << fname << ": Unpacked app info." << endl;
00205 
00206         for (int i = 0; i < 15; i++)
00207         {
00208                 DEBUGKPILOT << fname
00209                         << ": Category #"
00210                         << i
00211                         << " has ID "
00212                         << (int) fMemoAppInfo.category.ID[i]
00213                         << " and name "
00214                         << (fMemoAppInfo.category.name[i][0] ? "*" : "-")
00215                         << fMemoAppInfo.category.name[i] << endl;
00216         }
00217 #endif
00218 
00219         populateCategories(fCatList, &fMemoAppInfo.category);
00220 
00221 #ifdef DEBUG
00222         DEBUGKPILOT << fname << ": Populated categories" << endl;
00223 #endif
00224 
00225         initializeMemos(memoDB);
00226 
00227 #ifdef DEBUG
00228         DEBUGKPILOT << fname << ": Finished initializing" << endl;
00229 #endif
00230 
00231         delete memoDB;
00232 
00233         updateWidget();
00234 }
00235 
00236 void MemoWidget::postHotSync()
00237 {
00238         FUNCTIONSETUP;
00239         fMemoList.clear();
00240         initialize();
00241 }
00242 
00243 
00244 // void MemoWidget::setupWidget()
00245 //
00246 // Setup all the GUI components by allocating them.
00247 //
00248 //
00249 void MemoWidget::setupWidget()
00250 {
00251         FUNCTIONSETUP;
00252 
00253         QLabel *label = NULL;
00254         QPushButton *button = NULL;
00255         QGridLayout *grid = new QGridLayout(this, 5, 4, SPACING);
00256 
00257         fCatList = new QComboBox(this);
00258         grid->addWidget(fCatList, 0, 1);
00259         connect(fCatList, SIGNAL(activated(int)),
00260                 this, SLOT(slotSetCategory(int)));
00261         QWhatsThis::add(fCatList,
00262                 i18n("Select the category of addresses\n"
00263                         "to display here."));
00264 
00265         (void) i18n("Memos:");
00266         label = new QLabel(i18n("Category:"), this);
00267         label->setBuddy(fCatList);
00268         grid->addWidget(label, 0, 0);
00269 
00270         fListBox = new QListBox(this);
00271         grid->addMultiCellWidget(fListBox, 1, 1, 0, 1);
00272         connect(fListBox, SIGNAL(highlighted(int)),
00273                 this, SLOT(slotShowMemo(int)));
00274         connect(fListBox, SIGNAL(selectionChanged()),
00275                 this,SLOT(slotUpdateButtons()));
00276         QWhatsThis::add(fListBox,
00277                 i18n("This list displays all the memos\n"
00278                         "in the selected category. Click on\n"
00279                         "one to display it to the right."));
00280 
00281         label = new QLabel(i18n("Memo text:"), this);
00282         grid->addWidget(label, 0, 2);
00283 
00284         fTextWidget = new KTextEdit(this, "textArea");
00285         fTextWidget->setWordWrap(KTextEdit::WidgetWidth);
00286         fTextWidget->setTextFormat(Qt::PlainText);
00287         grid->addMultiCellWidget(fTextWidget, 1, 4, 2, 2);
00288         QWhatsThis::add(fTextWidget,
00289                 i18n("The text of the selected memo appears here."));
00290 
00291         button = new QPushButton(i18n("Import Memo"), this);
00292         grid->addWidget(button, 2, 0);
00293         connect(button, SIGNAL(clicked()), this, SLOT(slotImportMemo()));
00294         QWhatsThis::add(button,
00295                 i18n
00296                 ("Read a text file and add it to the Pilot's memo database."));
00297 
00298         fExportButton = new QPushButton(i18n("Export Memo"), this);
00299         grid->addWidget(fExportButton, 2, 1);
00300         connect(fExportButton, SIGNAL(clicked()), this,
00301                 SLOT(slotExportMemo()));
00302         QWhatsThis::add(fExportButton,
00303                 i18n("Write the selected memo to a file."));
00304 
00305         fDeleteButton = new QPushButton(i18n("Delete Memo"), this);
00306         grid->addWidget(fDeleteButton, 3, 0);
00307         connect(fDeleteButton, SIGNAL(clicked()), this,
00308                 SLOT(slotDeleteMemo()));
00309         QWhatsThis::add(fDeleteButton, i18n("Delete the selected memo."));
00310 }
00311 
00312 void MemoWidget::slotUpdateButtons()
00313 {
00314         FUNCTIONSETUP;
00315 
00316         bool highlight = false;
00317         
00318         if ((fListBox->currentItem() != -1) &&
00319                 (fListBox->isSelected(fListBox->currentItem())))
00320                         highlight=true;
00321         
00322 #ifdef DEBUG
00323         DEBUGKPILOT << fname << ": Selected items " << highlight << endl;
00324 #endif
00325 
00326         if (fExportButton)
00327         {
00328                 fExportButton->setEnabled(highlight);
00329         }
00330         if (fDeleteButton)
00331         {
00332                 fDeleteButton->setEnabled(highlight);
00333         }
00334 }
00335 
00336 void MemoWidget::slotSetCategory(int)
00337 {
00338         FUNCTIONSETUP;
00339         updateWidget();
00340 }
00341 
00342 void MemoWidget::slotDeleteMemo()
00343 {
00344         FUNCTIONSETUP;
00345 
00346         int item = fListBox->currentItem();
00347         
00348         if (item == -1)
00349         {
00350 #ifdef DEBUG
00351                 DEBUGKPILOT << fname << ": No current item selected\n";
00352 #endif
00353                 return;
00354         }
00355 
00356         PilotListItem *p = (PilotListItem *) fListBox->item(item);
00357         PilotMemo *selectedMemo = (PilotMemo *) p->rec();
00358 
00359         if (selectedMemo->id() == 0x0)
00360         {
00361                 // QADE: Why is this? What prevents us from deleting
00362                 // a "new" memo, ie. one we've imported, before *ever*
00363                 // sending it to the Pilot?
00364                 //
00365                 //
00366                 kdWarning() << k_funcinfo <<
00367                         ": Refusing to delete new memo.\n";
00368 
00369                 KMessageBox::error(this,
00370                         i18n("New memo cannot be deleted until "
00371                                 "HotSynced with pilot."),
00372                         i18n("HotSync Required"));
00373                 return;
00374         }
00375 
00376 
00377         if (KMessageBox::questionYesNo(this,
00378                         i18n("Delete currently selected memo?"),
00379                         i18n("Delete Memo?")) == KMessageBox::No)
00380         {
00381 #ifdef DEBUG
00382                 DEBUGKPILOT << fname <<
00383                         ": User decided not to delete memo.\n";
00384 #endif
00385                 return;
00386         }
00387 
00388         selectedMemo->makeDeleted();
00389         writeMemo(selectedMemo);
00390         fMemoList.remove(selectedMemo);
00391         delete p;
00392 }
00393 
00394 
00395 void MemoWidget::updateWidget()
00396 {
00397         FUNCTIONSETUP;
00398 
00399         if (fCatList->currentItem() == -1)
00400         {
00401 #ifdef DEBUG
00402                 DEBUGKPILOT << fname << ": No category selected.\n";
00403 #endif
00404                 return;
00405         }
00406 
00407         int listIndex = 0;
00408         int currentCatID = findSelectedCategory(fCatList,
00409                 &(fMemoAppInfo.category), false);
00410 
00411 
00412         fListBox->clear();
00413         fMemoList.first();
00414 
00415 
00416         // Iterate through all the memos and insert each memo
00417         // only if the category of the memo matches the selected category
00418         // (using -1 to mean "All")
00419         //
00420         //
00421         while (fMemoList.current())
00422         {
00423                 if ((fMemoList.current()->getCat() == currentCatID) ||
00424                         (currentCatID == -1))
00425                 {
00426                         PilotListItem *p =
00427                                 new PilotListItem(fMemoList.current()->
00428                                 shortTitle(),
00429                                 listIndex,
00430                                 fMemoList.current());
00431 
00432                         // List will delete the title of the memo,
00433                         // so there's no memory leak here.
00434                         //
00435                         //
00436                         fListBox->insertItem(p);
00437 
00438 #ifdef DEBUG
00439                         DEBUGKPILOT << fname << ": Added memo "
00440                                 << fMemoList.current()->getTitle() << endl;
00441 #endif
00442                 }
00443                 else
00444                 {
00445 #ifdef DEBUG
00446                         DEBUGKPILOT << fname << ": Skipped memo "
00447                                 << fMemoList.current()->getTitle() << endl;
00448 #endif
00449                 }
00450 
00451                 listIndex++;
00452                 fMemoList.next();
00453         }
00454 
00455         fTextWidget->clear();
00456 
00457         slotUpdateButtons();
00458 
00459         lastSelectedMemo=-1;
00460 }
00461 
00462 void MemoWidget::slotShowMemo(int which)
00463 {
00464         FUNCTIONSETUP;
00465         if ( which == -1 )
00466                 return;
00467 
00468         slotUpdateButtons();
00469         if ( !fListBox->isSelected(which) )
00470         {
00471                 // Handle unselecting a memo. This is easy.
00472                 fTextWidget->blockSignals(true);
00473                 fTextWidget->clear();
00474                 fTextWidget->blockSignals(false);
00475                 return;
00476         }
00477 
00478 
00479 #ifdef DEBUG
00480         DEBUGKPILOT << fname << ": Displaying memo " << which << endl;
00481 #endif
00482         fTextWidget->blockSignals(true);
00483         PilotListItem *p = (PilotListItem *) fListBox->item(which);
00484         PilotMemo *theMemo = (PilotMemo *) p->rec();
00485         fTextWidget->setText(theMemo->text());
00486         fTextWidget->blockSignals(false);
00487 }
00488 
00489 void MemoWidget::writeMemo(PilotMemo * which)
00490 {
00491         FUNCTIONSETUP;
00492 
00493         PilotDatabase *memoDB = new PilotLocalDatabase(dbPath(), CSL1("MemoDB"));
00494         PilotRecord *pilotRec = which->pack();
00495 
00496         memoDB->writeRecord(pilotRec);
00497         delete pilotRec;
00498         delete memoDB;
00499 }
00500 
00501 void MemoWidget::saveChangedMemo()
00502 {
00503         FUNCTIONSETUP;
00504         
00505         if (-1 == lastSelectedMemo) return;
00506         if (!fTextWidget->isModified()) return;
00507 
00508 #ifdef DEBUG
00509         DEBUGKPILOT << fname
00510                 << ": Saving changed memo " << lastSelectedMemo << endl;
00511 #endif
00512         
00513         PilotListItem *p =
00514                 (PilotListItem *) fListBox->item(lastSelectedMemo);
00515         PilotMemo *currentMemo = (PilotMemo *) p->rec();
00516 
00517         currentMemo->setText(PilotAppCategory::codec()->
00518                 fromUnicode(fTextWidget->text()));
00519         writeMemo(currentMemo);
00520 }
00521 
00522 /* virtual */ bool MemoWidget::preHotSync(QString &)
00523 {
00524         FUNCTIONSETUP;
00525         saveChangedMemo();
00526         return true;
00527 }
00528 
00529 void MemoWidget::slotImportMemo()
00530 {
00531         FUNCTIONSETUP;
00532 
00533         int i = 0;
00534         int nextChar;
00535         int currentCatID = findSelectedCategory(fCatList,
00536                 &(fMemoAppInfo.category), true);
00537 
00538         QString fileName = KFileDialog::getOpenFileName();
00539 
00540         if (!fileName.isEmpty())
00541         {
00542                 QFile importFile(fileName);
00543 
00544                 if (importFile.open(IO_ReadOnly) == FALSE)
00545                 {
00546                         // show error!
00547                         return;
00548                 }
00549                 char *text = new char[(int) MemoWidget::MAX_MEMO_LEN];
00550 
00551                 for (i = 0;
00552                         (i < (MemoWidget::MAX_MEMO_LEN - 1))
00553                         && ((nextChar = importFile.getch()) != -1); i++)
00554                         text[i] = nextChar;
00555                 text[i] = 0;
00556                 PilotMemo *aMemo = new PilotMemo(text, 0, 0, currentCatID);
00557 
00558                 fMemoList.append(aMemo);
00559                 writeMemo(aMemo);
00560                 updateWidget();
00561                 delete[]text;
00562         }
00563 }
00564 
00565 void MemoWidget::slotExportMemo()
00566 {
00567         FUNCTIONSETUP;
00568 
00569         int index = fListBox->numRows();
00570         if (index == 0)
00571                 return;
00572 
00573         QString data;
00574 
00575         const QString filter = CSL1("*|Plain text output\n*.xml|XML output");
00576         QString fileName;
00577 
00578         KFileDialog kfile( QString::null , filter, fExportButton , "memoSave" , true );
00579         kfile.setOperationMode( KFileDialog::Saving );
00580 
00581         if ( kfile.exec() == QDialog::Accepted ) {
00582                 fileName = kfile.selectedFile();
00583         }
00584 
00585         if (fileName.isEmpty())
00586                 return;
00587 
00588         QList<PilotListItem> menu_items;
00589 
00590         for (int x = 0; x < index; x++){
00591                 if (fListBox->item(x)->selected()){
00592                         menu_items.append((PilotListItem *) fListBox->item(x));
00593                 }
00594         }
00595 
00596         if (kfile.currentFilter() == CSL1("*.xml") )
00597         {
00598                 MemoWidget::saveAsXML( fileName , menu_items );
00599         }
00600         else
00601         {
00602                 MemoWidget::saveAsText( fileName , menu_items );
00603         }
00604 
00605 
00606         return;
00607 }
00608 
00609 bool MemoWidget::saveAsText(const QString &fileName,const QList<PilotListItem> &memo_list)
00610 {
00611         QFile f( fileName );
00612         QTextStream stream(&f);
00613 
00614         if ( QFile::exists( fileName ) )
00615         {
00616                 if( !f.open(IO_ReadWrite | IO_Append) )
00617                 {
00618                         return false;
00619                 }
00620         }
00621         else
00622         {
00623                 if( !f.open(IO_WriteOnly) )
00624                 {
00625                         return false;
00626                 }
00627         }
00628 
00629         QListIterator<PilotListItem> it(memo_list);
00630         for ( ; it.current(); ++it )
00631         {
00632                 PilotListItem *p = it.current();
00633                 PilotMemo *theMemo = (PilotMemo *) p->rec();
00634                 stream << theMemo->text() << endl;
00635         }
00636 
00637 
00638         return true;
00639 }
00640 
00641 bool MemoWidget::saveAsXML(const QString &fileName,const QList<PilotListItem> &memo_list)
00642 {
00643         QDomDocument doc( CSL1("kpilotmemos") );
00644         QFile f( fileName );
00645         QTextStream stream( &f );
00646         QDomElement memos;
00647         int append = 0;
00648 
00649 
00650         if ( f.exists() )
00651         {
00652                 if ( !f.open(IO_ReadOnly ) ) return false;
00653 
00654                 if ( doc.setContent( &f ) )
00655                 {
00656                 //
00657                 //
00658                 //Only if QDom can read the .xml file and set the doc object to be populated with it's contents
00659                         memos = doc.documentElement();
00660                         if ( memos.tagName()!= CSL1("memos") )
00661                         {
00662                                 return false;
00663                         }
00664                                 //
00665                                 //
00666                                 //This is an XML Document but it isn't a valid KPilot-Memo xml document
00667                         else
00668                         {
00669                                 append = 1;
00670                         }
00671                                 //
00672                                 //
00673                                 //This is a valid KPilot memo, and we will append the current memo to the xml
00674                 }
00675                 else
00676                 {
00677                 //
00678                 //
00679                 //We *couldn't* understand the xml.  Return false!
00680                         return false;
00681                 }
00682         }
00683         else
00684         {
00685                 if ( !f.open(IO_ReadWrite ) ) return false;
00686                 //
00687                 //
00688                 //If there's no such file, we are not appending, just opening the file to read/write.
00689         }
00690 
00691         f.close();
00692     // These are temporary, and should be retrieved from the pilot stuff
00693     QString mpilotid;
00694     mpilotid = "1";
00695     //  End of temp variables
00696 
00697         if (append == 1)
00698         {
00699                 memos = doc.documentElement();
00700         }
00701         else
00702         {
00703                 memos = doc.createElement( CSL1("memos") );
00704                 doc.appendChild ( memos );
00705         }
00706 
00707         QListIterator<PilotListItem> it(memo_list);
00708         for ( ; it.current(); ++it )
00709         {
00710                 PilotListItem *p = it.current();
00711                 PilotMemo *theMemo = (PilotMemo *) p->rec();
00712 
00713 
00714         QDomElement memo = doc.createElement( CSL1("memo") );
00715             memo.setAttribute ( CSL1("pilotid") , mpilotid );
00716             memos.appendChild ( memo );
00717 
00718             //QDomElement category = doc.createElement( "category" );
00719             //head.appendChild ( category );
00720                 //
00721                 //QDomText categorytext = doc.createTextNode( memo->category() );
00722                 //category.appendChild ( categorytext );
00723                 //FIXME
00724 
00725                 QDomElement title = doc.createElement(CSL1("title" ));
00726                 memo.appendChild ( title );
00727 
00728                 QDomText titletext = doc.createTextNode( theMemo->shortTitle() );
00729                 title.appendChild ( titletext );
00730 
00731                 QDomText body = doc.createTextNode( theMemo->text() );
00732                 memo.appendChild ( body );
00733         }
00734         if ( !f.open(IO_WriteOnly ) ) return false;
00735         stream << doc.toString();
00736         return true;
00737 }
00738 
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Sun Feb 15 11:40:44 2004 by doxygen 1.3.5 written by Dimitri van Heesch, © 1997-2001