author | zautrix <zautrix> | 2004-09-19 09:00:55 (UTC) |
---|---|---|
committer | zautrix <zautrix> | 2004-09-19 09:00:55 (UTC) |
commit | 787181d34f0d195ad72c9cf6aedbc317b6dd713e (patch) (unidiff) | |
tree | ac49d2b1d7887f96f3834458071b89e77b59218b /kaddressbook | |
parent | f370d0f89bcaeeb68bd60152a9812a9cd55e5d8a (diff) | |
download | kdepimpi-787181d34f0d195ad72c9cf6aedbc317b6dd713e.zip kdepimpi-787181d34f0d195ad72c9cf6aedbc317b6dd713e.tar.gz kdepimpi-787181d34f0d195ad72c9cf6aedbc317b6dd713e.tar.bz2 |
more AB sync
-rw-r--r-- | kaddressbook/kabcore.cpp | 27 |
1 files changed, 14 insertions, 13 deletions
diff --git a/kaddressbook/kabcore.cpp b/kaddressbook/kabcore.cpp index 8776b53..56f6af2 100644 --- a/kaddressbook/kabcore.cpp +++ b/kaddressbook/kabcore.cpp | |||
@@ -2513,67 +2513,69 @@ QString KABCore::getPassword( ) | |||
2513 | dia.hide(); | 2513 | dia.hide(); |
2514 | qApp->processEvents(); | 2514 | qApp->processEvents(); |
2515 | return retfile; | 2515 | return retfile; |
2516 | 2516 | ||
2517 | } | 2517 | } |
2518 | #include <libkcal/syncdefines.h> | 2518 | #include <libkcal/syncdefines.h> |
2519 | 2519 | ||
2520 | KABC::Addressee KABCore::getLastSyncAddressee() | 2520 | KABC::Addressee KABCore::getLastSyncAddressee() |
2521 | { | 2521 | { |
2522 | Addressee lse; | 2522 | Addressee lse; |
2523 | //qDebug("CurrentSyncDevice %s ",mCurrentSyncDevice .latin1() ); | 2523 | //qDebug("CurrentSyncDevice %s ",mCurrentSyncDevice .latin1() ); |
2524 | lse = mAddressBook->findByUid( "last-syncAddressee-"+mCurrentSyncDevice ); | 2524 | lse = mAddressBook->findByUid( "last-syncAddressee-"+mCurrentSyncDevice ); |
2525 | if (lse.isEmpty()) { | 2525 | if (lse.isEmpty()) { |
2526 | qDebug("Creating new last-syncAddressee "); | 2526 | qDebug("Creating new last-syncAddressee "); |
2527 | lse.setUid( "last-syncAddressee-"+mCurrentSyncDevice ); | 2527 | lse.setUid( "last-syncAddressee-"+mCurrentSyncDevice ); |
2528 | QString sum = ""; | 2528 | QString sum = ""; |
2529 | if ( KABPrefs::instance()->mExternSyncProfiles.contains( mCurrentSyncDevice ) ) | 2529 | if ( mGlobalSyncMode == SYNC_MODE_EXTERNAL ) |
2530 | sum = "E: "; | 2530 | sum = "E: "; |
2531 | lse.setFamilyName("!"+sum+mCurrentSyncDevice + i18n(" - sync event")); | 2531 | lse.setFamilyName("!"+sum+mCurrentSyncDevice + i18n(" - sync event")); |
2532 | lse.setRevision( mLastAddressbookSync ); | 2532 | lse.setRevision( mLastAddressbookSync ); |
2533 | lse.setCategories( i18n("SyncEvent") ); | 2533 | lse.setCategories( i18n("SyncEvent") ); |
2534 | mAddressBook->insertAddressee( lse ); | 2534 | mAddressBook->insertAddressee( lse ); |
2535 | } | 2535 | } |
2536 | return lse; | 2536 | return lse; |
2537 | } | 2537 | } |
2538 | int KABCore::takeAddressee( KABC::Addressee* local, KABC::Addressee* remote, int mode , bool full ) | 2538 | int KABCore::takeAddressee( KABC::Addressee* local, KABC::Addressee* remote, int mode , bool full ) |
2539 | { | 2539 | { |
2540 | 2540 | ||
2541 | //void setZaurusId(int id); | 2541 | //void setZaurusId(int id); |
2542 | // int zaurusId() const; | 2542 | // int zaurusId() const; |
2543 | // void setZaurusUid(int id); | 2543 | // void setZaurusUid(int id); |
2544 | // int zaurusUid() const; | 2544 | // int zaurusUid() const; |
2545 | // void setZaurusStat(int id); | 2545 | // void setZaurusStat(int id); |
2546 | // int zaurusStat() const; | 2546 | // int zaurusStat() const; |
2547 | // 0 equal | 2547 | // 0 equal |
2548 | // 1 take local | 2548 | // 1 take local |
2549 | // 2 take remote | 2549 | // 2 take remote |
2550 | // 3 cancel | 2550 | // 3 cancel |
2551 | QDateTime lastSync = mLastAddressbookSync; | 2551 | QDateTime lastSync = mLastAddressbookSync; |
2552 | if ( mGlobalSyncMode == SYNC_MODE_EXTERNAL ) { | 2552 | if ( mGlobalSyncMode == SYNC_MODE_EXTERNAL ) { |
2553 | bool remCh, locCh; | 2553 | bool remCh, locCh; |
2554 | remCh = ( remote->getCsum(mCurrentSyncDevice) != local->getCsum(mCurrentSyncDevice) ); | 2554 | remCh = ( remote->getCsum(mCurrentSyncDevice) != local->getCsum(mCurrentSyncDevice) ); |
2555 | //if ( remCh ) | 2555 | if ( remCh ) |
2556 | //qDebug("loc %s rem %s", local->getCsum(mCurrentSyncDevice).latin1(), remote->getCsum(mCurrentSyncDevice).latin1() ); | 2556 | qDebug("loc %s rem %s", local->getCsum(mCurrentSyncDevice).latin1(), remote->getCsum(mCurrentSyncDevice).latin1() ); |
2557 | locCh = ( local->revision() > mLastAddressbookSync ); | 2557 | locCh = ( local->revision() > mLastAddressbookSync ); |
2558 | if ( !remCh && ! locCh ) { | 2558 | if ( !remCh && ! locCh ) { |
2559 | //qDebug("both not changed "); | 2559 | qDebug("both not changed "); |
2560 | lastSync = local->revision().addDays(1); | 2560 | lastSync = local->revision().addDays(1); |
2561 | if ( mode <= SYNC_PREF_ASK ) | ||
2562 | return 0; | ||
2561 | } else { | 2563 | } else { |
2562 | if ( locCh ) { | 2564 | if ( locCh ) { |
2563 | //qDebug("loc changed %d %s %s", local->revision() , local->lastModified().toString().latin1(), mLastCalendarSync.toString().latin1()); | 2565 | qDebug("loc changed %s %s", local->revision().toString().latin1(), mLastAddressbookSync.toString().latin1()); |
2564 | lastSync = local->revision().addDays( -1 ); | 2566 | lastSync = local->revision().addDays( -1 ); |
2565 | if ( !remCh ) | 2567 | if ( !remCh ) |
2566 | remote->setRevision( lastSync.addDays( -1 ) ); | 2568 | remote->setRevision( lastSync.addDays( -1 ) ); |
2567 | } else { | 2569 | } else { |
2568 | //qDebug(" not loc changed "); | 2570 | //qDebug(" not loc changed "); |
2569 | lastSync = local->revision().addDays( 1 ); | 2571 | lastSync = local->revision().addDays( 1 ); |
2570 | if ( remCh ) | 2572 | if ( remCh ) |
2571 | remote->setRevision( lastSync.addDays( 1 ) ); | 2573 | remote->setRevision( lastSync.addDays( 1 ) ); |
2572 | 2574 | ||
2573 | } | 2575 | } |
2574 | } | 2576 | } |
2575 | full = true; | 2577 | full = true; |
2576 | if ( mode < SYNC_PREF_ASK ) | 2578 | if ( mode < SYNC_PREF_ASK ) |
2577 | mode = SYNC_PREF_ASK; | 2579 | mode = SYNC_PREF_ASK; |
2578 | } else { | 2580 | } else { |
2579 | if ( local->revision() == remote->revision() ) | 2581 | if ( local->revision() == remote->revision() ) |
@@ -2777,95 +2779,91 @@ bool KABCore::synchronizeAddressbooks( KABC::AddressBook* local, KABC::AddressBo | |||
2777 | inR.setResource( 0 ); | 2779 | inR.setResource( 0 ); |
2778 | remote->insertAddressee( inR , false); | 2780 | remote->insertAddressee( inR , false); |
2779 | ++changedRemote; | 2781 | ++changedRemote; |
2780 | } else { | 2782 | } else { |
2781 | idS = inL.IDStr(); | 2783 | idS = inL.IDStr(); |
2782 | local->removeAddressee( inL ); | 2784 | local->removeAddressee( inL ); |
2783 | inL = inR; | 2785 | inL = inR; |
2784 | inL.setIDStr( idS ); | 2786 | inL.setIDStr( idS ); |
2785 | inL.setResource( 0 ); | 2787 | inL.setResource( 0 ); |
2786 | local->insertAddressee( inL , false ); | 2788 | local->insertAddressee( inL , false ); |
2787 | ++changedLocal; | 2789 | ++changedLocal; |
2788 | } | 2790 | } |
2789 | } | 2791 | } |
2790 | } else { // no conflict | 2792 | } else { // no conflict |
2791 | if ( mGlobalSyncMode == SYNC_MODE_EXTERNAL ) { | 2793 | if ( mGlobalSyncMode == SYNC_MODE_EXTERNAL ) { |
2792 | QString des = addresseeLSync.note(); | 2794 | QString des = addresseeLSync.note(); |
2793 | QString pref = "a"; | 2795 | if ( des.find( inR.getID(mCurrentSyncDevice) +"," ) >= 0 && mode != 5) { // delete it |
2794 | if ( des.find(pref+ inR.getID(mCurrentSyncDevice) +"," ) >= 0 && mode != 5) { // delete it | ||
2795 | inR.setTempSyncStat( SYNC_TEMPSTATE_DELETE ); | 2796 | inR.setTempSyncStat( SYNC_TEMPSTATE_DELETE ); |
2797 | remote->insertAddressee( inR, false ); | ||
2796 | ++deletedAddresseeR; | 2798 | ++deletedAddresseeR; |
2797 | } else { | 2799 | } else { |
2798 | inR.setRevision( modifiedCalendar ); | 2800 | inR.setRevision( modifiedCalendar ); |
2799 | remote->insertAddressee( inR, false ); | 2801 | remote->insertAddressee( inR, false ); |
2800 | inL = inR; | 2802 | inL = inR; |
2801 | inL.setResource( 0 ); | 2803 | inL.setResource( 0 ); |
2802 | local->insertAddressee( inL , false); | 2804 | local->insertAddressee( inL , false); |
2803 | ++addedAddressee; | 2805 | ++addedAddressee; |
2804 | } | 2806 | } |
2805 | } else { | 2807 | } else { |
2806 | if ( inR.revision() > mLastAddressbookSync || mode == 5 ) { | 2808 | if ( inR.revision() > mLastAddressbookSync || mode == 5 ) { |
2807 | inR.setRevision( modifiedCalendar ); | 2809 | inR.setRevision( modifiedCalendar ); |
2808 | remote->insertAddressee( inR, false ); | 2810 | remote->insertAddressee( inR, false ); |
2809 | inR.setResource( 0 ); | 2811 | inR.setResource( 0 ); |
2810 | local->insertAddressee( inR, false ); | 2812 | local->insertAddressee( inR, false ); |
2811 | ++addedAddressee; | 2813 | ++addedAddressee; |
2812 | } else { | 2814 | } else { |
2813 | // pending checkExternSyncAddressee(addresseeRSyncSharp, inR); | 2815 | // pending checkExternSyncAddressee(addresseeRSyncSharp, inR); |
2814 | remote->removeAddressee( inR ); | 2816 | remote->removeAddressee( inR ); |
2815 | ++deletedAddresseeR; | 2817 | ++deletedAddresseeR; |
2816 | } | 2818 | } |
2817 | } | 2819 | } |
2818 | } | 2820 | } |
2819 | } | 2821 | } |
2820 | ++incCounter; | 2822 | ++incCounter; |
2821 | } | 2823 | } |
2822 | er.clear(); | 2824 | er.clear(); |
2823 | QStringList el = remote->uidList(); | 2825 | QStringList el = local->uidList(); |
2824 | modulo = (el.count()/10)+1; | 2826 | modulo = (el.count()/10)+1; |
2825 | bar.setCaption (i18n("Add / remove addressees") ); | 2827 | bar.setCaption (i18n("Add / remove addressees") ); |
2826 | bar.setTotalSteps ( el.count() ) ; | 2828 | bar.setTotalSteps ( el.count() ) ; |
2827 | bar.show(); | 2829 | bar.show(); |
2828 | incCounter = 0; | 2830 | incCounter = 0; |
2829 | while ( incCounter < el.count()) { | 2831 | while ( incCounter < el.count()) { |
2830 | |||
2831 | qApp->processEvents(); | 2832 | qApp->processEvents(); |
2832 | if ( ! bar.isVisible() ) | 2833 | if ( ! bar.isVisible() ) |
2833 | return false; | 2834 | return false; |
2834 | if ( incCounter % modulo == 0 ) | 2835 | if ( incCounter % modulo == 0 ) |
2835 | bar.setProgress( incCounter ); | 2836 | bar.setProgress( incCounter ); |
2836 | uid = el[ incCounter ]; | 2837 | uid = el[ incCounter ]; |
2837 | bool skipIncidence = false; | 2838 | bool skipIncidence = false; |
2838 | if ( uid.left(19) == QString("last-syncAddressee-") ) | 2839 | if ( uid.left(19) == QString("last-syncAddressee-") ) |
2839 | skipIncidence = true; | 2840 | skipIncidence = true; |
2840 | if ( mGlobalSyncMode == SYNC_MODE_EXTERNAL ) | ||
2841 | skipIncidence = true; | ||
2842 | if ( !skipIncidence ) { | 2841 | if ( !skipIncidence ) { |
2843 | inL = local->findByUid( uid ); | 2842 | inL = local->findByUid( uid ); |
2844 | inR = remote->findByUid( uid ); | 2843 | inR = remote->findByUid( uid ); |
2845 | if ( inR.isEmpty() ) { | 2844 | if ( inR.isEmpty() ) { |
2846 | if ( mGlobalSyncMode == SYNC_MODE_EXTERNAL ) { | 2845 | if ( mGlobalSyncMode == SYNC_MODE_EXTERNAL ) { |
2847 | if ( !inL.getID(mCurrentSyncDevice).isEmpty() && mode != 4 ) { | 2846 | if ( !inL.getID(mCurrentSyncDevice).isEmpty() && mode != 4 ) { |
2848 | // pending checkExternSyncAddressee(addresseeLSyncSharp, inL); | 2847 | // pending checkExternSyncAddressee(addresseeLSyncSharp, inL); |
2849 | local->removeAddressee( inL ); | 2848 | local->removeAddressee( inL ); |
2850 | ++deletedAddresseeL; | 2849 | ++deletedAddresseeL; |
2851 | } else { | 2850 | } else { |
2852 | if ( ! KABPrefs::instance()->mWriteBackExistingOnly ) { | 2851 | if ( ! KABPrefs::instance()->mWriteBackExistingOnly ) { |
2853 | inL.removeID(mCurrentSyncDevice ); | 2852 | inL.removeID(mCurrentSyncDevice ); |
2854 | ++addedAddresseeR; | 2853 | ++addedAddresseeR; |
2855 | //qDebug("remote added Incidence %s ", inL.summary().latin1()); | ||
2856 | inL.setRevision( modifiedCalendar ); | 2854 | inL.setRevision( modifiedCalendar ); |
2857 | local->insertAddressee( inL, false ); | 2855 | local->insertAddressee( inL, false ); |
2858 | inR = inL; | 2856 | inR = inL; |
2859 | inR.setTempSyncStat( SYNC_TEMPSTATE_INITIAL ); | 2857 | inR.setTempSyncStat( SYNC_TEMPSTATE_INITIAL ); |
2860 | inR.setResource( 0 ); | 2858 | inR.setResource( 0 ); |
2861 | remote->insertAddressee( inR, false ); | 2859 | remote->insertAddressee( inR, false ); |
2862 | } | 2860 | } |
2863 | } | 2861 | } |
2864 | } else { | 2862 | } else { |
2865 | if ( inL.revision() < mLastAddressbookSync && mode != 4 ) { | 2863 | if ( inL.revision() < mLastAddressbookSync && mode != 4 ) { |
2866 | // pending checkExternSyncAddressee(addresseeLSyncSharp, inL); | 2864 | // pending checkExternSyncAddressee(addresseeLSyncSharp, inL); |
2867 | local->removeAddressee( inL ); | 2865 | local->removeAddressee( inL ); |
2868 | ++deletedAddresseeL; | 2866 | ++deletedAddresseeL; |
2869 | } else { | 2867 | } else { |
2870 | if ( ! KABPrefs::instance()->mWriteBackExistingOnly ) { | 2868 | if ( ! KABPrefs::instance()->mWriteBackExistingOnly ) { |
2871 | ++addedAddresseeR; | 2869 | ++addedAddresseeR; |
@@ -2882,32 +2880,34 @@ bool KABCore::synchronizeAddressbooks( KABC::AddressBook* local, KABC::AddressBo | |||
2882 | ++incCounter; | 2880 | ++incCounter; |
2883 | } | 2881 | } |
2884 | el.clear(); | 2882 | el.clear(); |
2885 | bar.hide(); | 2883 | bar.hide(); |
2886 | mLastAddressbookSync = QDateTime::currentDateTime().addSecs( 1 ); | 2884 | mLastAddressbookSync = QDateTime::currentDateTime().addSecs( 1 ); |
2887 | // get rid of micro seconds | 2885 | // get rid of micro seconds |
2888 | QTime t = mLastAddressbookSync.time(); | 2886 | QTime t = mLastAddressbookSync.time(); |
2889 | mLastAddressbookSync.setTime( QTime (t.hour (), t.minute (), t.second () ) ); | 2887 | mLastAddressbookSync.setTime( QTime (t.hour (), t.minute (), t.second () ) ); |
2890 | addresseeLSync.setRevision( mLastAddressbookSync ); | 2888 | addresseeLSync.setRevision( mLastAddressbookSync ); |
2891 | addresseeRSync.setRevision( mLastAddressbookSync ); | 2889 | addresseeRSync.setRevision( mLastAddressbookSync ); |
2892 | addresseeRSync.setRole( i18n("!Remote from: ")+mCurrentSyncName ) ; | 2890 | addresseeRSync.setRole( i18n("!Remote from: ")+mCurrentSyncName ) ; |
2893 | addresseeLSync.setRole(i18n("!Local from: ") + mCurrentSyncName ); | 2891 | addresseeLSync.setRole(i18n("!Local from: ") + mCurrentSyncName ); |
2894 | addresseeRSync.setGivenName( i18n("!DO NOT EDIT!") ) ; | 2892 | addresseeRSync.setGivenName( i18n("!DO NOT EDIT!") ) ; |
2895 | addresseeLSync.setGivenName(i18n("!DO NOT EDIT!") ); | 2893 | addresseeLSync.setGivenName(i18n("!DO NOT EDIT!") ); |
2896 | addresseeRSync.setOrganization( "!"+mLastAddressbookSync.toString() ) ; | 2894 | addresseeRSync.setOrganization( "!"+mLastAddressbookSync.toString() ) ; |
2897 | addresseeLSync.setOrganization("!"+ mLastAddressbookSync.toString() ); | 2895 | addresseeLSync.setOrganization("!"+ mLastAddressbookSync.toString() ); |
2896 | addresseeRSync.setNote( "" ) ; | ||
2897 | addresseeLSync.setNote( "" ); | ||
2898 | 2898 | ||
2899 | if ( mGlobalSyncMode == SYNC_MODE_NORMAL) | 2899 | if ( mGlobalSyncMode == SYNC_MODE_NORMAL) |
2900 | remote->insertAddressee( addresseeRSync, false ); | 2900 | remote->insertAddressee( addresseeRSync, false ); |
2901 | local->insertAddressee( addresseeLSync, false ); | 2901 | local->insertAddressee( addresseeLSync, false ); |
2902 | QString mes; | 2902 | QString mes; |
2903 | mes .sprintf( i18n("Synchronization summary:\n\n %d items added to local\n %d items added to remote\n %d items updated on local\n %d items updated on remote\n %d items deleted on local\n %d items deleted on remote\n"),addedAddressee, addedAddresseeR, changedLocal, changedRemote, deletedAddresseeL, deletedAddresseeR ); | 2903 | mes .sprintf( i18n("Synchronization summary:\n\n %d items added to local\n %d items added to remote\n %d items updated on local\n %d items updated on remote\n %d items deleted on local\n %d items deleted on remote\n"),addedAddressee, addedAddresseeR, changedLocal, changedRemote, deletedAddresseeL, deletedAddresseeR ); |
2904 | if ( KABPrefs::instance()->mShowSyncSummary ) { | 2904 | if ( KABPrefs::instance()->mShowSyncSummary ) { |
2905 | KMessageBox::information(this, mes, i18n("KA/Pi Synchronization") ); | 2905 | KMessageBox::information(this, mes, i18n("KA/Pi Synchronization") ); |
2906 | } | 2906 | } |
2907 | qDebug( mes ); | 2907 | qDebug( mes ); |
2908 | return syncOK; | 2908 | return syncOK; |
2909 | } | 2909 | } |
2910 | 2910 | ||
2911 | bool KABCore::syncAB(QString filename, int mode) | 2911 | bool KABCore::syncAB(QString filename, int mode) |
2912 | { | 2912 | { |
2913 | 2913 | ||
@@ -2924,32 +2924,33 @@ bool KABCore::syncAB(QString filename, int mode) | |||
2924 | if ( lse.familyName().left(4) == "!E: " ) | 2924 | if ( lse.familyName().left(4) == "!E: " ) |
2925 | external = true; | 2925 | external = true; |
2926 | } else { | 2926 | } else { |
2927 | bool found = false; | 2927 | bool found = false; |
2928 | QDateTime dt( QDate( 2004,1,1)); | 2928 | QDateTime dt( QDate( 2004,1,1)); |
2929 | AddressBook::Iterator it; | 2929 | AddressBook::Iterator it; |
2930 | for ( it = abLocal.begin(); it != abLocal.end(); ++it ) { | 2930 | for ( it = abLocal.begin(); it != abLocal.end(); ++it ) { |
2931 | if ( (*it).revision() != dt ) { | 2931 | if ( (*it).revision() != dt ) { |
2932 | found = true; | 2932 | found = true; |
2933 | break; | 2933 | break; |
2934 | } | 2934 | } |
2935 | } | 2935 | } |
2936 | external = ! found; | 2936 | external = ! found; |
2937 | } | 2937 | } |
2938 | 2938 | ||
2939 | if ( external ) { | 2939 | if ( external ) { |
2940 | qDebug("**********Setting vcf mode to external "); | ||
2940 | mGlobalSyncMode = SYNC_MODE_EXTERNAL; | 2941 | mGlobalSyncMode = SYNC_MODE_EXTERNAL; |
2941 | AddressBook::Iterator it; | 2942 | AddressBook::Iterator it; |
2942 | for ( it = abLocal.begin(); it != abLocal.end(); ++it ) { | 2943 | for ( it = abLocal.begin(); it != abLocal.end(); ++it ) { |
2943 | (*it).setID( mCurrentSyncDevice, (*it).uid() ); | 2944 | (*it).setID( mCurrentSyncDevice, (*it).uid() ); |
2944 | (*it).computeCsum( mCurrentSyncDevice ); | 2945 | (*it).computeCsum( mCurrentSyncDevice ); |
2945 | } | 2946 | } |
2946 | } | 2947 | } |
2947 | //AddressBook::Iterator it; | 2948 | //AddressBook::Iterator it; |
2948 | //QStringList vcards; | 2949 | //QStringList vcards; |
2949 | //for ( it = abLocal.begin(); it != abLocal.end(); ++it ) { | 2950 | //for ( it = abLocal.begin(); it != abLocal.end(); ++it ) { |
2950 | // qDebug("Name %s ", (*it).familyName().latin1()); | 2951 | // qDebug("Name %s ", (*it).familyName().latin1()); |
2951 | //} | 2952 | //} |
2952 | syncOK = synchronizeAddressbooks( mAddressBook, &abLocal, mode ); | 2953 | syncOK = synchronizeAddressbooks( mAddressBook, &abLocal, mode ); |
2953 | if ( syncOK ) { | 2954 | if ( syncOK ) { |
2954 | if ( KABPrefs::instance()->mWriteBackFile ) | 2955 | if ( KABPrefs::instance()->mWriteBackFile ) |
2955 | { | 2956 | { |