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