Пример #1
0
void AddressEditDialog::saveAddress( KABC::Address &addr )
{
  addr.setLocality( mLocalityEdit->text() );
  addr.setRegion( mRegionEdit->text() );
  addr.setPostalCode( mPostalCodeEdit->text() );
  addr.setCountry( mCountryCombo->currentText() );
  addr.setPostOfficeBox( mPOBoxEdit->text() );
  addr.setStreet( mStreetTextEdit->text() );
  addr.setLabel( mLabel );


  if ( mPreferredCheckBox->isChecked() ) {
    KABC::Address::List::Iterator it;
    for ( it = mAddressList.begin(); it != mAddressList.end(); ++it )
      (*it).setType( (*it).type() & ~( KABC::Address::Pref ) );

    addr.setType( addr.type() | KABC::Address::Pref );
  } else
    addr.setType( addr.type() & ~( KABC::Address::Pref ) );
}
Пример #2
0
KABC::Address VCard21Parser::readAddressFromQStringList(const QStringList &data, const int type)
{
    KABC::Address mAddress;
    mAddress.setType(type);

    if(data.count() > 0)
        mAddress.setPostOfficeBox(data[0]);
    if(data.count() > 1)
        mAddress.setExtended(data[1]);
    if(data.count() > 2)
        mAddress.setStreet(data[2]);
    if(data.count() > 3)
        mAddress.setLocality(data[3]);
    if(data.count() > 4)
        mAddress.setRegion(data[4]);
    if(data.count() > 5)
        mAddress.setPostalCode(data[5]);
    if(data.count() > 6)
        mAddress.setCountry(data[6]);

    return mAddress;
}
Пример #3
0
KABC::AddresseeList GMXXXPort::importContacts( const QString& ) const
{
  KABC::AddresseeList addrList;

  QString fileName = KFileDialog::getOpenFileName( ":xxport_gmx", 
                      GMX_FILESELECTION_STRING, 0 );
  if ( fileName.isEmpty() )
    return addrList;

  QFile file( fileName );
  if ( !file.open( IO_ReadOnly ) ) {
    QString msg = i18n( "<qt>Unable to open <b>%1</b> for reading.</qt>" );
    KMessageBox::error( parentWidget(), msg.arg( fileName ) );
    return addrList;
  }

  QDateTime dt;
  QTextStream gmxStream( &file );
  gmxStream.setEncoding( QTextStream::Latin1 );
  QString line, line2;
  line  = gmxStream.readLine();
  line2 = gmxStream.readLine();
  if (!line.startsWith("AB_ADDRESSES:") || !line2.startsWith("Address_id")) {
	KMessageBox::error( parentWidget(), i18n("%1 is not a GMX address book file.").arg(fileName) );
	return addrList;
  }

  QStringList strList;
  typedef QMap<QString, KABC::Addressee *> AddressMap;
  AddressMap addrMap;

  // "Address_id,Nickname,Firstname,Lastname,Title,Birthday,Comments,Change_date,Status,Address_link_id,Categories"
  line = gmxStream.readLine();
  while (!line.startsWith("####") && !gmxStream.atEnd()) {
    while (1) {
       strList = QStringList::split('#', line, true);
       if (strList.count() >= 11) 
           break;
       line.append('\n');
       line.append(gmxStream.readLine());
    };

    KABC::Addressee *addr = new KABC::Addressee;
    addr->setNickName(strList[1]);
    addr->setGivenName(strList[2]);
    addr->setFamilyName(strList[3]);
    addr->setTitle(strList[4]);

    if (addr->formattedName().isEmpty())
	addr->setFormattedName(addr->realName());

    if (checkDateTime(strList[5],dt)) addr->setBirthday(dt);
    addr->setNote(strList[6]);
    if (checkDateTime(strList[7],dt)) addr->setRevision(dt);
    // addr->setStatus(strList[8]); Status
    // addr->xxx(strList[9]); Address_link_id 
    // addr->setCategory(strList[10]); Categories
    addrMap[strList[0]] = addr;

    line = gmxStream.readLine();
  }

  // now read the address records
  line  = gmxStream.readLine();
  if (!line.startsWith("AB_ADDRESS_RECORDS:")) {
	kdWarning() << "Could not find address records!\n";
	return addrList;
  }
  // Address_id,Record_id,Street,Country,Zipcode,City,Phone,Fax,Mobile,Mobile_type,Email,
  // Homepage,Position,Comments,Record_type_id,Record_type,Company,Department,Change_date,Preferred,Status
  line = gmxStream.readLine();
  line = gmxStream.readLine();

  while (!line.startsWith("####") && !gmxStream.atEnd()) {
    while (1) {
       strList = QStringList::split('#', line, true);
       if (strList.count() >= 21) 
           break;
       line.append('\n');
       line.append(gmxStream.readLine());
    };

    KABC::Addressee *addr = addrMap[strList[0]];
    if (addr) {
	for ( QStringList::Iterator it = strList.begin(); it != strList.end(); ++it )
		*it = (*it).simplifyWhiteSpace();
	// strList[1] = Record_id (numbered item, ignore here)
	int id = strList[14].toInt(); // Record_type_id (0=work,1=home,2=other)
	int type = (id==0) ? KABC::Address::Work : KABC::Address::Home;
	if (!strList[19].isEmpty() && strList[19].toInt()!=0)
		type |= KABC::Address::Pref; // Preferred address (seems to be bitfield for telephone Prefs)
        KABC::Address adr = addr->address(type);
	adr.setStreet(strList[2]);
	adr.setCountry(strList[3]);
	adr.setPostalCode(strList[4]);
	adr.setLocality(strList[5]);
	addr->insertPhoneNumber( KABC::PhoneNumber(strList[6], KABC::PhoneNumber::Home) );
	addr->insertPhoneNumber( KABC::PhoneNumber(strList[7], KABC::PhoneNumber::Fax) );
	int celltype = KABC::PhoneNumber::Cell;
	// strList[9]=Mobile_type // always 0 or -1(default phone).
	if (strList[9].toInt()) celltype |= KABC::PhoneNumber::Pref;
	addr->insertPhoneNumber( KABC::PhoneNumber(strList[8], celltype) );
	addr->insertEmail(strList[10]);
	if (!strList[11].isEmpty()) addr->setUrl(strList[11]);
	if (!strList[12].isEmpty()) addr->setRole(strList[12]);
	// strList[13]=Comments
	// strList[14]=Record_type_id (0,1,2) - see above
	// strList[15]=Record_type (name of this additional record entry)
	if (!strList[16].isEmpty()) addr->setOrganization(strList[16]); // Company
	if (!strList[17].isEmpty()) addr->insertCustom( 
			"KADDRESSBOOK", "X-Department", strList[17]); // Department
        if (checkDateTime(strList[18],dt)) addr->setRevision(dt); // Change_date
	// strList[19]=Preferred (see above)
	// strList[20]=Status (should always be "1")
	addr->insertAddress(adr);
    } else {
	kdWarning() << "unresolved line: " << line << endl;
    }

    line = gmxStream.readLine();
  }

  // now add the addresses to to addrList
  for ( AddressMap::Iterator it = addrMap.begin(); it != addrMap.end(); ++it ) {
     KABC::Addressee *addr = it.data();
     addrList.append(*addr);
     delete addr;
  }

  file.close();
  return addrList;
}
Пример #4
0
static gn_error read_phone_entry_highlevel( int index, const gn_memory_type memtype, KABC::Addressee *a )
{
  gn_phonebook_entry entry;
  QStringList addrlist;
  QString s, country;
  KABC::Address *addr;
  gn_error error;

//  if (index > (memstat.used + memstat.free))
//	return GN_ERR_INVALIDLOCATION;

  error = read_phone_entry( index, memtype, &entry );
  if (error != GN_ERR_NONE)
      return error;

  GNOKII_DEBUG(QString("%1: %2, num=%3, location=%4, group=%5, count=%6\n").arg(index).arg(entry.name)
	.arg(entry.number).arg(entry.location).arg(entry.caller_group).arg(entry.subentries_count));

  // try to split Name into FamilyName and GivenName
  s = QString(entry.name).simplifyWhiteSpace();
  a->setFormattedName(s);
  if (s.find(',')!=-1) {
  	addrlist = QStringList::split(',', s);
	if (addrlist.count()==2) {
		a->setFamilyName(addrlist[0].simplifyWhiteSpace());
		a->setGivenName(addrlist[1].simplifyWhiteSpace());
	  } else
		a->setGivenName(s);
  } else {
  	addrlist = QStringList::split(' ', s);
	  if (addrlist.count()==2) {
		a->setFamilyName(addrlist[1].simplifyWhiteSpace());
		a->setGivenName(addrlist[0].simplifyWhiteSpace());
	  } else
		a->setGivenName(s);
  }

  a->insertCustom(APP, "X_GSM_CALLERGROUP", s.setNum(entry.caller_group));
  a->insertCustom(APP, "X_GSM_STORE_AT", QString("%1_%2").arg(GN_MT_ME).arg(entry.location));

  // set ProductId
  a->setProductId(PhoneProductId);

  // evaluate timestamp (ignore timezone)
  QDateTime datetime;
  if (entry.date.year<1998)
	datetime = QDateTime::currentDateTime();
  else
	datetime = QDateTime( QDate(entry.date.year, entry.date.month, entry.date.day), 
			  QTime(entry.date.hour, entry.date.minute, entry.date.second) );
  GNOKII_DEBUG(QString(" date=%1\n").arg(datetime.toString()));
  a->setRevision(datetime);

  if (!entry.subentries_count)
	a->insertPhoneNumber(KABC::PhoneNumber(entry.number, KABC::PhoneNumber::Work | KABC::PhoneNumber::Pref));

  /* scan sub-entries */
  if (entry.subentries_count)
	 for (int n=0; n<entry.subentries_count; n++) {
		QString s = QString(entry.subentries[n].data.number).simplifyWhiteSpace();
		GNOKII_DEBUG(QString(" Subentry#%1, entry_type=%2, number_type=%3, number=%4\n")
			.arg(n).arg(entry.subentries[n].entry_type)
			.arg(entry.subentries[n].number_type).arg(s));
		if (s.isEmpty())
			continue;
		switch(entry.subentries[n].entry_type) {
		   case GN_PHONEBOOK_ENTRY_Name:
				a->setName(s);
				break;
		   case GN_PHONEBOOK_ENTRY_Email:
				a->insertEmail(s);
				break;
		   case GN_PHONEBOOK_ENTRY_Postal:
				addrlist = QStringList::split(',', s, true);
				addr = new KABC::Address(KABC::Address::Work);
				switch (addrlist.count()) {
				 case 4:	addr->setStreet(addrlist[0].simplifyWhiteSpace());
						addr->setLocality(addrlist[1].simplifyWhiteSpace());
						addr->setPostalCode(addrlist[2].simplifyWhiteSpace());
						country = addrlist[3].simplifyWhiteSpace();
						if (!country.isEmpty())
							addr->setCountry(i18n(country.utf8()));
						break;
				 case 3:	addr->setLocality(addrlist[0].simplifyWhiteSpace());
						addr->setPostalCode(addrlist[1].simplifyWhiteSpace());
						country = addrlist[2].simplifyWhiteSpace();
						if (!country.isEmpty())
							addr->setCountry(i18n(country.utf8()));
						break;
				 default:	addr->setStreet(s.simplifyWhiteSpace());
				}
				a->insertAddress(*addr);
				delete addr;
				break;
		   case GN_PHONEBOOK_ENTRY_Note:
				if (!a->note().isEmpty())
					s = "\n" + s;
				a->setNote(a->note()+s);
				break;
		   case GN_PHONEBOOK_ENTRY_Number:
				enum KABC::PhoneNumber::Types phonetype;
				switch (entry.subentries[n].number_type) {
				 case GN_PHONEBOOK_NUMBER_Mobile: phonetype = KABC::PhoneNumber::Cell; break;
				 case GN_PHONEBOOK_NUMBER_Fax:    phonetype = KABC::PhoneNumber::Fax;  break;
				 case GN_PHONEBOOK_NUMBER_General:
				 case GN_PHONEBOOK_NUMBER_Work:   phonetype = KABC::PhoneNumber::Work; break;
				 default:
				 case GN_PHONEBOOK_NUMBER_Home:   phonetype = KABC::PhoneNumber::Home; break;
				}
				//if (s == entry.number)
				//  type = (KABC::PhoneNumber::Types) (phonetype | KABC::PhoneNumber::Pref);
				a->insertPhoneNumber(KABC::PhoneNumber(s, phonetype));
				break;
		   case GN_PHONEBOOK_ENTRY_URL:
				a->setUrl(s);
				break;
		   case GN_PHONEBOOK_ENTRY_Group:
				a->insertCategory(s);
				break;
		   default:
				GNOKII_DEBUG(QString(" Not handled id=%1, entry=%2\n")
					.arg(entry.subentries[n].entry_type).arg(s));
				break;
		  } // switch()
	} // for(subentry)

  GNOKII_CHECK_ERROR(error);
  return error;
}
Пример #5
0
static void setOtherStreet(const QString &value, KABC::Address &address)
{
    address.setStreet(value);
}
Пример #6
0
QString KTnef::msTNEFToVPart( const QByteArray &tnef )
{
  bool bOk = false;

  KTNEFParser parser;
  QByteArray b( tnef );
  QBuffer buf( &b );
  MemoryCalendar::Ptr cal( new MemoryCalendar( KDateTime::UTC ) );
  KABC::Addressee addressee;
  ICalFormat calFormat;
  Event::Ptr event( new Event() );

  if ( parser.openDevice( &buf ) ) {
    KTNEFMessage *tnefMsg = parser.message();
    //QMap<int,KTNEFProperty*> props = parser.message()->properties();

    // Everything depends from property PR_MESSAGE_CLASS
    // (this is added by KTNEFParser):
    QString msgClass = tnefMsg->findProp( 0x001A, QString(), true ).toUpper();
    if ( !msgClass.isEmpty() ) {
      // Match the old class names that might be used by Outlook for
      // compatibility with Microsoft Mail for Windows for Workgroups 3.1.
      bool bCompatClassAppointment = false;
      bool bCompatMethodRequest = false;
      bool bCompatMethodCancled = false;
      bool bCompatMethodAccepted = false;
      bool bCompatMethodAcceptedCond = false;
      bool bCompatMethodDeclined = false;
      if ( msgClass.startsWith( QLatin1String( "IPM.MICROSOFT SCHEDULE." ) ) ) {
        bCompatClassAppointment = true;
        if ( msgClass.endsWith( QLatin1String( ".MTGREQ" ) ) ) {
          bCompatMethodRequest = true;
        }
        if ( msgClass.endsWith( QLatin1String( ".MTGCNCL" ) ) ) {
          bCompatMethodCancled = true;
        }
        if ( msgClass.endsWith( QLatin1String( ".MTGRESPP" ) ) ) {
          bCompatMethodAccepted = true;
        }
        if ( msgClass.endsWith( QLatin1String( ".MTGRESPA" ) ) ) {
          bCompatMethodAcceptedCond = true;
        }
        if ( msgClass.endsWith( QLatin1String( ".MTGRESPN" ) ) ) {
          bCompatMethodDeclined = true;
        }
      }
      bool bCompatClassNote = ( msgClass == "IPM.MICROSOFT MAIL.NOTE" );

      if ( bCompatClassAppointment || "IPM.APPOINTMENT" == msgClass ) {
        // Compose a vCal
        bool bIsReply = false;
        QString prodID = "-//Microsoft Corporation//Outlook ";
        prodID += tnefMsg->findNamedProp( "0x8554", "9.0" );
        prodID += "MIMEDIR/EN\n";
        prodID += "VERSION:2.0\n";
        calFormat.setApplication( "Outlook", prodID );

        iTIPMethod method;
        if ( bCompatMethodRequest ) {
          method = iTIPRequest;
        } else if ( bCompatMethodCancled ) {
          method = iTIPCancel;
        } else if ( bCompatMethodAccepted || bCompatMethodAcceptedCond ||
                 bCompatMethodDeclined ) {
          method = iTIPReply;
          bIsReply = true;
        } else {
          // pending(khz): verify whether "0x0c17" is the right tag ???
          //
          // at the moment we think there are REQUESTS and UPDATES
          //
          // but WHAT ABOUT REPLIES ???
          //
          //

          if ( tnefMsg->findProp(0x0c17) == "1" ) {
            bIsReply = true;
          }
          method = iTIPRequest;
        }

        /// ###  FIXME Need to get this attribute written
        ScheduleMessage schedMsg( event, method, ScheduleMessage::Unknown );

        QString sSenderSearchKeyEmail( tnefMsg->findProp( 0x0C1D ) );

        if ( !sSenderSearchKeyEmail.isEmpty() ) {
          int colon = sSenderSearchKeyEmail.indexOf( ':' );
          // May be e.g. "SMTP:[email protected]"
          if ( sSenderSearchKeyEmail.indexOf( ':' ) == -1 ) {
            sSenderSearchKeyEmail.remove( 0, colon+1 );
          }
        }

        QString s( tnefMsg->findProp( 0x8189 ) );
        const QStringList attendees = s.split( ';' );
        if ( attendees.count() ) {
          for ( QStringList::const_iterator it = attendees.begin();
               it != attendees.end(); ++it ) {
            // Skip all entries that have no '@' since these are
            // no mail addresses
            if ( (*it).indexOf( '@' ) == -1 ) {
              s = (*it).trimmed();

              Attendee::Ptr attendee( new Attendee( s, s, true ) );
              if ( bIsReply ) {
                if ( bCompatMethodAccepted ) {
                  attendee->setStatus( Attendee::Accepted );
                }
                if ( bCompatMethodDeclined ) {
                  attendee->setStatus( Attendee::Declined );
                }
                if ( bCompatMethodAcceptedCond ) {
                  attendee->setStatus( Attendee::Tentative );
                }
              } else {
                attendee->setStatus( Attendee::NeedsAction );
                attendee->setRole( Attendee::ReqParticipant );
              }
              event->addAttendee( attendee );
            }
          }
        } else {
          // Oops, no attendees?
          // This must be old style, let us use the PR_SENDER_SEARCH_KEY.
          s = sSenderSearchKeyEmail;
          if ( !s.isEmpty() ) {
            Attendee::Ptr attendee( new Attendee( QString(), QString(), true ) );
            if ( bIsReply ) {
              if ( bCompatMethodAccepted ) {
                attendee->setStatus( Attendee::Accepted );
              }
              if ( bCompatMethodAcceptedCond ) {
                attendee->setStatus( Attendee::Declined );
              }
              if ( bCompatMethodDeclined ) {
                attendee->setStatus( Attendee::Tentative );
              }
            } else {
              attendee->setStatus( Attendee::NeedsAction );
              attendee->setRole( Attendee::ReqParticipant );
            }
            event->addAttendee( attendee );
          }
        }
        s = tnefMsg->findProp( 0x3ff8 ); // look for organizer property
        if ( s.isEmpty() && !bIsReply ) {
          s = sSenderSearchKeyEmail;
        }
        // TODO: Use the common name?
        if ( !s.isEmpty() ) {
          event->setOrganizer( s );
        }

        s = tnefMsg->findProp( 0x819b ).remove( QChar( '-' ) ).remove( QChar( ':' ) );
        event->setDtStart( KDateTime::fromString( s ) ); // ## Format??

        s = tnefMsg->findProp( 0x819c ).remove( QChar( '-' ) ).remove( QChar( ':' ) );
        event->setDtEnd( KDateTime::fromString( s ) );

        s = tnefMsg->findProp( 0x810d );
        event->setLocation( s );
        // is it OK to set this to OPAQUE always ??
        //vPart += "TRANSP:OPAQUE\n"; ###FIXME, portme!
        //vPart += "SEQUENCE:0\n";

        // is "0x0023" OK  -  or should we look for "0x0003" ??
        s = tnefMsg->findProp( 0x0023 );
        event->setUid( s );

        // PENDING(khz): is this value in local timezone? Must it be
        // adjusted? Most likely this is a bug in the server or in
        // Outlook - we ignore it for now.
        s = tnefMsg->findProp( 0x8202 ).remove( QChar( '-' ) ).remove( QChar( ':' ) );
        // ### kcal always uses currentDateTime()
        // event->setDtStamp( QDateTime::fromString( s ) );

        s = tnefMsg->findNamedProp( "Keywords" );
        event->setCategories( s );

        s = tnefMsg->findProp( 0x1000 );
        event->setDescription( s );

        s = tnefMsg->findProp( 0x0070 );
        event->setSummary( s );

        s = tnefMsg->findProp( 0x0026 );
        event->setPriority( s.toInt() );
        // is reminder flag set ?
        if ( !tnefMsg->findProp( 0x8503 ).isEmpty() ) {
          Alarm::Ptr alarm( new Alarm( event.data() ) ); // TODO: fix when KCalCore::Alarm is fixed
          KDateTime highNoonTime =
            pureISOToLocalQDateTime( tnefMsg->findProp( 0x8502 ).
                                     remove( QChar( '-' ) ).remove( QChar( ':' ) ) );
          KDateTime wakeMeUpTime =
            pureISOToLocalQDateTime( tnefMsg->findProp( 0x8560, "" ).
                                     remove( QChar( '-' ) ).remove( QChar( ':' ) ) );
          alarm->setTime( wakeMeUpTime );

          if ( highNoonTime.isValid() && wakeMeUpTime.isValid() ) {
            alarm->setStartOffset( Duration( highNoonTime, wakeMeUpTime ) );
          } else {
            // default: wake them up 15 minutes before the appointment
            alarm->setStartOffset( Duration( 15 * 60 ) );
          }
          alarm->setDisplayAlarm( i18n( "Reminder" ) );

          // Sorry: the different action types are not known (yet)
          //        so we always set 'DISPLAY' (no sounds, no images...)
          event->addAlarm( alarm );
        }
        //ensure we have a uid for this event
        if ( event->uid().isEmpty() ) {
          event->setUid( CalFormat::createUniqueId() );
        }
        cal->addEvent( event );
        bOk = true;
        // we finished composing a vCal
      } else if ( bCompatClassNote || "IPM.CONTACT" == msgClass ) {
        addressee.setUid( stringProp( tnefMsg, attMSGID ) );
        addressee.setFormattedName( stringProp( tnefMsg, MAPI_TAG_PR_DISPLAY_NAME ) );
        addressee.insertEmail( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_EMAIL1EMAILADDRESS ), true );
        addressee.insertEmail( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_EMAIL2EMAILADDRESS ), false );
        addressee.insertEmail( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_EMAIL3EMAILADDRESS ), false );
        addressee.insertCustom( "KADDRESSBOOK", "X-IMAddress",
                                sNamedProp( tnefMsg, MAPI_TAG_CONTACT_IMADDRESS ) );
        addressee.insertCustom( "KADDRESSBOOK", "X-SpousesName",
                                stringProp( tnefMsg, MAPI_TAG_PR_SPOUSE_NAME ) );
        addressee.insertCustom( "KADDRESSBOOK", "X-ManagersName",
                                stringProp( tnefMsg, MAPI_TAG_PR_MANAGER_NAME ) );
        addressee.insertCustom( "KADDRESSBOOK", "X-AssistantsName",
                                stringProp( tnefMsg, MAPI_TAG_PR_ASSISTANT ) );
        addressee.insertCustom( "KADDRESSBOOK", "X-Department",
                                stringProp( tnefMsg, MAPI_TAG_PR_DEPARTMENT_NAME ) );
        addressee.insertCustom( "KADDRESSBOOK", "X-Office",
                                stringProp( tnefMsg, MAPI_TAG_PR_OFFICE_LOCATION ) );
        addressee.insertCustom( "KADDRESSBOOK", "X-Profession",
                                stringProp( tnefMsg, MAPI_TAG_PR_PROFESSION ) );

        QString s = tnefMsg->findProp( MAPI_TAG_PR_WEDDING_ANNIVERSARY ).
                    remove( QChar( '-' ) ).remove( QChar( ':' ) );
        if ( !s.isEmpty() ) {
          addressee.insertCustom( "KADDRESSBOOK", "X-Anniversary", s );
        }

        addressee.setUrl( KUrl( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_WEBPAGE ) ) );

        // collect parts of Name entry
        addressee.setFamilyName( stringProp( tnefMsg, MAPI_TAG_PR_SURNAME ) );
        addressee.setGivenName( stringProp( tnefMsg, MAPI_TAG_PR_GIVEN_NAME ) );
        addressee.setAdditionalName( stringProp( tnefMsg, MAPI_TAG_PR_MIDDLE_NAME ) );
        addressee.setPrefix( stringProp( tnefMsg, MAPI_TAG_PR_DISPLAY_NAME_PREFIX ) );
        addressee.setSuffix( stringProp( tnefMsg, MAPI_TAG_PR_GENERATION ) );

        addressee.setNickName( stringProp( tnefMsg, MAPI_TAG_PR_NICKNAME ) );
        addressee.setRole( stringProp( tnefMsg, MAPI_TAG_PR_TITLE ) );
        addressee.setOrganization( stringProp( tnefMsg, MAPI_TAG_PR_COMPANY_NAME ) );
        /*
        the MAPI property ID of this (multiline) )field is unknown:
        vPart += stringProp(tnefMsg, "\n","NOTE", ... , "" );
        */

        KABC::Address adr;
        adr.setPostOfficeBox( stringProp( tnefMsg, MAPI_TAG_PR_HOME_ADDRESS_PO_BOX ) );
        adr.setStreet( stringProp( tnefMsg, MAPI_TAG_PR_HOME_ADDRESS_STREET ) );
        adr.setLocality( stringProp( tnefMsg, MAPI_TAG_PR_HOME_ADDRESS_CITY ) );
        adr.setRegion( stringProp( tnefMsg, MAPI_TAG_PR_HOME_ADDRESS_STATE_OR_PROVINCE ) );
        adr.setPostalCode( stringProp( tnefMsg, MAPI_TAG_PR_HOME_ADDRESS_POSTAL_CODE ) );
        adr.setCountry( stringProp( tnefMsg, MAPI_TAG_PR_HOME_ADDRESS_COUNTRY ) );
        adr.setType( KABC::Address::Home );
        addressee.insertAddress( adr );

        adr.setPostOfficeBox( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_BUSINESSADDRESSPOBOX ) );
        adr.setStreet( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_BUSINESSADDRESSSTREET ) );
        adr.setLocality( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_BUSINESSADDRESSCITY ) );
        adr.setRegion( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_BUSINESSADDRESSSTATE ) );
        adr.setPostalCode( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_BUSINESSADDRESSPOSTALCODE ) );
        adr.setCountry( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_BUSINESSADDRESSCOUNTRY ) );
        adr.setType( KABC::Address::Work );
        addressee.insertAddress( adr );

        adr.setPostOfficeBox( stringProp( tnefMsg, MAPI_TAG_PR_OTHER_ADDRESS_PO_BOX ) );
        adr.setStreet( stringProp( tnefMsg, MAPI_TAG_PR_OTHER_ADDRESS_STREET ) );
        adr.setLocality( stringProp( tnefMsg, MAPI_TAG_PR_OTHER_ADDRESS_CITY ) );
        adr.setRegion( stringProp( tnefMsg, MAPI_TAG_PR_OTHER_ADDRESS_STATE_OR_PROVINCE ) );
        adr.setPostalCode( stringProp( tnefMsg, MAPI_TAG_PR_OTHER_ADDRESS_POSTAL_CODE ) );
        adr.setCountry( stringProp( tnefMsg, MAPI_TAG_PR_OTHER_ADDRESS_COUNTRY ) );
        adr.setType( KABC::Address::Dom );
        addressee.insertAddress( adr );

        // problem: the 'other' address was stored by KOrganizer in
        //          a line looking like the following one:
        // vPart += "\nADR;TYPE=dom;TYPE=intl;TYPE=parcel;TYPE=postal;TYPE=work;"
        //          "TYPE=home:other_pobox;;other_str1\nother_str2;other_loc;other_region;"
        //          "other_pocode;other_country"

        QString nr;
        nr = stringProp( tnefMsg, MAPI_TAG_PR_HOME_TELEPHONE_NUMBER );
        addressee.insertPhoneNumber(
          KABC::PhoneNumber( nr, KABC::PhoneNumber::Home ) );
        nr = stringProp( tnefMsg, MAPI_TAG_PR_BUSINESS_TELEPHONE_NUMBER );
        addressee.insertPhoneNumber(
          KABC::PhoneNumber( nr, KABC::PhoneNumber::Work ) );
        nr = stringProp( tnefMsg, MAPI_TAG_PR_MOBILE_TELEPHONE_NUMBER );
        addressee.insertPhoneNumber(
          KABC::PhoneNumber( nr, KABC::PhoneNumber::Cell ) );
        nr = stringProp( tnefMsg, MAPI_TAG_PR_HOME_FAX_NUMBER );
        addressee.insertPhoneNumber(
          KABC::PhoneNumber( nr, KABC::PhoneNumber::Fax | KABC::PhoneNumber::Home ) );
        nr = stringProp( tnefMsg, MAPI_TAG_PR_BUSINESS_FAX_NUMBER );
        addressee.insertPhoneNumber(
          KABC::PhoneNumber( nr, KABC::PhoneNumber::Fax | KABC::PhoneNumber::Work ) );

        s = tnefMsg->findProp( MAPI_TAG_PR_BIRTHDAY ).
            remove( QChar( '-' ) ).remove( QChar( ':' ) );
        if ( !s.isEmpty() ) {
          addressee.setBirthday( QDateTime::fromString( s ) );
        }

        bOk = ( !addressee.isEmpty() );
      } else if ( "IPM.NOTE" == msgClass ) {

      } // else if ... and so on ...
    }
  }

  // Compose return string
  // KDAB_TODO: Interesting, without the explicit QString the toString call is
  //            reported to be ambigious with toString( const Incidence::Ptr & ).
  const QString iCal = calFormat.toString( cal, QString() );
  if ( !iCal.isEmpty() ) {
    // This was an iCal
    return iCal;
  }

  // Not an iCal - try a vCard
  KABC::VCardConverter converter;
  return QString::fromUtf8( converter.createVCard( addressee ) );
}