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