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