summaryrefslogtreecommitdiff
authorzecke <zecke>2002-06-19 17:38:11 (UTC)
committer zecke <zecke>2002-06-19 17:38:11 (UTC)
commit23ac56db3aa77b298f20b288aadf503fd09a23a9 (patch) (unidiff)
treefe820ec743bbf829d31ae3ab1436a41a69b1855c
parentdee5f6c5a3bd982913d0b234fb9392ce68d5df63 (diff)
downloadopie-23ac56db3aa77b298f20b288aadf503fd09a23a9.zip
opie-23ac56db3aa77b298f20b288aadf503fd09a23a9.tar.gz
opie-23ac56db3aa77b298f20b288aadf503fd09a23a9.tar.bz2
Tille ask Diana how she was able to trigger that bug?
I nominate her for the bug finding queen 2002. Ok I just fixed two possible crashes with the risk of losing data.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/pim/addressbook/abtable.cpp25
1 files changed, 17 insertions, 8 deletions
diff --git a/core/pim/addressbook/abtable.cpp b/core/pim/addressbook/abtable.cpp
index e9e6a0b..3fa1a7c 100644
--- a/core/pim/addressbook/abtable.cpp
+++ b/core/pim/addressbook/abtable.cpp
@@ -437,502 +437,511 @@ QString AbTable::findContactContact( const Contact &entry )
437 value = entry.notes(); 437 value = entry.notes();
438 break; 438 break;
439 } 439 }
440 if ( !value.isEmpty() ) 440 if ( !value.isEmpty() )
441 break; 441 break;
442 } 442 }
443 return value; 443 return value;
444} 444}
445 445
446void AbTable::addEntry( const Contact &newCnt ) 446void AbTable::addEntry( const Contact &newCnt )
447{ 447{
448 int row = numRows(); 448 int row = numRows();
449 setNumRows( row + 1 ); 449 setNumRows( row + 1 );
450 updateJournal( newCnt, Contact::ACTION_ADD ); 450 updateJournal( newCnt, Contact::ACTION_ADD );
451 insertIntoTable( newCnt, row ); 451 insertIntoTable( newCnt, row );
452 setCurrentCell( row, 0 ); 452 setCurrentCell( row, 0 );
453 updateVisible(); 453 updateVisible();
454} 454}
455 455
456void AbTable::resizeRows( int size ) { 456void AbTable::resizeRows( int size ) {
457/* 457/*
458 if (numRows()) { 458 if (numRows()) {
459 for (int i = 0; i < numRows(); i++) { 459 for (int i = 0; i < numRows(); i++) {
460 setRowHeight( i, size ); 460 setRowHeight( i, size );
461 } 461 }
462 }*/ 462 }*/
463 updateVisible(); 463 updateVisible();
464} 464}
465 465
466void AbTable::updateJournal( const Contact &cnt, 466void AbTable::updateJournal( const Contact &cnt,
467 Contact::journal_action action, int row ) 467 Contact::journal_action action, int row )
468{ 468{
469 QFile f( journalFileName() ); 469 QFile f( journalFileName() );
470 if ( !f.open(IO_WriteOnly|IO_Append) ) 470 if ( !f.open(IO_WriteOnly|IO_Append) )
471 return; 471 return;
472 QString buf; 472 QString buf;
473 QCString str; 473 QCString str;
474 buf = "<Contact "; 474 buf = "<Contact ";
475 cnt.save( buf ); 475 cnt.save( buf );
476 buf += " action=\"" + QString::number( (int)action ) + "\" "; 476 buf += " action=\"" + QString::number( (int)action ) + "\" ";
477 if ( action == Contact::ACTION_REMOVE || action == Contact::ACTION_REPLACE) 477 if ( action == Contact::ACTION_REMOVE || action == Contact::ACTION_REPLACE)
478 buf += " actionrow=\"" + QString::number(row) + "\" "; 478 buf += " actionrow=\"" + QString::number(row) + "\" ";
479 buf += "/>\n"; 479 buf += "/>\n";
480 QCString cstr = buf.utf8(); 480 QCString cstr = buf.utf8();
481 f.writeBlock( cstr.data(), cstr.length() ); 481 f.writeBlock( cstr.data(), cstr.length() );
482 QCopEnvelope( "QPE/PIM", "addressbookUpdated()" ); 482 QCopEnvelope( "QPE/PIM", "addressbookUpdated()" );
483} 483}
484 484
485bool AbTable::save( const QString &fn ) 485bool AbTable::save( const QString &fn )
486{ 486{
487// QTime t; 487// QTime t;
488// t.start(); 488// t.start();
489 489
490 QString strNewFile = fn + ".new"; 490 QString strNewFile = fn + ".new";
491 QFile f( strNewFile ); 491 QFile f( strNewFile );
492 if ( !f.open( IO_WriteOnly|IO_Raw ) ) 492 if ( !f.open( IO_WriteOnly|IO_Raw ) )
493 return false; 493 return false;
494 494
495 int total_written; 495 int total_written;
496 QString out; 496 QString out;
497 out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n" 497 out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n"
498 " <Groups>\n" 498 " <Groups>\n"
499 " </Groups>\n" 499 " </Groups>\n"
500 " <Contacts>\n"; 500 " <Contacts>\n";
501 QMapIterator<AbTableItem*, Contact> it; 501 QMapIterator<AbTableItem*, Contact> it;
502 for ( it = contactList.begin(); it != contactList.end(); ++it ) { 502 for ( it = contactList.begin(); it != contactList.end(); ++it ) {
503 out += "<Contact "; 503 out += "<Contact ";
504 it.data().save( out ); 504 it.data().save( out );
505 out += "/>\n"; 505 out += "/>\n";
506 QCString cstr = out.utf8(); 506 QCString cstr = out.utf8();
507 total_written = f.writeBlock( cstr.data(), cstr.length() ); 507 total_written = f.writeBlock( cstr.data(), cstr.length() );
508 if ( total_written != int(cstr.length()) ) { 508 if ( total_written != int(cstr.length()) ) {
509 f.close(); 509 f.close();
510 QFile::remove( strNewFile ); 510 QFile::remove( strNewFile );
511 return false; 511 return false;
512 } 512 }
513 out = ""; 513 out = "";
514 } 514 }
515 out += " </Contacts>\n</AddressBook>\n"; 515 out += " </Contacts>\n</AddressBook>\n";
516 516
517 QCString cstr = out.utf8(); 517 QCString cstr = out.utf8();
518 total_written = f.writeBlock( cstr.data(), cstr.length() ); 518 total_written = f.writeBlock( cstr.data(), cstr.length() );
519 if ( total_written != int(cstr.length()) ) { 519 if ( total_written != int(cstr.length()) ) {
520 f.close(); 520 f.close();
521 QFile::remove( strNewFile ); 521 QFile::remove( strNewFile );
522 return false; 522 return false;
523 } 523 }
524 f.close(); 524 f.close();
525 525
526// qDebug("saving: %d", t.elapsed() ); 526// qDebug("saving: %d", t.elapsed() );
527 527
528 // move the file over, I'm just going to use the system call 528 // move the file over, I'm just going to use the system call
529 // because, I don't feel like using QDir. 529 // because, I don't feel like using QDir.
530 if ( ::rename( strNewFile.latin1(), fn.latin1() ) < 0 ) { 530 if ( ::rename( strNewFile.latin1(), fn.latin1() ) < 0 ) {
531 qWarning( "problem renaming file %s to %s, errno: %d", 531 qWarning( "problem renaming file %s to %s, errno: %d",
532 strNewFile.latin1(), fn.latin1(), errno ); 532 strNewFile.latin1(), fn.latin1(), errno );
533 // remove the tmp file... 533 // remove the tmp file...
534 QFile::remove( strNewFile ); 534 QFile::remove( strNewFile );
535 } 535 }
536 // remove the journal... 536 // remove the journal...
537 QFile::remove( journalFileName() ); 537 QFile::remove( journalFileName() );
538 return true; 538 return true;
539} 539}
540 540
541void AbTable::load( const QString &fn ) 541void AbTable::load( const QString &fn )
542{ 542{
543 setSorting( false ); 543 setSorting( false );
544 loadFile( fn, false ); 544 loadFile( fn, false );
545 // merge in the journal 545 // merge in the journal
546 if ( QFile::exists( journalFileName() ) ) { 546 if ( QFile::exists( journalFileName() ) ) {
547 loadFile( journalFileName(), true ); 547 loadFile( journalFileName(), true );
548 save( fn ); 548 save( fn );
549 } 549 }
550 setSorting( true ); 550 setSorting( true );
551 resort(); 551 resort();
552} 552}
553 553
554void AbTable::loadFile( const QString &strFile, bool journalFile ) 554void AbTable::loadFile( const QString &strFile, bool journalFile )
555{ 555{
556// QTime t; 556// QTime t;
557// t.start(); 557// t.start();
558 QFile f( strFile ); 558 QFile f( strFile );
559 if ( !f.open(IO_ReadOnly) ) 559 if ( !f.open(IO_ReadOnly) )
560 return; 560 return;
561 QList<Contact> list; 561 QList<Contact> list;
562 list.setAutoDelete( TRUE ); 562 list.setAutoDelete( TRUE );
563 QByteArray ba = f.readAll(); 563 QByteArray ba = f.readAll();
564 f.close(); 564 f.close();
565 if (ba.isEmpty() )
566 return;
565 char *uc = ba.data();//(QChar *)data.unicode(); 567 char *uc = ba.data();//(QChar *)data.unicode();
566 int len = ba.size();//data.length(); 568 int len = ba.size();//data.length();
567 bool foundAction = false; 569 bool foundAction = false;
568 Contact::journal_action action; 570 Contact::journal_action action;
569 bool foundKey = false; 571 bool foundKey = false;
570 int journalKey = 0; 572 int journalKey = 0;
571 573
572 const int JOURNALACTION = Qtopia::Notes + 1; 574 const int JOURNALACTION = Qtopia::Notes + 1;
573 const int JOURNALROW = JOURNALACTION + 1; 575 const int JOURNALROW = JOURNALACTION + 1;
574 576
575 // ********************************** 577 // **********************************
576 // CHANGE THE SIZE OF THE DICT IF YOU ADD ANY MORE FIELDS!!!! 578 // CHANGE THE SIZE OF THE DICT IF YOU ADD ANY MORE FIELDS!!!!
577 // ********************************** 579 // **********************************
578 QAsciiDict<int> dict( 47 ); 580 QAsciiDict<int> dict( 47 );
579 dict.setAutoDelete( TRUE ); 581 dict.setAutoDelete( TRUE );
580 dict.insert( "Uid", new int(Qtopia::AddressUid) ); 582 dict.insert( "Uid", new int(Qtopia::AddressUid) );
581 dict.insert( "Title", new int(Qtopia::Title) ); 583 dict.insert( "Title", new int(Qtopia::Title) );
582 dict.insert( "FirstName", new int(Qtopia::FirstName) ); 584 dict.insert( "FirstName", new int(Qtopia::FirstName) );
583 dict.insert( "MiddleName", new int(Qtopia::MiddleName) ); 585 dict.insert( "MiddleName", new int(Qtopia::MiddleName) );
584 dict.insert( "LastName", new int(Qtopia::LastName) ); 586 dict.insert( "LastName", new int(Qtopia::LastName) );
585 dict.insert( "Suffix", new int(Qtopia::Suffix) ); 587 dict.insert( "Suffix", new int(Qtopia::Suffix) );
586 dict.insert( "FileAs", new int(Qtopia::FileAs) ); 588 dict.insert( "FileAs", new int(Qtopia::FileAs) );
587 dict.insert( "Categories", new int(Qtopia::AddressCategory) ); 589 dict.insert( "Categories", new int(Qtopia::AddressCategory) );
588 dict.insert( "DefaultEmail", new int(Qtopia::DefaultEmail) ); 590 dict.insert( "DefaultEmail", new int(Qtopia::DefaultEmail) );
589 dict.insert( "Emails", new int(Qtopia::Emails) ); 591 dict.insert( "Emails", new int(Qtopia::Emails) );
590 dict.insert( "HomeStreet", new int(Qtopia::HomeStreet) ); 592 dict.insert( "HomeStreet", new int(Qtopia::HomeStreet) );
591 dict.insert( "HomeCity", new int(Qtopia::HomeCity) ); 593 dict.insert( "HomeCity", new int(Qtopia::HomeCity) );
592 dict.insert( "HomeState", new int(Qtopia::HomeState) ); 594 dict.insert( "HomeState", new int(Qtopia::HomeState) );
593 dict.insert( "HomeZip", new int(Qtopia::HomeZip) ); 595 dict.insert( "HomeZip", new int(Qtopia::HomeZip) );
594 dict.insert( "HomeCountry", new int(Qtopia::HomeCountry) ); 596 dict.insert( "HomeCountry", new int(Qtopia::HomeCountry) );
595 dict.insert( "HomePhone", new int(Qtopia::HomePhone) ); 597 dict.insert( "HomePhone", new int(Qtopia::HomePhone) );
596 dict.insert( "HomeFax", new int(Qtopia::HomeFax) ); 598 dict.insert( "HomeFax", new int(Qtopia::HomeFax) );
597 dict.insert( "HomeMobile", new int(Qtopia::HomeMobile) ); 599 dict.insert( "HomeMobile", new int(Qtopia::HomeMobile) );
598 dict.insert( "HomeWebPage", new int(Qtopia::HomeWebPage) ); 600 dict.insert( "HomeWebPage", new int(Qtopia::HomeWebPage) );
599 dict.insert( "Company", new int(Qtopia::Company) ); 601 dict.insert( "Company", new int(Qtopia::Company) );
600 dict.insert( "BusinessStreet", new int(Qtopia::BusinessStreet) ); 602 dict.insert( "BusinessStreet", new int(Qtopia::BusinessStreet) );
601 dict.insert( "BusinessCity", new int(Qtopia::BusinessCity) ); 603 dict.insert( "BusinessCity", new int(Qtopia::BusinessCity) );
602 dict.insert( "BusinessState", new int(Qtopia::BusinessState) ); 604 dict.insert( "BusinessState", new int(Qtopia::BusinessState) );
603 dict.insert( "BusinessZip", new int(Qtopia::BusinessZip) ); 605 dict.insert( "BusinessZip", new int(Qtopia::BusinessZip) );
604 dict.insert( "BusinessCountry", new int(Qtopia::BusinessCountry) ); 606 dict.insert( "BusinessCountry", new int(Qtopia::BusinessCountry) );
605 dict.insert( "BusinessWebPage", new int(Qtopia::BusinessWebPage) ); 607 dict.insert( "BusinessWebPage", new int(Qtopia::BusinessWebPage) );
606 dict.insert( "JobTitle", new int(Qtopia::JobTitle) ); 608 dict.insert( "JobTitle", new int(Qtopia::JobTitle) );
607 dict.insert( "Department", new int(Qtopia::Department) ); 609 dict.insert( "Department", new int(Qtopia::Department) );
608 dict.insert( "Office", new int(Qtopia::Office) ); 610 dict.insert( "Office", new int(Qtopia::Office) );
609 dict.insert( "BusinessPhone", new int(Qtopia::BusinessPhone) ); 611 dict.insert( "BusinessPhone", new int(Qtopia::BusinessPhone) );
610 dict.insert( "BusinessFax", new int(Qtopia::BusinessFax) ); 612 dict.insert( "BusinessFax", new int(Qtopia::BusinessFax) );
611 dict.insert( "BusinessMobile", new int(Qtopia::BusinessMobile) ); 613 dict.insert( "BusinessMobile", new int(Qtopia::BusinessMobile) );
612 dict.insert( "BusinessPager", new int(Qtopia::BusinessPager) ); 614 dict.insert( "BusinessPager", new int(Qtopia::BusinessPager) );
613 dict.insert( "Profession", new int(Qtopia::Profession) ); 615 dict.insert( "Profession", new int(Qtopia::Profession) );
614 dict.insert( "Assistant", new int(Qtopia::Assistant) ); 616 dict.insert( "Assistant", new int(Qtopia::Assistant) );
615 dict.insert( "Manager", new int(Qtopia::Manager) ); 617 dict.insert( "Manager", new int(Qtopia::Manager) );
616 dict.insert( "Spouse", new int(Qtopia::Spouse) ); 618 dict.insert( "Spouse", new int(Qtopia::Spouse) );
617 dict.insert( "Children", new int(Qtopia::Children) ); 619 dict.insert( "Children", new int(Qtopia::Children) );
618 dict.insert( "Gender", new int(Qtopia::Gender) ); 620 dict.insert( "Gender", new int(Qtopia::Gender) );
619 dict.insert( "Birthday", new int(Qtopia::Birthday) ); 621 dict.insert( "Birthday", new int(Qtopia::Birthday) );
620 dict.insert( "Anniversary", new int(Qtopia::Anniversary) ); 622 dict.insert( "Anniversary", new int(Qtopia::Anniversary) );
621 dict.insert( "Nickname", new int(Qtopia::Nickname) ); 623 dict.insert( "Nickname", new int(Qtopia::Nickname) );
622 dict.insert( "Notes", new int(Qtopia::Notes) ); 624 dict.insert( "Notes", new int(Qtopia::Notes) );
623 dict.insert( "action", new int(JOURNALACTION) ); 625 dict.insert( "action", new int(JOURNALACTION) );
624 dict.insert( "actionrow", new int(JOURNALROW) ); 626 dict.insert( "actionrow", new int(JOURNALROW) );
625 627
626 int i = 0; 628 int i = 0;
627 int num = 0; 629 int num = 0;
628 char *point; 630 char *point;
629 while ( (point = strstr( uc+i, "<Contact " ) ) != NULL ) { 631 while ( (point = strstr( uc+i, "<Contact " ) ) != NULL ) {
630 i = point - uc; 632 i = point - uc;
631 // if we are reading the standard file, we just need to 633 // if we are reading the standard file, we just need to
632 // insert info, so just say we'll do an insert... 634 // insert info, so just say we'll do an insert...
633 action = Contact::ACTION_ADD; 635 action = Contact::ACTION_ADD;
634 // new Contact 636 // new Contact
635 Contact *cnt = new Contact; 637 Contact *cnt = new Contact;
636 i += 9; 638 i += 9;
637 while ( 1 ) { 639 while ( 1 ) {
638 while ( i < len && (uc[i] == ' ' || uc[i] == '\n' || uc[i] == '\r') ) 640 while ( i < len && (uc[i] == ' ' || uc[i] == '\n' || uc[i] == '\r') )
639 i++; 641 i++;
640 if ( i >= len-2 || (uc[i] == '/' && uc[i+1] == '>') ) 642 if ( i >= len-2 || (uc[i] == '/' && uc[i+1] == '>') )
641 break; 643 break;
642 // we have another attribute read it. 644 // we have another attribute read it.
643 int j = i; 645 int j = i;
644 while ( j < len && uc[j] != '=' ) 646 while ( j < len && uc[j] != '=' )
645 j++; 647 j++;
646 char *attr = uc+i; 648 char *attr = uc+i;
647 uc[j] = '\0'; 649 uc[j] = '\0';
648 //qDebug("attr=%s", attr.latin1() ); 650 //qDebug("attr=%s", attr.latin1() );
649 i = ++j; // skip = 651 i = ++j; // skip =
650 while ( i < len && uc[i] != '"' ) 652 while ( i < len && uc[i] != '"' )
651 i++; 653 i++;
652 j = ++i; 654 j = ++i;
653 bool haveEnt = FALSE; 655 bool haveEnt = FALSE;
654 bool haveUtf = FALSE; 656 bool haveUtf = FALSE;
655 while ( j < len && uc[j] != '"' ) { 657 while ( j < len && uc[j] != '"' ) {
656 if ( uc[j] == '&' ) 658 if ( uc[j] == '&' )
657 haveEnt = TRUE; 659 haveEnt = TRUE;
658 if ( ((unsigned char)uc[j]) > 0x7f ) 660 if ( ((unsigned char)uc[j]) > 0x7f )
659 haveUtf = TRUE; 661 haveUtf = TRUE;
660 j++; 662 j++;
661 } 663 }
662 664
663 if ( j == i ) { 665 if ( j == i ) {
664 // empty value 666 // empty value
665 i = j + 1; 667 i = j + 1;
666 continue; 668 continue;
667 } 669 }
668 670
669 QString value = haveUtf ? QString::fromUtf8( uc+i, j-i ) 671 QString value = haveUtf ? QString::fromUtf8( uc+i, j-i )
670 : QString::fromLatin1( uc+i, j-i ); 672 : QString::fromLatin1( uc+i, j-i );
671 if ( haveEnt ) 673 if ( haveEnt )
672 value = Qtopia::plainString( value ); 674 value = Qtopia::plainString( value );
673 i = j + 1; 675 i = j + 1;
674 676
675 int *find = dict[ attr ]; 677 int *find = dict[ attr ];
676 if ( !find ) { 678 if ( !find ) {
677 cnt->setCustomField(attr, value); 679 cnt->setCustomField(attr, value);
678 continue; 680 continue;
679 } 681 }
680#if 1 682#if 1
681 switch( *find ) { 683 switch( *find ) {
682 case Qtopia::AddressUid: 684 case Qtopia::AddressUid:
683 cnt->setUid( value.toInt() ); 685 cnt->setUid( value.toInt() );
684 break; 686 break;
685 case Qtopia::AddressCategory: 687 case Qtopia::AddressCategory:
686 cnt->setCategories( Qtopia::Record::idsFromString( value )); 688 cnt->setCategories( Qtopia::Record::idsFromString( value ));
687 break; 689 break;
688 case JOURNALACTION: 690 case JOURNALACTION:
689 action = Contact::journal_action(value.toInt()); 691 action = Contact::journal_action(value.toInt());
690 break; 692 break;
691 case JOURNALROW: 693 case JOURNALROW:
692 journalKey = value.toInt(); 694 journalKey = value.toInt();
693 break; 695 break;
694 696
695 default: 697 default:
696 cnt->insert( *find, value ); 698 cnt->insert( *find, value );
697 break; 699 break;
698 } 700 }
699#endif 701#endif
700 } 702 }
701 703
702 // sadly we can't delay adding of items from the journal to get 704 // sadly we can't delay adding of items from the journal to get
703 // the proper effect, but then, the journal should _never_ be 705 // the proper effect, but then, the journal should _never_ be
704 // that huge, and recovering from a crash is not necessarily 706 // that huge, and recovering from a crash is not necessarily
705 // a *fast* thing. 707 // a *fast* thing.
706 switch ( action ) { 708 switch ( action ) {
707 case Contact::ACTION_ADD: 709 case Contact::ACTION_ADD:
708 if ( journalFile ) { 710 if ( journalFile ) {
709 int myrows = numRows(); 711 int myrows = numRows();
710 setNumRows( myrows + 1 ); 712 setNumRows( myrows + 1 );
711 insertIntoTable( *cnt, myrows ); 713 insertIntoTable( *cnt, myrows );
712 delete cnt; 714 delete cnt;
713 } 715 }
714 else 716 else
715 list.append( cnt ); 717 list.append( cnt );
716 break; 718 break;
717 case Contact::ACTION_REMOVE: 719 case Contact::ACTION_REMOVE:
718 // yup, we don't use the entry to remove the object... 720 // yup, we don't use the entry to remove the object...
719 journalFreeRemove( journalKey ); 721 journalFreeRemove( journalKey );
720 delete cnt; 722 delete cnt;
721 break; 723 break;
722 case Contact::ACTION_REPLACE: 724 case Contact::ACTION_REPLACE:
723 journalFreeReplace( *cnt, journalKey ); 725 journalFreeReplace( *cnt, journalKey );
724 delete cnt; 726 delete cnt;
725 break; 727 break;
726 default: 728 default:
727 break; 729 break;
728 } 730 }
729 num++; 731 num++;
730 foundAction = false; 732 foundAction = false;
731 foundKey = false; 733 foundKey = false;
732 // if ( num % 100 == 0 ) { 734 // if ( num % 100 == 0 ) {
733 // qDebug("loading file, num=%d, t=%d", num, t.elapsed() ); 735 // qDebug("loading file, num=%d, t=%d", num, t.elapsed() );
734 // } 736 // }
735 } 737 }
736 if ( list.count() > 0 ) { 738 if ( list.count() > 0 ) {
737 internalAddEntries( list ); 739 internalAddEntries( list );
738 } 740 }
739// qDebug("done loading %d, t=%d", num, t.elapsed() ); 741// qDebug("done loading %d, t=%d", num, t.elapsed() );
740 742
741} 743}
742 744
743void AbTable::realignTable( int row ) 745void AbTable::realignTable( int row )
744{ 746{
745 QTableItem *ti1, 747 QTableItem *ti1,
746 *ti2; 748 *ti2;
747 int totalRows = numRows(); 749 int totalRows = numRows();
748 for ( int curr = row; curr < totalRows - 1; curr++ ) { 750 for ( int curr = row; curr < totalRows - 1; curr++ ) {
749 // the same info from the todo list still applies, but I 751 // the same info from the todo list still applies, but I
750 // don't think it is _too_ bad. 752 // don't think it is _too_ bad.
751 ti1 = item( curr + 1, 0 ); 753 ti1 = item( curr + 1, 0 );
752 ti2 = item( curr + 1, 1 ); 754 ti2 = item( curr + 1, 1 );
753 takeItem( ti1 ); 755 takeItem( ti1 );
754 takeItem( ti2 ); 756 takeItem( ti2 );
755 setItem( curr, 0, ti1 ); 757 setItem( curr, 0, ti1 );
756 setItem( curr, 1, ti2 ); 758 setItem( curr, 1, ti2 );
757 } 759 }
758 setNumRows( totalRows - 1 ); 760 setNumRows( totalRows - 1 );
759 resort(); 761 resort();
760} 762}
761 763
762void AbTable::insertIntoTable( const Contact &cnt, int row ) 764void AbTable::insertIntoTable( const Contact &cnt, int row )
763{ 765{
764 QString strName, 766 QString strName,
765 strContact; 767 strContact;
766 768
767 strName = findContactName( cnt ); 769 strName = findContactName( cnt );
768 strContact = findContactContact( cnt ); 770 strContact = findContactContact( cnt );
769 771
770 AbTableItem *ati; 772 AbTableItem *ati;
771 ati = new AbTableItem( this, QTableItem::Never, strName, strContact); 773 ati = new AbTableItem( this, QTableItem::Never, strName, strContact);
772 contactList.insert( ati, cnt ); 774 contactList.insert( ati, cnt );
773 setItem( row, 0, ati ); 775 setItem( row, 0, ati );
774 ati = new AbTableItem( this, QTableItem::Never, strContact, strName); 776 ati = new AbTableItem( this, QTableItem::Never, strContact, strName);
775 setItem( row, 1, ati ); 777 setItem( row, 1, ati );
776 778
777 //### cannot do this; table only has two columns at this point 779 //### cannot do this; table only has two columns at this point
778 // setItem( row, 2, new AbPickItem( this ) ); 780 // setItem( row, 2, new AbPickItem( this ) );
779 781
780 // resort at some point? 782 // resort at some point?
781} 783}
782 784
783void AbTable::internalAddEntries( QList<Contact> &list ) 785void AbTable::internalAddEntries( QList<Contact> &list )
784{ 786{
785 setUpdatesEnabled( FALSE ); 787 setUpdatesEnabled( FALSE );
786 setNumRows( list.count() ); 788 setNumRows( list.count() );
787 int row = 0; 789 int row = 0;
788 Contact *it; 790 Contact *it;
789 for ( it = list.first(); it; it = list.next() ) 791 for ( it = list.first(); it; it = list.next() )
790 insertIntoTable( *it, row++ ); 792 insertIntoTable( *it, row++ );
791 resort(); 793 resort();
792 setUpdatesEnabled( TRUE ); 794 setUpdatesEnabled( TRUE );
793} 795}
794 796
795 797
796void AbTable::journalFreeReplace( const Contact &cnt, int row ) 798void AbTable::journalFreeReplace( const Contact &cnt, int row )
797{ 799{
798 QString strName, 800 QString strName,
799 strContact; 801 strContact;
800 AbTableItem *ati; 802 AbTableItem *ati = 0l;
801 803
802 strName = findContactName( cnt ); 804 strName = findContactName( cnt );
803 strContact = findContactContact( cnt ); 805 strContact = findContactContact( cnt );
804 ati = static_cast<AbTableItem*>(item(row, 0)); 806 ati = static_cast<AbTableItem*>(item(row, 0));
805 contactList.remove( ati ); 807 if ( ati != 0 ) {
806 ati->setItem( strName, strContact ); 808 contactList.remove( ati );
807 contactList.insert( ati, cnt ); 809 ati->setItem( strName, strContact );
808 810 contactList.insert( ati, cnt );
809 ati = static_cast<AbTableItem*>(item(row, 1)); 811
810 ati->setItem( strContact, strName ); 812 ati = static_cast<AbTableItem*>(item(row, 1));
813 ati->setItem( strContact, strName );
814 }else{
815 int myrows = numRows();
816 setNumRows( myrows + 1 );
817 insertIntoTable( cnt, myrows );
818 // gets deleted when returning
819 }
811} 820}
812 821
813void AbTable::journalFreeRemove( int row ) 822void AbTable::journalFreeRemove( int row )
814{ 823{
815 AbTableItem *ati; 824 AbTableItem *ati;
816 ati = static_cast<AbTableItem*>(item(row, 0)); 825 ati = static_cast<AbTableItem*>(item(row, 0));
817 if ( !ati ) 826 if ( !ati )
818 return; 827 return;
819 contactList.remove( ati ); 828 contactList.remove( ati );
820 realignTable( row ); 829 realignTable( row );
821} 830}
822 831
823#if QT_VERSION <= 230 832#if QT_VERSION <= 230
824#ifndef SINGLE_APP 833#ifndef SINGLE_APP
825void QTable::paintEmptyArea( QPainter *p, int cx, int cy, int cw, int ch ) 834void QTable::paintEmptyArea( QPainter *p, int cx, int cy, int cw, int ch )
826{ 835{
827 // Region of the rect we should draw 836 // Region of the rect we should draw
828 QRegion reg( QRect( cx, cy, cw, ch ) ); 837 QRegion reg( QRect( cx, cy, cw, ch ) );
829 // Subtract the table from it 838 // Subtract the table from it
830 reg = reg.subtract( QRect( QPoint( 0, 0 ), tableSize() ) ); 839 reg = reg.subtract( QRect( QPoint( 0, 0 ), tableSize() ) );
831 // And draw the rectangles (transformed as needed) 840 // And draw the rectangles (transformed as needed)
832 QArray<QRect> r = reg.rects(); 841 QArray<QRect> r = reg.rects();
833 for (unsigned int i=0; i<r.count(); i++) 842 for (unsigned int i=0; i<r.count(); i++)
834 p->fillRect( r[i], colorGroup().brush( QColorGroup::Base ) ); 843 p->fillRect( r[i], colorGroup().brush( QColorGroup::Base ) );
835} 844}
836#endif 845#endif
837#endif 846#endif
838 847
839 848
840// int AbTable::rowHeight( int ) const 849// int AbTable::rowHeight( int ) const
841// { 850// {
842// return 18; 851// return 18;
843// } 852// }
844 853
845// int AbTable::rowPos( int row ) const 854// int AbTable::rowPos( int row ) const
846// { 855// {
847// return 18*row; 856// return 18*row;
848// } 857// }
849 858
850// int AbTable::rowAt( int pos ) const 859// int AbTable::rowAt( int pos ) const
851// { 860// {
852// return QMIN( pos/18, numRows()-1 ); 861// return QMIN( pos/18, numRows()-1 );
853// } 862// }
854 863
855void AbTable::slotDoFind( const QString &findString, bool caseSensitive, 864void AbTable::slotDoFind( const QString &findString, bool caseSensitive,
856 bool backwards, int category ) 865 bool backwards, int category )
857{ 866{
858 if ( currFindRow < -1 ) 867 if ( currFindRow < -1 )
859 currFindRow = currentRow() - 1; 868 currFindRow = currentRow() - 1;
860 clearSelection( TRUE ); 869 clearSelection( TRUE );
861 int rows, 870 int rows,
862 row; 871 row;
863 AbTableItem *ati; 872 AbTableItem *ati;
864 QRegExp r( findString ); 873 QRegExp r( findString );
865 r.setCaseSensitive( caseSensitive ); 874 r.setCaseSensitive( caseSensitive );
866 rows = numRows(); 875 rows = numRows();
867 static bool wrapAround = true; 876 static bool wrapAround = true;
868 877
869 if ( !backwards ) { 878 if ( !backwards ) {
870 for ( row = currFindRow + 1; row < rows; row++ ) { 879 for ( row = currFindRow + 1; row < rows; row++ ) {
871 ati = static_cast<AbTableItem*>( item(row, 0) ); 880 ati = static_cast<AbTableItem*>( item(row, 0) );
872 if ( contactCompare( contactList[ati], r, category ) ) 881 if ( contactCompare( contactList[ati], r, category ) )
873 break; 882 break;
874 883
875 } 884 }
876 } else { 885 } else {
877 for ( row = currFindRow - 1; row > -1; row-- ) { 886 for ( row = currFindRow - 1; row > -1; row-- ) {
878 ati = static_cast<AbTableItem*>( item(row, 0) ); 887 ati = static_cast<AbTableItem*>( item(row, 0) );
879 if ( contactCompare( contactList[ati], r, category ) ) 888 if ( contactCompare( contactList[ati], r, category ) )
880 break; 889 break;
881 } 890 }
882 } 891 }
883 if ( row >= rows || row < 0 ) { 892 if ( row >= rows || row < 0 ) {
884 if ( row < 0 ) 893 if ( row < 0 )
885 currFindRow = rows; 894 currFindRow = rows;
886 else 895 else
887 currFindRow = -1; 896 currFindRow = -1;
888 897
889 if ( wrapAround ) 898 if ( wrapAround )
890 emit signalWrapAround(); 899 emit signalWrapAround();
891 else 900 else
892 emit signalNotFound(); 901 emit signalNotFound();
893 902
894 wrapAround = !wrapAround; 903 wrapAround = !wrapAround;
895 } else { 904 } else {
896 currFindRow = row; 905 currFindRow = row;
897 QTableSelection foundSelection; 906 QTableSelection foundSelection;
898 foundSelection.init( currFindRow, 0 ); 907 foundSelection.init( currFindRow, 0 );
899 foundSelection.expandTo( currFindRow, numCols() - 1 ); 908 foundSelection.expandTo( currFindRow, numCols() - 1 );
900 addSelection( foundSelection ); 909 addSelection( foundSelection );
901 setCurrentCell( currFindRow, numCols() - 1 ); 910 setCurrentCell( currFindRow, numCols() - 1 );
902 wrapAround = true; 911 wrapAround = true;
903 } 912 }
904} 913}
905 914
906static bool contactCompare( const Contact &cnt, const QRegExp &r, int category ) 915static bool contactCompare( const Contact &cnt, const QRegExp &r, int category )
907{ 916{
908 bool returnMe; 917 bool returnMe;
909 QArray<int> cats; 918 QArray<int> cats;
910 cats = cnt.categories(); 919 cats = cnt.categories();
911 920
912 returnMe = false; 921 returnMe = false;
913 if ( (category == -1 && cats.count() == 0) || category == -2 ) 922 if ( (category == -1 && cats.count() == 0) || category == -2 )
914 returnMe = cnt.match( r ); 923 returnMe = cnt.match( r );
915 else { 924 else {
916 int i; 925 int i;
917 for ( i = 0; i < int(cats.count()); i++ ) { 926 for ( i = 0; i < int(cats.count()); i++ ) {
918 if ( cats[i] == category ) { 927 if ( cats[i] == category ) {
919 returnMe = cnt.match( r ); 928 returnMe = cnt.match( r );
920 break; 929 break;
921 } 930 }
922 } 931 }
923 } 932 }
924 return returnMe; 933 return returnMe;
925} 934}
926 935
927void AbTable::fitColumns() 936void AbTable::fitColumns()
928{ 937{
929 int contentsWidth = visibleWidth(); 938 int contentsWidth = visibleWidth();
930 int n = numCols(); 939 int n = numCols();
931 int pw = n == 3 ? columnWidth(2) : 0; 940 int pw = n == 3 ? columnWidth(2) : 0;
932 setColumnWidth( 0, contentsWidth - contentsWidth / 2 ); 941 setColumnWidth( 0, contentsWidth - contentsWidth / 2 );
933 setColumnWidth( 1, contentsWidth / 2 - pw ); 942 setColumnWidth( 1, contentsWidth / 2 - pw );
934} 943}
935 944
936void AbTable::show() 945void AbTable::show()
937{ 946{
938 fitColumns(); 947 fitColumns();
@@ -958,244 +967,244 @@ void AbTable::itemClicked(int,int col)
958{ 967{
959 if ( col == 2 ) { 968 if ( col == 2 ) {
960 return; 969 return;
961 } else { 970 } else {
962 emit details(); 971 emit details();
963 } 972 }
964} 973}
965 974
966QStringList AbTable::choiceNames() const 975QStringList AbTable::choiceNames() const
967{ 976{
968 return choicenames; 977 return choicenames;
969} 978}
970 979
971void AbTable::setChoiceSelection(int /*index*/, const QStringList& /*list*/) 980void AbTable::setChoiceSelection(int /*index*/, const QStringList& /*list*/)
972{ 981{
973 /* ###### 982 /* ######
974 983
975 QString selname = choicenames.at(index); 984 QString selname = choicenames.at(index);
976 for (each row) { 985 for (each row) {
977 Contact *c = contactForRow(row); 986 Contact *c = contactForRow(row);
978 if ( list.contains(c->email) ) { 987 if ( list.contains(c->email) ) {
979 list.remove(c->email); 988 list.remove(c->email);
980 setText(row, 2, selname); 989 setText(row, 2, selname);
981 } 990 }
982 } 991 }
983 for (remaining list items) { 992 for (remaining list items) {
984 Contact *c = new contact(item); 993 Contact *c = new contact(item);
985 setText(newrow, 2, selname); 994 setText(newrow, 2, selname);
986 } 995 }
987 996
988 */ 997 */
989} 998}
990 999
991QStringList AbTable::choiceSelection(int /*index*/) const 1000QStringList AbTable::choiceSelection(int /*index*/) const
992{ 1001{
993 QStringList r; 1002 QStringList r;
994 /* ###### 1003 /* ######
995 1004
996 QString selname = choicenames.at(index); 1005 QString selname = choicenames.at(index);
997 for (each row) { 1006 for (each row) {
998 Contact *c = contactForRow(row); 1007 Contact *c = contactForRow(row);
999 if ( text(row,2) == selname ) { 1008 if ( text(row,2) == selname ) {
1000 r.append(c->email); 1009 r.append(c->email);
1001 } 1010 }
1002 } 1011 }
1003 1012
1004 */ 1013 */
1005 return r; 1014 return r;
1006} 1015}
1007 1016
1008void AbTable::setShowCategory( const QString &c ) 1017void AbTable::setShowCategory( const QString &c )
1009{ 1018{
1010 showCat = c; 1019 showCat = c;
1011 updateVisible(); 1020 updateVisible();
1012} 1021}
1013 1022
1014void AbTable::setShowByLetter( char c ) 1023void AbTable::setShowByLetter( char c )
1015{ 1024{
1016 showChar = tolower(c); 1025 showChar = tolower(c);
1017 updateVisible(); 1026 updateVisible();
1018} 1027}
1019 1028
1020QString AbTable::showCategory() const 1029QString AbTable::showCategory() const
1021{ 1030{
1022 return showCat; 1031 return showCat;
1023} 1032}
1024 1033
1025 1034
1026QStringList AbTable::categories() 1035QStringList AbTable::categories()
1027{ 1036{
1028 mCat.load( categoryFileName() ); 1037 mCat.load( categoryFileName() );
1029 QStringList categoryList = mCat.labels( "Contacts" ); 1038 QStringList categoryList = mCat.labels( "Contacts" );
1030 return categoryList; 1039 return categoryList;
1031} 1040}
1032 1041
1033void AbTable::updateVisible() 1042void AbTable::updateVisible()
1034{ 1043{
1035 int visible, 1044 int visible,
1036 totalRows, 1045 totalRows,
1037 id, 1046 id,
1038 totalCats, 1047 totalCats,
1039 it, 1048 it,
1040 row; 1049 row;
1041 bool hide; 1050 bool hide;
1042 AbTableItem *ati; 1051 AbTableItem *ati;
1043 Contact *cnt; 1052 Contact *cnt;
1044 QString fileAsName; 1053 QString fileAsName;
1045 QString tmpStr; 1054 QString tmpStr;
1046 visible = 0; 1055 visible = 0;
1047 1056
1048 setPaintingEnabled( FALSE ); 1057 setPaintingEnabled( FALSE );
1049 1058
1050 totalRows = numRows(); 1059 totalRows = numRows();
1051 id = mCat.id( "Contacts", showCat ); 1060 id = mCat.id( "Contacts", showCat );
1052 QArray<int> cats; 1061 QArray<int> cats;
1053 for ( row = 0; row < totalRows; row++ ) { 1062 for ( row = 0; row < totalRows; row++ ) {
1054 ati = static_cast<AbTableItem*>( item(row, 0) ); 1063 ati = static_cast<AbTableItem*>( item(row, 0) );
1055 cnt = &contactList[ati]; 1064 cnt = &contactList[ati];
1056 cats = cnt->categories(); 1065 cats = cnt->categories();
1057 fileAsName = cnt->fileAs(); 1066 fileAsName = cnt->fileAs();
1058 hide = false; 1067 hide = false;
1059 if ( !showCat.isEmpty() ) { 1068 if ( !showCat.isEmpty() ) {
1060 if ( showCat == tr( "Unfiled" ) ) { 1069 if ( showCat == tr( "Unfiled" ) ) {
1061 if ( cats.count() > 0 ) 1070 if ( cats.count() > 0 )
1062 hide = true; 1071 hide = true;
1063 } else { 1072 } else {
1064 // do some comparing 1073 // do some comparing
1065 if ( !hide ) { 1074 if ( !hide ) {
1066 hide = true; 1075 hide = true;
1067 totalCats = int(cats.count()); 1076 totalCats = int(cats.count());
1068 for ( it = 0; it < totalCats; it++ ) { 1077 for ( it = 0; it < totalCats; it++ ) {
1069 if ( cats[it] == id ) { 1078 if ( cats[it] == id ) {
1070 hide = false; 1079 hide = false;
1071 break; 1080 break;
1072 } 1081 }
1073 } 1082 }
1074 } 1083 }
1075 } 1084 }
1076 } 1085 }
1077 if ( showChar != '\0' ) { 1086 if ( showChar != '\0' ) {
1078 tmpStr = fileAsName.left(1); 1087 tmpStr = fileAsName.left(1);
1079 tmpStr = tmpStr.lower(); 1088 tmpStr = tmpStr.lower();
1080 if ( tmpStr != QString(QChar(showChar)) && showChar != '#' ) { 1089 if ( tmpStr != QString(QChar(showChar)) && showChar != '#' ) {
1081 hide = true; 1090 hide = true;
1082 } 1091 }
1083 if ( showChar == '#' ) { 1092 if ( showChar == '#' ) {
1084 if (tmpStr == "a") 1093 if (tmpStr == "a")
1085 hide = true; 1094 hide = true;
1086 1095
1087 if (tmpStr == "b") 1096 if (tmpStr == "b")
1088 hide = true; 1097 hide = true;
1089 1098
1090 if (tmpStr == "c") 1099 if (tmpStr == "c")
1091 hide = true; 1100 hide = true;
1092 1101
1093 if (tmpStr == "d") 1102 if (tmpStr == "d")
1094 hide = true; 1103 hide = true;
1095 1104
1096 if (tmpStr == "e") 1105 if (tmpStr == "e")
1097 hide = true; 1106 hide = true;
1098 1107
1099 if (tmpStr == "f") 1108 if (tmpStr == "f")
1100 hide = true; 1109 hide = true;
1101 1110
1102 if (tmpStr == "g") 1111 if (tmpStr == "g")
1103 hide = true; 1112 hide = true;
1104 1113
1105 if (tmpStr == "h") 1114 if (tmpStr == "h")
1106 hide = true; 1115 hide = true;
1107 1116
1108 if (tmpStr == "i") 1117 if (tmpStr == "i")
1109 hide = true; 1118 hide = true;
1110 1119
1111 if (tmpStr == "j") 1120 if (tmpStr == "j")
1112 hide = true; 1121 hide = true;
1113 1122
1114 if (tmpStr == "k") 1123 if (tmpStr == "k")
1115 hide = true; 1124 hide = true;
1116 1125
1117 if (tmpStr == "l") 1126 if (tmpStr == "l")
1118 hide = true; 1127 hide = true;
1119 1128
1120 if (tmpStr == "m") 1129 if (tmpStr == "m")
1121 hide = true; 1130 hide = true;
1122 1131
1123 if (tmpStr == "n") 1132 if (tmpStr == "n")
1124 hide = true; 1133 hide = true;
1125 1134
1126 if (tmpStr == "o") 1135 if (tmpStr == "o")
1127 hide = true; 1136 hide = true;
1128 1137
1129 if (tmpStr == "p") 1138 if (tmpStr == "p")
1130 hide = true; 1139 hide = true;
1131 1140
1132 if (tmpStr == "q") 1141 if (tmpStr == "q")
1133 hide = true; 1142 hide = true;
1134 1143
1135 if (tmpStr == "r") 1144 if (tmpStr == "r")
1136 hide = true; 1145 hide = true;
1137 1146
1138 if (tmpStr == "s") 1147 if (tmpStr == "s")
1139 hide = true; 1148 hide = true;
1140 1149
1141 if (tmpStr == "t") 1150 if (tmpStr == "t")
1142 hide = true; 1151 hide = true;
1143 1152
1144 if (tmpStr == "u") 1153 if (tmpStr == "u")
1145 hide = true; 1154 hide = true;
1146 1155
1147 if (tmpStr == "v") 1156 if (tmpStr == "v")
1148 hide = true; 1157 hide = true;
1149 1158
1150 if (tmpStr == "w") 1159 if (tmpStr == "w")
1151 hide = true; 1160 hide = true;
1152 1161
1153 if (tmpStr == "x") 1162 if (tmpStr == "x")
1154 hide = true; 1163 hide = true;
1155 1164
1156 if (tmpStr == "y") 1165 if (tmpStr == "y")
1157 hide = true; 1166 hide = true;
1158 1167
1159 if (tmpStr == "z") 1168 if (tmpStr == "z")
1160 hide = true; 1169 hide = true;
1161 } 1170 }
1162 1171
1163 } 1172 }
1164 if ( hide ) { 1173 if ( hide ) {
1165 if ( currentRow() == row ) 1174 if ( currentRow() == row )
1166 setCurrentCell( -1, 0 ); 1175 setCurrentCell( -1, 0 );
1167 if ( rowHeight(row) > 0 ) 1176 if ( rowHeight(row) > 0 )
1168 hideRow( row ); 1177 hideRow( row );
1169 } else { 1178 } else {
1170 if ( rowHeight(row) == 0 ) { 1179 if ( rowHeight(row) == 0 ) {
1171 showRow( row ); 1180 showRow( row );
1172 adjustRow( row ); 1181 adjustRow( row );
1173 } 1182 }
1174 visible++; 1183 visible++;
1175 } 1184 }
1176 } 1185 }
1177 if ( !visible ) 1186 if ( !visible )
1178 setCurrentCell( -1, 0 ); 1187 setCurrentCell( -1, 0 );
1179 1188
1180 setPaintingEnabled( TRUE ); 1189 setPaintingEnabled( TRUE );
1181} 1190}
1182 1191
1183 1192
1184void AbTable::setPaintingEnabled( bool e ) 1193void AbTable::setPaintingEnabled( bool e )
1185{ 1194{
1186 if ( e != enablePainting ) { 1195 if ( e != enablePainting ) {
1187 if ( !enablePainting ) { 1196 if ( !enablePainting ) {
1188 enablePainting = true; 1197 enablePainting = true;
1189 rowHeightChanged( 0 ); 1198 rowHeightChanged( 0 );
1190 viewport()->update(); 1199 viewport()->update();
1191 } else { 1200 } else {
1192 enablePainting = false; 1201 enablePainting = false;
1193 } 1202 }
1194 } 1203 }
1195} 1204}
1196 1205
1197void AbTable::rowHeightChanged( int row ) 1206void AbTable::rowHeightChanged( int row )
1198{ 1207{
1199 if ( enablePainting ) 1208 if ( enablePainting )
1200 QTable::rowHeightChanged( row ); 1209 QTable::rowHeightChanged( row );
1201} 1210}