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