00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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 <qdatetime.h>
00049 #include <qptrlist.h>
00050
00051 #include <kapplication.h>
00052 #include <kmessagebox.h>
00053 #include <kfiledialog.h>
00054 #include <kdeversion.h>
00055 #include <ktextedit.h>
00056
00057 #include "kpilot.h"
00058 #include "kpilotConfig.h"
00059 #include "listItems.h"
00060 #include "pilotLocalDatabase.h"
00061 #include "pilotMemo.h"
00062
00063 #include "memoWidget.moc"
00064
00065
00066 class MemoWidget::Private
00067 {
00068 public:
00069 Private() : fMemoAppInfo(0L) { } ;
00070 ~Private() { KPILOT_DELETE(fMemoAppInfo); } ;
00071
00072 PilotMemoInfo *fMemoAppInfo;
00073 QPtrList<PilotMemo> fMemoList;
00074 } ;
00075
00076
00077 MemoWidget::MemoWidget(QWidget * parent,
00078 const QString & path) :
00079 PilotComponent(parent, "component_memo", path),
00080 fTextWidget(0L),
00081 d(new Private()),
00082 lastSelectedMemo(-1)
00083 {
00084 FUNCTIONSETUP;
00085
00086 setGeometry(0, 0,
00087 parent->geometry().width(), parent->geometry().height());
00088 setupWidget();
00089 d->fMemoList.setAutoDelete(true);
00090 slotUpdateButtons();
00091 }
00092
00093 MemoWidget::~MemoWidget()
00094 {
00095 FUNCTIONSETUP;
00096 saveChangedMemo();
00097 KPILOT_DELETE(d);
00098 }
00099
00100
00101
00102
00103
00104
00105
00106
00107 void MemoWidget::initializeMemos(PilotDatabase * memoDB)
00108 {
00109 FUNCTIONSETUP;
00110
00111
00112
00113
00114
00115 bool showSecrets = KPilotSettings::showSecrets();
00116
00117 d->fMemoList.clear();
00118
00119
00120 int currentRecord = 0;
00121 PilotRecord *pilotRec;
00122 PilotMemo *memo;
00123
00124 while ((pilotRec = memoDB->readRecordByIndex(currentRecord)) != NULL)
00125 {
00126 if (!pilotRec->isDeleted())
00127 {
00128 if ((!pilotRec->isSecret()) || showSecrets)
00129 {
00130 memo = new PilotMemo(pilotRec);
00131 d->fMemoList.append(memo);
00132
00133 #ifdef DEBUG
00134 DEBUGKPILOT << fname <<
00135 ": Added memo "
00136 << currentRecord << endl;
00137 #endif
00138 }
00139 else
00140 {
00141 #ifdef DEBUG
00142 DEBUGKPILOT << fname <<
00143 ": Skipped secret record " <<
00144 currentRecord << endl;
00145 #endif
00146 }
00147 }
00148 else
00149 {
00150 #ifdef DEBUG
00151 DEBUGKPILOT << fname <<
00152 ": Skipped deleted record " <<
00153 currentRecord << endl;
00154 #endif
00155 }
00156
00157 delete pilotRec;
00158
00159 currentRecord++;
00160 }
00161 }
00162
00163
00164 void MemoWidget::showComponent()
00165 {
00166 FUNCTIONSETUP;
00167 if (!shown) return;
00168
00169
00170
00171
00172
00173 PilotLocalDatabase *memoDB =
00174 new PilotLocalDatabase(dbPath(), CSL1("MemoDB"));
00175 if (memoDB == NULL || !memoDB->isOpen())
00176 {
00177 kdWarning() << k_funcinfo <<
00178 ": Can't open local database MemoDB\n";
00179
00180 populateCategories(fCatList, 0L);
00181 updateWidget();
00182 return;
00183 }
00184
00185 KPILOT_DELETE(d->fMemoAppInfo);
00186 d->fMemoAppInfo = new PilotMemoInfo(memoDB);
00187
00188 d->fMemoAppInfo->dump();
00189 populateCategories(fCatList, d->fMemoAppInfo->categoryInfo());
00190 initializeMemos(memoDB);
00191
00192 KPILOT_DELETE( memoDB );
00193
00194 updateWidget();
00195 }
00196
00197 void MemoWidget::hideComponent()
00198 {
00199 FUNCTIONSETUP;
00200 saveChangedMemo();
00201 fCatList->clear();
00202 fTextWidget->clear();
00203 d->fMemoList.clear();
00204 fListBox->clear();
00205 lastSelectedMemo = -1;
00206 }
00207
00208 void MemoWidget::postHotSync()
00209 {
00210 FUNCTIONSETUP;
00211 d->fMemoList.clear();
00212 showComponent();
00213 }
00214
00215
00216
00217
00218
00219
00220
00221 void MemoWidget::setupWidget()
00222 {
00223 FUNCTIONSETUP;
00224
00225 QLabel *label = NULL;
00226 QPushButton *button = NULL;
00227 QGridLayout *grid = new QGridLayout(this, 5, 4, SPACING);
00228 QString wt;
00229
00230 fCatList = new QComboBox(this);
00231 grid->addWidget(fCatList, 0, 1);
00232 connect(fCatList, SIGNAL(activated(int)),
00233 this, SLOT(slotSetCategory(int)));
00234 QWhatsThis::add(fCatList,
00235 i18n("Select the category of addresses\n"
00236 "to display here."));
00237
00238 (void) i18n("Memos:");
00239 label = new QLabel(i18n("Category:"), this);
00240 label->setBuddy(fCatList);
00241 grid->addWidget(label, 0, 0);
00242
00243 fListBox = new QListBox(this);
00244 grid->addMultiCellWidget(fListBox, 1, 1, 0, 1);
00245 connect(fListBox, SIGNAL(highlighted(int)),
00246 this, SLOT(slotShowMemo(int)));
00247 connect(fListBox, SIGNAL(selectionChanged()),
00248 this,SLOT(slotUpdateButtons()));
00249 QWhatsThis::add(fListBox,
00250 i18n("This list displays all the memos\n"
00251 "in the selected category. Click on\n"
00252 "one to display it to the right."));
00253
00254 label = new QLabel(i18n("Memo text:"), this);
00255 grid->addWidget(label, 0, 2);
00256
00257 fTextWidget = new KTextEdit(this, "textArea");
00258 fTextWidget->setWordWrap(KTextEdit::WidgetWidth);
00259 fTextWidget->setTextFormat(Qt::PlainText);
00260 grid->addMultiCellWidget(fTextWidget, 1, 4, 2, 2);
00261 QWhatsThis::add(fTextWidget,
00262 i18n("The text of the selected memo appears here."));
00263 fTextWidget->setReadOnly(!KPilotSettings::internalEditors());
00264
00265 button = new QPushButton(i18n("Import Memo..."), this);
00266 grid->addWidget(button, 2, 0);
00267 connect(button, SIGNAL(clicked()), this, SLOT(slotImportMemo()));
00268 wt = KPilotSettings::internalEditors() ?
00269 i18n ("Read a text file and add it to the Pilot's memo database.") :
00270 i18n("<qt><i>Import is disabled by the 'internal editors' setting.</i></qt>");
00271 QWhatsThis::add(button,wt);
00272
00273 fExportButton = new QPushButton(i18n("Export Memo..."), this);
00274 grid->addWidget(fExportButton, 2, 1);
00275 connect(fExportButton, SIGNAL(clicked()), this,
00276 SLOT(slotExportMemo()));
00277 QWhatsThis::add(fExportButton,
00278 i18n("Write the selected memo to a file."));
00279
00280 fDeleteButton = new QPushButton(i18n("Delete Memo"), this);
00281 grid->addWidget(fDeleteButton, 3, 1);
00282 connect(fDeleteButton, SIGNAL(clicked()), this,
00283 SLOT(slotDeleteMemo()));
00284 wt = KPilotSettings::internalEditors() ?
00285 i18n("Delete the selected memo.") :
00286 i18n("<qt><i>Deleting is disabled by the 'internal editors' setting.</i></qt>") ;
00287 QWhatsThis::add(fDeleteButton, wt);
00288
00289 button = new QPushButton(i18n("Add Memo"), this);
00290 grid->addWidget(button, 3, 0);
00291 connect(button, SIGNAL(clicked()), this, SLOT(slotAddMemo()));
00292 QWhatsThis::add(button,i18n("Add a new memo to the database."));
00293 }
00294
00295 void MemoWidget::slotUpdateButtons()
00296 {
00297 FUNCTIONSETUP;
00298
00299 bool highlight = false;
00300
00301 if ((fListBox->currentItem() != -1) &&
00302 (fListBox->isSelected(fListBox->currentItem())))
00303 highlight=true;
00304
00305 #ifdef DEBUG
00306 DEBUGKPILOT << fname << ": Selected items " << highlight << endl;
00307 #endif
00308
00309 if (fExportButton)
00310 {
00311 fExportButton->setEnabled(highlight);
00312 }
00313
00314
00315
00316 highlight &= KPilotSettings::internalEditors() ;
00317 if (fDeleteButton)
00318 {
00319 fDeleteButton->setEnabled(highlight);
00320 }
00321 }
00322
00323 void MemoWidget::slotSetCategory(int)
00324 {
00325 FUNCTIONSETUP;
00326 updateWidget();
00327 }
00328
00329 void MemoWidget::slotDeleteMemo()
00330 {
00331 FUNCTIONSETUP;
00332 if (!shown) return;
00333
00334 int item = fListBox->currentItem();
00335
00336 if (item == -1)
00337 {
00338 #ifdef DEBUG
00339 DEBUGKPILOT << fname << ": No current item selected\n";
00340 #endif
00341 return;
00342 }
00343 if (KMessageBox::questionYesNo(this,
00344 i18n("Delete currently selected memo?"),
00345 i18n("Delete Memo?"), KStdGuiItem::del(), KStdGuiItem::cancel()) != KMessageBox::Yes)
00346 {
00347 #ifdef DEBUG
00348 DEBUGKPILOT << fname <<
00349 ": User decided not to delete memo.\n";
00350 #endif
00351 return;
00352 }
00353
00354 PilotListItem *p = (PilotListItem *) fListBox->item(item);
00355 PilotMemo *selectedMemo = (PilotMemo *) p->rec();
00356
00357 if (selectedMemo->id() == 0x0)
00358 {
00359 #ifdef DEBUG
00360 DEBUGKPILOT << fname << ": Searching for record to delete (it's fresh)" << endl;
00361 #endif
00362 PilotLocalDatabase *memoDB = new PilotLocalDatabase(dbPath(), CSL1("MemoDB"));
00363 if (!memoDB || (!memoDB->isOpen()))
00364 {
00365
00366 kdWarning() << k_funcinfo << ": Can't open MemoDB" << endl;
00367 KMessageBox::sorry(this,
00368 i18n("Cannot open MemoDB to delete record."),
00369 i18n("Cannot Delete Memo"));
00370 return;
00371 }
00372 memoDB->resetDBIndex();
00373 #ifdef DEBUG
00374 DEBUGKPILOT << fname << ": Searching for new record." << endl;
00375 #endif
00376 const PilotRecord *r = 0L;
00377 while ((r = memoDB->findNextNewRecord()))
00378 {
00379 #ifdef DEBUG
00380 DEBUGKPILOT << fname << ": got record " << (void *) r << endl;
00381 #endif
00382 PilotMemo m(r);
00383 if (m.text() == selectedMemo->text())
00384 {
00385 #ifdef DEBUG
00386 DEBUGKPILOT << fname << ": I think I found the memo." << endl;
00387 #endif
00388 (const_cast<PilotRecord *>(r))->setDeleted(true);
00389 break;
00390 }
00391 }
00392 delete memoDB;
00393 }
00394 else
00395 {
00396 selectedMemo->setDeleted(true);
00397 writeMemo(selectedMemo);
00398 }
00399 d->fMemoList.remove(selectedMemo);
00400 delete p;
00401 }
00402
00403
00404 void MemoWidget::updateWidget()
00405 {
00406 FUNCTIONSETUP;
00407 if (!shown || !d->fMemoAppInfo ) 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 d->fMemoAppInfo->categoryInfo(), false);
00420
00421
00422 fListBox->clear();
00423 d->fMemoList.first();
00424
00425
00426
00427
00428
00429
00430
00431 while (d->fMemoList.current())
00432 {
00433 PilotMemo *curr = d->fMemoList.current();
00434 if ((curr->category() == currentCatID) ||
00435 (currentCatID == -1))
00436 {
00437 PilotListItem *p =
00438 new PilotListItem(curr->shortTitle(),
00439 listIndex,
00440 curr);
00441
00442
00443
00444
00445
00446 fListBox->insertItem(p);
00447
00448 #ifdef DEBUG
00449 DEBUGKPILOT << fname << ": Added memo "
00450 << curr->getTitle() << endl;
00451 #endif
00452 }
00453 else
00454 {
00455 #ifdef DEBUG
00456 DEBUGKPILOT << fname << ": Skipped memo "
00457 << curr->getTitle() << endl;
00458 #endif
00459 }
00460
00461 listIndex++;
00462 d->fMemoList.next();
00463 }
00464
00465 fTextWidget->clear();
00466
00467 slotUpdateButtons();
00468
00469 lastSelectedMemo=-1;
00470 }
00471
00472 void MemoWidget::showMemo(const PilotMemo *m)
00473 {
00474 FUNCTIONSETUP;
00475
00476 int index = fListBox->count();
00477 for (int x = 0; x < index; x++)
00478 {
00479 PilotMemo *p = (PilotMemo *) ((PilotListItem *)fListBox->item(x))->rec();
00480 #ifdef DEBUG
00481 DEBUGKPILOT << fname << ": Memo @" << (void *) p <<endl;
00482 DEBUGKPILOT << fname << " :" << fListBox->item(x)->text() << endl;
00483 #endif
00484 if (m==p)
00485 {
00486 fListBox->setSelected(x,true);
00487 slotShowMemo(x);
00488 break;
00489 }
00490 }
00491
00492 }
00493
00494 void MemoWidget::slotShowMemo(int which)
00495 {
00496 FUNCTIONSETUP;
00497 if ( which == -1 ) return;
00498 if (!shown) return;
00499
00500 slotUpdateButtons();
00501 if ( !fListBox->isSelected(which) )
00502 {
00503
00504 fTextWidget->blockSignals(true);
00505 fTextWidget->clear();
00506 fTextWidget->blockSignals(false);
00507 return;
00508 }
00509
00510
00511 #ifdef DEBUG
00512 DEBUGKPILOT << fname << ": Displaying memo " << which << endl;
00513 #endif
00514 fTextWidget->blockSignals(true);
00515 PilotListItem *p = (PilotListItem *) fListBox->item(which);
00516 PilotMemo *theMemo = (PilotMemo *) p->rec();
00517 fTextWidget->setText(theMemo->text());
00518 fTextWidget->blockSignals(false);
00519 }
00520
00521
00522 void MemoWidget::writeMemo(PilotMemo * which)
00523 {
00524 FUNCTIONSETUP;
00525 if (!shown) return;
00526 PilotRecord *pilotRec = which->pack();
00527 PilotDatabase *memoDB = new PilotLocalDatabase(dbPath(), CSL1("MemoDB"));
00528 memoDB->writeRecord(pilotRec);
00529 markDBDirty(CSL1("MemoDB"));
00530 KPILOT_DELETE( memoDB );
00531 KPILOT_DELETE( pilotRec );
00532 }
00533
00534 void MemoWidget::saveChangedMemo()
00535 {
00536 FUNCTIONSETUP;
00537 if (!shown) return;
00538
00539 if (-1 == lastSelectedMemo) return;
00540 if (!fTextWidget->isModified()) return;
00541
00542 #ifdef DEBUG
00543 DEBUGKPILOT << fname
00544 << ": Saving changed memo " << lastSelectedMemo << endl;
00545 #endif
00546
00547 PilotListItem *p =
00548 (PilotListItem *) fListBox->item(lastSelectedMemo);
00549 PilotMemo *currentMemo = (PilotMemo *) p->rec();
00550
00551
00552 currentMemo->setText(Pilot::toPilot(fTextWidget->text()));
00553 writeMemo(currentMemo);
00554 }
00555
00556 bool MemoWidget::preHotSync(QString &)
00557 {
00558 FUNCTIONSETUP;
00559 saveChangedMemo();
00560 return true;
00561 }
00562
00563 bool MemoWidget::addMemo(const QString &s, int category)
00564 {
00565 FUNCTIONSETUP;
00566
00567 if (s.length() >= MemoWidget::MAX_MEMO_LEN)
00568 {
00569 return false;
00570 }
00571 if ((category<0) || (category>=(int)Pilot::CATEGORY_COUNT))
00572 {
00573 category=Pilot::Unfiled;
00574 }
00575
00576 PilotMemo *aMemo = new PilotMemo();
00577 aMemo->setCategory(category);
00578 aMemo->setText(s);
00579
00580 d->fMemoList.append(aMemo);
00581 writeMemo(aMemo);
00582 updateWidget();
00583 #ifdef DEBUG
00584 DEBUGKPILOT << fname << ": New memo @" << (void *)aMemo << endl;
00585 #endif
00586 showMemo(aMemo);
00587 return true;
00588 }
00589
00590 void MemoWidget::slotAddMemo()
00591 {
00592 FUNCTIONSETUP;
00593 int currentCatID = findSelectedCategory(fCatList,
00594 d->fMemoAppInfo->categoryInfo(), true);
00595 addMemo(QDateTime::currentDateTime().toString(), currentCatID);
00596 }
00597
00598 void MemoWidget::slotImportMemo()
00599 {
00600 FUNCTIONSETUP;
00601 if (!shown || !d->fMemoAppInfo ) return;
00602
00603 int currentCatID = findSelectedCategory(fCatList,
00604 d->fMemoAppInfo->categoryInfo(), true);
00605
00606 QString fileName = KFileDialog::getOpenFileName();
00607
00608 if (!fileName.isEmpty())
00609 {
00610 QFile importFile(fileName);
00611
00612 if (importFile.open(IO_ReadOnly) == FALSE)
00613 {
00614
00615 return;
00616 }
00617
00618 if (importFile.size() > MemoWidget::MAX_MEMO_LEN)
00619 {
00620
00621 return;
00622 }
00623
00624 QTextStream stream(&importFile);
00625 QString memoText = stream.read();
00626 addMemo(memoText, currentCatID);
00627 }
00628 }
00629
00630 void MemoWidget::slotExportMemo()
00631 {
00632 FUNCTIONSETUP;
00633 if (!shown) return;
00634
00635 int index = fListBox->numRows();
00636 if (index == 0)
00637 return;
00638
00639 QString data;
00640
00641 const QString filter = CSL1("*|Plain text output\n*.xml|XML output");
00642 QString fileName;
00643
00644 KFileDialog kfile( QString::null , filter, fExportButton , "memoSave" , true );
00645 kfile.setOperationMode( KFileDialog::Saving );
00646
00647 if ( kfile.exec() == QDialog::Accepted ) {
00648 fileName = kfile.selectedFile();
00649 }
00650
00651 if (fileName.isEmpty())
00652 return;
00653
00654 QPtrList<PilotListItem> menu_items;
00655
00656 for (int x = 0; x < index; x++){
00657 if (fListBox->item(x)->isSelected()){
00658 menu_items.append((PilotListItem *) fListBox->item(x));
00659 }
00660 }
00661
00662 if (kfile.currentFilter() == CSL1("*.xml") )
00663 {
00664 MemoWidget::saveAsXML( fileName , menu_items );
00665 }
00666 else
00667 {
00668 MemoWidget::saveAsText( fileName , menu_items );
00669 }
00670
00671
00672 return;
00673 }
00674
00675 bool MemoWidget::saveAsText(const QString &fileName,const QPtrList<PilotListItem> &memo_list)
00676 {
00677 QFile f( fileName );
00678 QTextStream stream(&f);
00679
00680 if ( QFile::exists( fileName ) )
00681 {
00682 if( !f.open(IO_ReadWrite | IO_Append) )
00683 {
00684 return false;
00685 }
00686 }
00687 else
00688 {
00689 if( !f.open(IO_WriteOnly) )
00690 {
00691 return false;
00692 }
00693 }
00694
00695 QPtrListIterator<PilotListItem> it(memo_list);
00696 for ( ; it.current(); ++it )
00697 {
00698 PilotListItem *p = it.current();
00699 PilotMemo *theMemo = (PilotMemo *) p->rec();
00700 stream << theMemo->text() << endl;
00701 }
00702
00703
00704 return true;
00705 }
00706
00707 bool MemoWidget::saveAsXML(const QString &fileName,const QPtrList<PilotListItem> &memo_list)
00708 {
00709 QDomDocument doc( CSL1("kpilotmemos") );
00710 QFile f( fileName );
00711 QTextStream stream( &f );
00712 QDomElement memos;
00713 int append = 0;
00714
00715
00716 if ( f.exists() )
00717 {
00718 if ( !f.open(IO_ReadOnly ) ) return false;
00719
00720 if ( doc.setContent( &f ) )
00721 {
00722
00723
00724
00725 memos = doc.documentElement();
00726 if ( memos.tagName()!= CSL1("memos") )
00727 {
00728 return false;
00729 }
00730
00731
00732
00733 else
00734 {
00735 append = 1;
00736 }
00737
00738
00739
00740 }
00741 else
00742 {
00743
00744
00745
00746 return false;
00747 }
00748 }
00749 else
00750 {
00751 if ( !f.open(IO_ReadWrite ) ) return false;
00752
00753
00754
00755 }
00756
00757 f.close();
00758
00759 QString mpilotid;
00760 mpilotid = "1";
00761
00762
00763 if (append == 1)
00764 {
00765 memos = doc.documentElement();
00766 }
00767 else
00768 {
00769 memos = doc.createElement( CSL1("memos") );
00770 doc.appendChild ( memos );
00771 }
00772
00773 QPtrListIterator<PilotListItem> it(memo_list);
00774 for ( ; it.current(); ++it )
00775 {
00776 PilotListItem *p = it.current();
00777 PilotMemo *theMemo = (PilotMemo *) p->rec();
00778
00779
00780 QDomElement memo = doc.createElement( CSL1("memo") );
00781 memo.setAttribute ( CSL1("pilotid") , mpilotid );
00782 memos.appendChild ( memo );
00783
00784
00785
00786
00787
00788
00789
00790
00791 QDomElement title = doc.createElement(CSL1("title" ));
00792 memo.appendChild ( title );
00793
00794 QDomText titletext = doc.createTextNode( theMemo->shortTitle() );
00795 title.appendChild ( titletext );
00796
00797 QDomText body = doc.createTextNode( theMemo->text() );
00798 memo.appendChild ( body );
00799 }
00800 if ( !f.open(IO_WriteOnly ) ) return false;
00801 stream << doc.toString();
00802 return true;
00803 }
00804