Home | History | Annotate | Download | only in model
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.contacts.model;
     18 
     19 import com.android.contacts.R;
     20 import com.google.android.collect.Lists;
     21 
     22 import android.content.ContentValues;
     23 import android.content.Context;
     24 import android.content.res.Resources;
     25 import android.database.Cursor;
     26 import android.provider.ContactsContract.CommonDataKinds.BaseTypes;
     27 import android.provider.ContactsContract.CommonDataKinds.Email;
     28 import android.provider.ContactsContract.CommonDataKinds.Event;
     29 import android.provider.ContactsContract.CommonDataKinds.Im;
     30 import android.provider.ContactsContract.CommonDataKinds.Nickname;
     31 import android.provider.ContactsContract.CommonDataKinds.Note;
     32 import android.provider.ContactsContract.CommonDataKinds.Organization;
     33 import android.provider.ContactsContract.CommonDataKinds.Phone;
     34 import android.provider.ContactsContract.CommonDataKinds.Photo;
     35 import android.provider.ContactsContract.CommonDataKinds.SipAddress;
     36 import android.provider.ContactsContract.CommonDataKinds.StructuredName;
     37 import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
     38 import android.provider.ContactsContract.CommonDataKinds.Website;
     39 import android.view.inputmethod.EditorInfo;
     40 
     41 import java.util.Locale;
     42 
     43 public class FallbackSource extends ContactsSource {
     44     protected static final int FLAGS_PHONE = EditorInfo.TYPE_CLASS_PHONE;
     45     protected static final int FLAGS_EMAIL = EditorInfo.TYPE_CLASS_TEXT
     46             | EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS;
     47     protected static final int FLAGS_PERSON_NAME = EditorInfo.TYPE_CLASS_TEXT
     48             | EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS | EditorInfo.TYPE_TEXT_VARIATION_PERSON_NAME;
     49     protected static final int FLAGS_PHONETIC = EditorInfo.TYPE_CLASS_TEXT
     50             | EditorInfo.TYPE_TEXT_VARIATION_PHONETIC;
     51     protected static final int FLAGS_GENERIC_NAME = EditorInfo.TYPE_CLASS_TEXT
     52             | EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS;
     53     protected static final int FLAGS_NOTE = EditorInfo.TYPE_CLASS_TEXT
     54             | EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
     55     protected static final int FLAGS_WEBSITE = EditorInfo.TYPE_CLASS_TEXT
     56             | EditorInfo.TYPE_TEXT_VARIATION_URI;
     57     protected static final int FLAGS_POSTAL = EditorInfo.TYPE_CLASS_TEXT
     58             | EditorInfo.TYPE_TEXT_VARIATION_POSTAL_ADDRESS | EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS
     59             | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
     60     protected static final int FLAGS_SIP_ADDRESS = EditorInfo.TYPE_CLASS_TEXT
     61             | EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS;  // since SIP addresses have the same
     62                                                              // basic format as email addresses
     63 
     64     public FallbackSource() {
     65         this.accountType = null;
     66         this.titleRes = R.string.account_phone;
     67         this.iconRes = R.drawable.ic_launcher_contacts;
     68     }
     69 
     70     @Override
     71     protected void inflate(Context context, int inflateLevel) {
     72 
     73         inflateStructuredName(context, inflateLevel);
     74         inflateNickname(context, inflateLevel);
     75         inflatePhone(context, inflateLevel);
     76         inflateEmail(context, inflateLevel);
     77         inflateStructuredPostal(context, inflateLevel);
     78         inflateIm(context, inflateLevel);
     79         inflateOrganization(context, inflateLevel);
     80         inflatePhoto(context, inflateLevel);
     81         inflateNote(context, inflateLevel);
     82         inflateWebsite(context, inflateLevel);
     83         inflateEvent(context, inflateLevel);
     84         inflateSipAddress(context, inflateLevel);
     85 
     86         setInflatedLevel(inflateLevel);
     87 
     88     }
     89 
     90     protected EditType buildPhoneType(int type) {
     91         return new EditType(type, Phone.getTypeLabelResource(type));
     92     }
     93 
     94     protected EditType buildEmailType(int type) {
     95         return new EditType(type, Email.getTypeLabelResource(type));
     96     }
     97 
     98     protected EditType buildPostalType(int type) {
     99         return new EditType(type, StructuredPostal.getTypeLabelResource(type));
    100     }
    101 
    102     protected EditType buildImType(int type) {
    103         return new EditType(type, Im.getProtocolLabelResource(type));
    104     }
    105 
    106     protected EditType buildOrgType(int type) {
    107         return new EditType(type, Organization.getTypeLabelResource(type));
    108     }
    109 
    110     protected DataKind inflateStructuredName(Context context, int inflateLevel) {
    111         DataKind kind = getKindForMimetype(StructuredName.CONTENT_ITEM_TYPE);
    112         if (kind == null) {
    113             kind = addKind(new DataKind(StructuredName.CONTENT_ITEM_TYPE,
    114                     R.string.nameLabelsGroup, -1, -1, true));
    115         }
    116 
    117         if (inflateLevel >= ContactsSource.LEVEL_CONSTRAINTS) {
    118             boolean displayOrderPrimary =
    119                     context.getResources().getBoolean(R.bool.config_editor_field_order_primary);
    120 
    121             kind.fieldList = Lists.newArrayList();
    122             kind.fieldList.add(new EditField(StructuredName.PREFIX, R.string.name_prefix,
    123                     FLAGS_PERSON_NAME).setOptional(true));
    124             if (!displayOrderPrimary) {
    125                 kind.fieldList.add(new EditField(StructuredName.FAMILY_NAME, R.string.name_family,
    126                         FLAGS_PERSON_NAME));
    127                 kind.fieldList.add(new EditField(StructuredName.MIDDLE_NAME, R.string.name_middle,
    128                         FLAGS_PERSON_NAME).setOptional(true));
    129                 kind.fieldList.add(new EditField(StructuredName.GIVEN_NAME, R.string.name_given,
    130                         FLAGS_PERSON_NAME));
    131                 kind.fieldList.add(new EditField(StructuredName.SUFFIX, R.string.name_suffix,
    132                         FLAGS_PERSON_NAME).setOptional(true));
    133                 kind.fieldList.add(new EditField(StructuredName.PHONETIC_FAMILY_NAME,
    134                         R.string.name_phonetic_family, FLAGS_PHONETIC).setOptional(true));
    135                 kind.fieldList.add(new EditField(StructuredName.PHONETIC_MIDDLE_NAME,
    136                         R.string.name_phonetic_middle, FLAGS_PHONETIC).setOptional(true));
    137                 kind.fieldList.add(new EditField(StructuredName.PHONETIC_GIVEN_NAME,
    138                         R.string.name_phonetic_given, FLAGS_PHONETIC).setOptional(true));
    139             } else {
    140                 kind.fieldList.add(new EditField(StructuredName.GIVEN_NAME, R.string.name_given,
    141                         FLAGS_PERSON_NAME));
    142                 kind.fieldList.add(new EditField(StructuredName.MIDDLE_NAME, R.string.name_middle,
    143                         FLAGS_PERSON_NAME).setOptional(true));
    144                 kind.fieldList.add(new EditField(StructuredName.FAMILY_NAME, R.string.name_family,
    145                         FLAGS_PERSON_NAME));
    146                 kind.fieldList.add(new EditField(StructuredName.SUFFIX, R.string.name_suffix,
    147                         FLAGS_PERSON_NAME).setOptional(true));
    148                 kind.fieldList.add(new EditField(StructuredName.PHONETIC_GIVEN_NAME,
    149                         R.string.name_phonetic_given, FLAGS_PHONETIC).setOptional(true));
    150                 kind.fieldList.add(new EditField(StructuredName.PHONETIC_MIDDLE_NAME,
    151                         R.string.name_phonetic_middle, FLAGS_PHONETIC).setOptional(true));
    152                 kind.fieldList.add(new EditField(StructuredName.PHONETIC_FAMILY_NAME,
    153                         R.string.name_phonetic_family, FLAGS_PHONETIC).setOptional(true));
    154             }
    155         }
    156 
    157         return kind;
    158     }
    159 
    160     protected DataKind inflateNickname(Context context, int inflateLevel) {
    161         DataKind kind = getKindForMimetype(Nickname.CONTENT_ITEM_TYPE);
    162         if (kind == null) {
    163             kind = addKind(new DataKind(Nickname.CONTENT_ITEM_TYPE,
    164                     R.string.nicknameLabelsGroup, -1, 115, true));
    165             kind.secondary = true;
    166             kind.isList = false;
    167             kind.actionHeader = new SimpleInflater(R.string.nicknameLabelsGroup);
    168             kind.actionBody = new SimpleInflater(Nickname.NAME);
    169         }
    170 
    171         if (inflateLevel >= ContactsSource.LEVEL_CONSTRAINTS) {
    172             kind.defaultValues = new ContentValues();
    173             kind.defaultValues.put(Nickname.TYPE, Nickname.TYPE_DEFAULT);
    174 
    175             kind.fieldList = Lists.newArrayList();
    176             kind.fieldList.add(new EditField(Nickname.NAME, R.string.nicknameLabelsGroup,
    177                     FLAGS_PERSON_NAME));
    178         }
    179 
    180         return kind;
    181     }
    182 
    183     protected DataKind inflatePhone(Context context, int inflateLevel) {
    184         DataKind kind = getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
    185         if (kind == null) {
    186             kind = addKind(new DataKind(Phone.CONTENT_ITEM_TYPE, R.string.phoneLabelsGroup,
    187                     android.R.drawable.sym_action_call, 10, true));
    188             kind.iconAltRes = R.drawable.sym_action_sms;
    189             kind.actionHeader = new PhoneActionInflater();
    190             kind.actionAltHeader = new PhoneActionAltInflater();
    191             kind.actionBody = new SimpleInflater(Phone.NUMBER);
    192         }
    193 
    194         if (inflateLevel >= ContactsSource.LEVEL_CONSTRAINTS) {
    195             kind.typeColumn = Phone.TYPE;
    196             kind.typeList = Lists.newArrayList();
    197             kind.typeList.add(buildPhoneType(Phone.TYPE_HOME));
    198             kind.typeList.add(buildPhoneType(Phone.TYPE_MOBILE));
    199             kind.typeList.add(buildPhoneType(Phone.TYPE_WORK));
    200             kind.typeList.add(buildPhoneType(Phone.TYPE_FAX_WORK).setSecondary(true));
    201             kind.typeList.add(buildPhoneType(Phone.TYPE_FAX_HOME).setSecondary(true));
    202             kind.typeList.add(buildPhoneType(Phone.TYPE_PAGER).setSecondary(true));
    203             kind.typeList.add(buildPhoneType(Phone.TYPE_OTHER));
    204             kind.typeList.add(buildPhoneType(Phone.TYPE_CUSTOM).setSecondary(true).setCustomColumn(
    205                     Phone.LABEL));
    206             kind.typeList.add(buildPhoneType(Phone.TYPE_CALLBACK).setSecondary(true));
    207             kind.typeList.add(buildPhoneType(Phone.TYPE_CAR).setSecondary(true));
    208             kind.typeList.add(buildPhoneType(Phone.TYPE_COMPANY_MAIN).setSecondary(true));
    209             kind.typeList.add(buildPhoneType(Phone.TYPE_ISDN).setSecondary(true));
    210             kind.typeList.add(buildPhoneType(Phone.TYPE_MAIN).setSecondary(true));
    211             kind.typeList.add(buildPhoneType(Phone.TYPE_OTHER_FAX).setSecondary(true));
    212             kind.typeList.add(buildPhoneType(Phone.TYPE_RADIO).setSecondary(true));
    213             kind.typeList.add(buildPhoneType(Phone.TYPE_TELEX).setSecondary(true));
    214             kind.typeList.add(buildPhoneType(Phone.TYPE_TTY_TDD).setSecondary(true));
    215             kind.typeList.add(buildPhoneType(Phone.TYPE_WORK_MOBILE).setSecondary(true));
    216             kind.typeList.add(buildPhoneType(Phone.TYPE_WORK_PAGER).setSecondary(true));
    217             kind.typeList.add(buildPhoneType(Phone.TYPE_ASSISTANT).setSecondary(true)
    218                     .setCustomColumn(Phone.LABEL));
    219             kind.typeList.add(buildPhoneType(Phone.TYPE_MMS).setSecondary(true));
    220 
    221             kind.fieldList = Lists.newArrayList();
    222             kind.fieldList.add(new EditField(Phone.NUMBER, R.string.phoneLabelsGroup, FLAGS_PHONE));
    223         }
    224 
    225         return kind;
    226     }
    227 
    228     protected DataKind inflateEmail(Context context, int inflateLevel) {
    229         DataKind kind = getKindForMimetype(Email.CONTENT_ITEM_TYPE);
    230         if (kind == null) {
    231             kind = addKind(new DataKind(Email.CONTENT_ITEM_TYPE,
    232                     R.string.emailLabelsGroup, android.R.drawable.sym_action_email, 15, true));
    233             kind.actionHeader = new EmailActionInflater();
    234             kind.actionBody = new SimpleInflater(Email.DATA);
    235         }
    236 
    237         if (inflateLevel >= ContactsSource.LEVEL_CONSTRAINTS) {
    238             kind.typeColumn = Email.TYPE;
    239             kind.typeList = Lists.newArrayList();
    240             kind.typeList.add(buildEmailType(Email.TYPE_HOME));
    241             kind.typeList.add(buildEmailType(Email.TYPE_WORK));
    242             kind.typeList.add(buildEmailType(Email.TYPE_OTHER));
    243             kind.typeList.add(buildEmailType(Email.TYPE_MOBILE));
    244             kind.typeList.add(buildEmailType(Email.TYPE_CUSTOM).setSecondary(true).setCustomColumn(
    245                     Email.LABEL));
    246 
    247             kind.fieldList = Lists.newArrayList();
    248             kind.fieldList.add(new EditField(Email.DATA, R.string.emailLabelsGroup, FLAGS_EMAIL));
    249         }
    250 
    251         return kind;
    252     }
    253 
    254     protected DataKind inflateStructuredPostal(Context context, int inflateLevel) {
    255         DataKind kind = getKindForMimetype(StructuredPostal.CONTENT_ITEM_TYPE);
    256         if (kind == null) {
    257             kind = addKind(new DataKind(StructuredPostal.CONTENT_ITEM_TYPE,
    258                     R.string.postalLabelsGroup, R.drawable.sym_action_map, 25, true));
    259             kind.actionHeader = new PostalActionInflater();
    260             kind.actionBody = new SimpleInflater(StructuredPostal.FORMATTED_ADDRESS);
    261         }
    262 
    263         if (inflateLevel >= ContactsSource.LEVEL_CONSTRAINTS) {
    264             final boolean useJapaneseOrder =
    265                 Locale.JAPANESE.getLanguage().equals(Locale.getDefault().getLanguage());
    266             kind.typeColumn = StructuredPostal.TYPE;
    267             kind.typeList = Lists.newArrayList();
    268             kind.typeList.add(buildPostalType(StructuredPostal.TYPE_HOME));
    269             kind.typeList.add(buildPostalType(StructuredPostal.TYPE_WORK));
    270             kind.typeList.add(buildPostalType(StructuredPostal.TYPE_OTHER));
    271             kind.typeList.add(buildPostalType(StructuredPostal.TYPE_CUSTOM).setSecondary(true)
    272                     .setCustomColumn(StructuredPostal.LABEL));
    273 
    274             kind.fieldList = Lists.newArrayList();
    275 
    276             if (useJapaneseOrder) {
    277                 kind.fieldList.add(new EditField(StructuredPostal.COUNTRY,
    278                         R.string.postal_country, FLAGS_POSTAL).setOptional(true));
    279                 kind.fieldList.add(new EditField(StructuredPostal.POSTCODE,
    280                         R.string.postal_postcode, FLAGS_POSTAL));
    281                 kind.fieldList.add(new EditField(StructuredPostal.REGION,
    282                         R.string.postal_region, FLAGS_POSTAL));
    283                 kind.fieldList.add(new EditField(StructuredPostal.CITY,
    284                         R.string.postal_city, FLAGS_POSTAL));
    285                 kind.fieldList.add(new EditField(StructuredPostal.NEIGHBORHOOD,
    286                         R.string.postal_neighborhood, FLAGS_POSTAL).setOptional(true));
    287                 kind.fieldList.add(new EditField(StructuredPostal.STREET,
    288                         R.string.postal_street, FLAGS_POSTAL));
    289                 kind.fieldList.add(new EditField(StructuredPostal.POBOX,
    290                         R.string.postal_pobox, FLAGS_POSTAL).setOptional(true));
    291             } else {
    292                 kind.fieldList.add(new EditField(StructuredPostal.STREET,
    293                         R.string.postal_street, FLAGS_POSTAL));
    294                 kind.fieldList.add(new EditField(StructuredPostal.POBOX,
    295                         R.string.postal_pobox, FLAGS_POSTAL).setOptional(true));
    296                 kind.fieldList.add(new EditField(StructuredPostal.NEIGHBORHOOD,
    297                         R.string.postal_neighborhood, FLAGS_POSTAL).setOptional(true));
    298                 kind.fieldList.add(new EditField(StructuredPostal.CITY,
    299                         R.string.postal_city, FLAGS_POSTAL));
    300                 kind.fieldList.add(new EditField(StructuredPostal.REGION,
    301                         R.string.postal_region, FLAGS_POSTAL));
    302                 kind.fieldList.add(new EditField(StructuredPostal.POSTCODE,
    303                         R.string.postal_postcode, FLAGS_POSTAL));
    304                 kind.fieldList.add(new EditField(StructuredPostal.COUNTRY,
    305                         R.string.postal_country, FLAGS_POSTAL).setOptional(true));
    306             }
    307         }
    308 
    309         return kind;
    310     }
    311 
    312     protected DataKind inflateIm(Context context, int inflateLevel) {
    313         DataKind kind = getKindForMimetype(Im.CONTENT_ITEM_TYPE);
    314         if (kind == null) {
    315             kind = addKind(new DataKind(Im.CONTENT_ITEM_TYPE, R.string.imLabelsGroup,
    316                     android.R.drawable.sym_action_chat, 20, true));
    317             kind.secondary = true;
    318             kind.actionHeader = new ImActionInflater();
    319             kind.actionBody = new SimpleInflater(Im.DATA);
    320         }
    321 
    322         if (inflateLevel >= ContactsSource.LEVEL_CONSTRAINTS) {
    323             // NOTE: even though a traditional "type" exists, for editing
    324             // purposes we're using the protocol to pick labels
    325 
    326             kind.defaultValues = new ContentValues();
    327             kind.defaultValues.put(Im.TYPE, Im.TYPE_OTHER);
    328 
    329             kind.typeColumn = Im.PROTOCOL;
    330             kind.typeList = Lists.newArrayList();
    331             kind.typeList.add(buildImType(Im.PROTOCOL_AIM));
    332             kind.typeList.add(buildImType(Im.PROTOCOL_MSN));
    333             kind.typeList.add(buildImType(Im.PROTOCOL_YAHOO));
    334             kind.typeList.add(buildImType(Im.PROTOCOL_SKYPE));
    335             kind.typeList.add(buildImType(Im.PROTOCOL_QQ));
    336             kind.typeList.add(buildImType(Im.PROTOCOL_GOOGLE_TALK));
    337             kind.typeList.add(buildImType(Im.PROTOCOL_ICQ));
    338             kind.typeList.add(buildImType(Im.PROTOCOL_JABBER));
    339             kind.typeList.add(buildImType(Im.PROTOCOL_CUSTOM).setSecondary(true).setCustomColumn(
    340                     Im.CUSTOM_PROTOCOL));
    341 
    342             kind.fieldList = Lists.newArrayList();
    343             kind.fieldList.add(new EditField(Im.DATA, R.string.imLabelsGroup, FLAGS_EMAIL));
    344         }
    345 
    346         return kind;
    347     }
    348 
    349     protected DataKind inflateOrganization(Context context, int inflateLevel) {
    350         DataKind kind = getKindForMimetype(Organization.CONTENT_ITEM_TYPE);
    351         if (kind == null) {
    352             kind = addKind(new DataKind(Organization.CONTENT_ITEM_TYPE,
    353                     R.string.organizationLabelsGroup, R.drawable.sym_action_organization, 30, true));
    354             kind.actionHeader = new SimpleInflater(Organization.COMPANY);
    355             kind.actionBody = new SimpleInflater(Organization.TITLE);
    356         }
    357 
    358         if (inflateLevel >= ContactsSource.LEVEL_CONSTRAINTS) {
    359             kind.typeColumn = Organization.TYPE;
    360             kind.typeList = Lists.newArrayList();
    361             kind.typeList.add(buildOrgType(Organization.TYPE_WORK));
    362             kind.typeList.add(buildOrgType(Organization.TYPE_OTHER));
    363             kind.typeList.add(buildOrgType(Organization.TYPE_CUSTOM).setSecondary(true)
    364                     .setCustomColumn(Organization.LABEL));
    365 
    366             kind.fieldList = Lists.newArrayList();
    367             kind.fieldList.add(new EditField(Organization.COMPANY, R.string.ghostData_company,
    368                     FLAGS_GENERIC_NAME));
    369             kind.fieldList.add(new EditField(Organization.TITLE, R.string.ghostData_title,
    370                     FLAGS_GENERIC_NAME));
    371         }
    372 
    373         return kind;
    374     }
    375 
    376     protected DataKind inflatePhoto(Context context, int inflateLevel) {
    377         DataKind kind = getKindForMimetype(Photo.CONTENT_ITEM_TYPE);
    378         if (kind == null) {
    379             kind = addKind(new DataKind(Photo.CONTENT_ITEM_TYPE, -1, -1, -1, true));
    380         }
    381 
    382         if (inflateLevel >= ContactsSource.LEVEL_CONSTRAINTS) {
    383             kind.fieldList = Lists.newArrayList();
    384             kind.fieldList.add(new EditField(Photo.PHOTO, -1, -1));
    385         }
    386 
    387         return kind;
    388     }
    389 
    390     protected DataKind inflateNote(Context context, int inflateLevel) {
    391         DataKind kind = getKindForMimetype(Note.CONTENT_ITEM_TYPE);
    392         if (kind == null) {
    393             kind = addKind(new DataKind(Note.CONTENT_ITEM_TYPE,
    394                     R.string.label_notes, R.drawable.sym_note, 110, true));
    395             kind.isList = false;
    396             kind.secondary = true;
    397             kind.actionHeader = new SimpleInflater(R.string.label_notes);
    398             kind.actionBody = new SimpleInflater(Note.NOTE);
    399         }
    400 
    401         if (inflateLevel >= ContactsSource.LEVEL_CONSTRAINTS) {
    402             kind.fieldList = Lists.newArrayList();
    403             kind.fieldList.add(new EditField(Note.NOTE, R.string.label_notes, FLAGS_NOTE));
    404         }
    405 
    406         return kind;
    407     }
    408 
    409     protected DataKind inflateWebsite(Context context, int inflateLevel) {
    410         DataKind kind = getKindForMimetype(Website.CONTENT_ITEM_TYPE);
    411         if (kind == null) {
    412             kind = addKind(new DataKind(Website.CONTENT_ITEM_TYPE,
    413                     R.string.websiteLabelsGroup, -1, 120, true));
    414             kind.secondary = true;
    415             kind.actionHeader = new SimpleInflater(R.string.websiteLabelsGroup);
    416             kind.actionBody = new SimpleInflater(Website.URL);
    417         }
    418 
    419         if (inflateLevel >= ContactsSource.LEVEL_CONSTRAINTS) {
    420             kind.defaultValues = new ContentValues();
    421             kind.defaultValues.put(Website.TYPE, Website.TYPE_OTHER);
    422 
    423             kind.fieldList = Lists.newArrayList();
    424             kind.fieldList.add(new EditField(Website.URL, R.string.websiteLabelsGroup, FLAGS_WEBSITE));
    425         }
    426 
    427         return kind;
    428     }
    429 
    430     protected DataKind inflateEvent(Context context, int inflateLevel) {
    431         DataKind kind = getKindForMimetype(Event.CONTENT_ITEM_TYPE);
    432         if (kind == null) {
    433             kind = addKind(new DataKind(Event.CONTENT_ITEM_TYPE,
    434                     R.string.eventLabelsGroup, -1, 150, false));
    435             kind.secondary = true;
    436             kind.actionHeader = new EventActionInflater();
    437             kind.actionBody = new SimpleInflater(Event.START_DATE);
    438         }
    439 
    440         return kind;
    441     }
    442 
    443     protected DataKind inflateSipAddress(Context context, int inflateLevel) {
    444         DataKind kind = getKindForMimetype(SipAddress.CONTENT_ITEM_TYPE);
    445         if (kind == null) {
    446             // The icon specified here is the one that gets displayed for
    447             // "Internet call" items, in the "view contact" UI within the
    448             // Contacts app.
    449             //
    450             // This is independent of the "SIP call" icon that gets
    451             // displayed in the Quick Contacts widget, which comes from
    452             // the android:icon attribute of the SIP-related
    453             // intent-filters in the Phone app's manifest.
    454 
    455             kind = addKind(new DataKind(SipAddress.CONTENT_ITEM_TYPE,
    456                     R.string.label_sip_address, android.R.drawable.sym_action_call, 130, true));
    457 
    458             kind.isList = false;
    459             kind.secondary = true;
    460             kind.actionHeader = new SimpleInflater(R.string.label_sip_address);
    461             kind.actionBody = new SimpleInflater(SipAddress.SIP_ADDRESS);
    462         }
    463 
    464         if (inflateLevel >= ContactsSource.LEVEL_CONSTRAINTS) {
    465             kind.fieldList = Lists.newArrayList();
    466             kind.fieldList.add(new EditField(SipAddress.SIP_ADDRESS,
    467                                              R.string.label_sip_address, FLAGS_SIP_ADDRESS));
    468         }
    469 
    470         return kind;
    471     }
    472 
    473     /**
    474      * Simple inflater that assumes a string resource has a "%s" that will be
    475      * filled from the given column.
    476      */
    477     public static class SimpleInflater implements StringInflater {
    478         private final int mStringRes;
    479         private final String mColumnName;
    480 
    481         public SimpleInflater(int stringRes) {
    482             this(stringRes, null);
    483         }
    484 
    485         public SimpleInflater(String columnName) {
    486             this(-1, columnName);
    487         }
    488 
    489         public SimpleInflater(int stringRes, String columnName) {
    490             mStringRes = stringRes;
    491             mColumnName = columnName;
    492         }
    493 
    494         public CharSequence inflateUsing(Context context, Cursor cursor) {
    495             final int index = mColumnName != null ? cursor.getColumnIndex(mColumnName) : -1;
    496             final boolean validString = mStringRes > 0;
    497             final boolean validColumn = index != -1;
    498 
    499             final CharSequence stringValue = validString ? context.getText(mStringRes) : null;
    500             final CharSequence columnValue = validColumn ? cursor.getString(index) : null;
    501 
    502             if (validString && validColumn) {
    503                 return String.format(stringValue.toString(), columnValue);
    504             } else if (validString) {
    505                 return stringValue;
    506             } else if (validColumn) {
    507                 return columnValue;
    508             } else {
    509                 return null;
    510             }
    511         }
    512 
    513         public CharSequence inflateUsing(Context context, ContentValues values) {
    514             final boolean validColumn = values.containsKey(mColumnName);
    515             final boolean validString = mStringRes > 0;
    516 
    517             final CharSequence stringValue = validString ? context.getText(mStringRes) : null;
    518             final CharSequence columnValue = validColumn ? values.getAsString(mColumnName) : null;
    519 
    520             if (validString && validColumn) {
    521                 return String.format(stringValue.toString(), columnValue);
    522             } else if (validString) {
    523                 return stringValue;
    524             } else if (validColumn) {
    525                 return columnValue;
    526             } else {
    527                 return null;
    528             }
    529         }
    530     }
    531 
    532     public static abstract class CommonInflater implements StringInflater {
    533         protected abstract int getTypeLabelResource(Integer type);
    534 
    535         protected boolean isCustom(Integer type) {
    536             return type == BaseTypes.TYPE_CUSTOM;
    537         }
    538 
    539         protected String getTypeColumn() {
    540             return Phone.TYPE;
    541         }
    542 
    543         protected String getLabelColumn() {
    544             return Phone.LABEL;
    545         }
    546 
    547         protected CharSequence getTypeLabel(Resources res, Integer type, CharSequence label) {
    548             final int labelRes = getTypeLabelResource(type);
    549             if (type == null) {
    550                 return res.getText(labelRes);
    551             } else if (isCustom(type)) {
    552                 return res.getString(labelRes, label == null ? "" : label);
    553             } else {
    554                 return res.getText(labelRes);
    555             }
    556         }
    557 
    558         public CharSequence inflateUsing(Context context, Cursor cursor) {
    559             final Integer type = cursor.getInt(cursor.getColumnIndex(getTypeColumn()));
    560             final String label = cursor.getString(cursor.getColumnIndex(getLabelColumn()));
    561             return getTypeLabel(context.getResources(), type, label);
    562         }
    563 
    564         public CharSequence inflateUsing(Context context, ContentValues values) {
    565             final Integer type = values.getAsInteger(getTypeColumn());
    566             final String label = values.getAsString(getLabelColumn());
    567             return getTypeLabel(context.getResources(), type, label);
    568         }
    569     }
    570 
    571     public static class PhoneActionInflater extends CommonInflater {
    572         @Override
    573         protected boolean isCustom(Integer type) {
    574             return type == Phone.TYPE_CUSTOM || type == Phone.TYPE_ASSISTANT;
    575         }
    576 
    577         @Override
    578         protected int getTypeLabelResource(Integer type) {
    579             if (type == null) return R.string.call_other;
    580             switch (type) {
    581                 case Phone.TYPE_HOME: return R.string.call_home;
    582                 case Phone.TYPE_MOBILE: return R.string.call_mobile;
    583                 case Phone.TYPE_WORK: return R.string.call_work;
    584                 case Phone.TYPE_FAX_WORK: return R.string.call_fax_work;
    585                 case Phone.TYPE_FAX_HOME: return R.string.call_fax_home;
    586                 case Phone.TYPE_PAGER: return R.string.call_pager;
    587                 case Phone.TYPE_OTHER: return R.string.call_other;
    588                 case Phone.TYPE_CALLBACK: return R.string.call_callback;
    589                 case Phone.TYPE_CAR: return R.string.call_car;
    590                 case Phone.TYPE_COMPANY_MAIN: return R.string.call_company_main;
    591                 case Phone.TYPE_ISDN: return R.string.call_isdn;
    592                 case Phone.TYPE_MAIN: return R.string.call_main;
    593                 case Phone.TYPE_OTHER_FAX: return R.string.call_other_fax;
    594                 case Phone.TYPE_RADIO: return R.string.call_radio;
    595                 case Phone.TYPE_TELEX: return R.string.call_telex;
    596                 case Phone.TYPE_TTY_TDD: return R.string.call_tty_tdd;
    597                 case Phone.TYPE_WORK_MOBILE: return R.string.call_work_mobile;
    598                 case Phone.TYPE_WORK_PAGER: return R.string.call_work_pager;
    599                 case Phone.TYPE_ASSISTANT: return R.string.call_assistant;
    600                 case Phone.TYPE_MMS: return R.string.call_mms;
    601                 default: return R.string.call_custom;
    602             }
    603         }
    604     }
    605 
    606     public static class PhoneActionAltInflater extends CommonInflater {
    607         @Override
    608         protected boolean isCustom(Integer type) {
    609             return (type == Phone.TYPE_CUSTOM || type == Phone.TYPE_ASSISTANT);
    610         }
    611 
    612         @Override
    613         protected int getTypeLabelResource(Integer type) {
    614             if (type == null) return R.string.sms_other;
    615             switch (type) {
    616                 case Phone.TYPE_HOME: return R.string.sms_home;
    617                 case Phone.TYPE_MOBILE: return R.string.sms_mobile;
    618                 case Phone.TYPE_WORK: return R.string.sms_work;
    619                 case Phone.TYPE_FAX_WORK: return R.string.sms_fax_work;
    620                 case Phone.TYPE_FAX_HOME: return R.string.sms_fax_home;
    621                 case Phone.TYPE_PAGER: return R.string.sms_pager;
    622                 case Phone.TYPE_OTHER: return R.string.sms_other;
    623                 case Phone.TYPE_CALLBACK: return R.string.sms_callback;
    624                 case Phone.TYPE_CAR: return R.string.sms_car;
    625                 case Phone.TYPE_COMPANY_MAIN: return R.string.sms_company_main;
    626                 case Phone.TYPE_ISDN: return R.string.sms_isdn;
    627                 case Phone.TYPE_MAIN: return R.string.sms_main;
    628                 case Phone.TYPE_OTHER_FAX: return R.string.sms_other_fax;
    629                 case Phone.TYPE_RADIO: return R.string.sms_radio;
    630                 case Phone.TYPE_TELEX: return R.string.sms_telex;
    631                 case Phone.TYPE_TTY_TDD: return R.string.sms_tty_tdd;
    632                 case Phone.TYPE_WORK_MOBILE: return R.string.sms_work_mobile;
    633                 case Phone.TYPE_WORK_PAGER: return R.string.sms_work_pager;
    634                 case Phone.TYPE_ASSISTANT: return R.string.sms_assistant;
    635                 case Phone.TYPE_MMS: return R.string.sms_mms;
    636                 default: return R.string.sms_custom;
    637             }
    638         }
    639     }
    640 
    641     public static class EmailActionInflater extends CommonInflater {
    642         @Override
    643         protected int getTypeLabelResource(Integer type) {
    644             if (type == null) return R.string.email;
    645             switch (type) {
    646                 case Email.TYPE_HOME: return R.string.email_home;
    647                 case Email.TYPE_WORK: return R.string.email_work;
    648                 case Email.TYPE_OTHER: return R.string.email_other;
    649                 case Email.TYPE_MOBILE: return R.string.email_mobile;
    650                 default: return R.string.email_custom;
    651             }
    652         }
    653     }
    654 
    655     public static class EventActionInflater extends CommonInflater {
    656         @Override
    657         protected int getTypeLabelResource(Integer type) {
    658             return Event.getTypeResource(type);
    659         }
    660     }
    661 
    662     public static class PostalActionInflater extends CommonInflater {
    663         @Override
    664         protected int getTypeLabelResource(Integer type) {
    665             if (type == null) return R.string.map_other;
    666             switch (type) {
    667                 case StructuredPostal.TYPE_HOME: return R.string.map_home;
    668                 case StructuredPostal.TYPE_WORK: return R.string.map_work;
    669                 case StructuredPostal.TYPE_OTHER: return R.string.map_other;
    670                 default: return R.string.map_custom;
    671             }
    672         }
    673     }
    674 
    675     public static class ImActionInflater extends CommonInflater {
    676         @Override
    677         protected String getTypeColumn() {
    678             return Im.PROTOCOL;
    679         }
    680 
    681         @Override
    682         protected String getLabelColumn() {
    683             return Im.CUSTOM_PROTOCOL;
    684         }
    685 
    686         @Override
    687         protected int getTypeLabelResource(Integer type) {
    688             if (type == null) return R.string.chat;
    689             switch (type) {
    690                 case Im.PROTOCOL_AIM: return R.string.chat_aim;
    691                 case Im.PROTOCOL_MSN: return R.string.chat_msn;
    692                 case Im.PROTOCOL_YAHOO: return R.string.chat_yahoo;
    693                 case Im.PROTOCOL_SKYPE: return R.string.chat_skype;
    694                 case Im.PROTOCOL_QQ: return R.string.chat_qq;
    695                 case Im.PROTOCOL_GOOGLE_TALK: return R.string.chat_gtalk;
    696                 case Im.PROTOCOL_ICQ: return R.string.chat_icq;
    697                 case Im.PROTOCOL_JABBER: return R.string.chat_jabber;
    698                 case Im.PROTOCOL_NETMEETING: return R.string.chat;
    699                 default: return R.string.chat;
    700             }
    701         }
    702     }
    703 
    704     @Override
    705     public int getHeaderColor(Context context) {
    706         return 0xff7f93bc;
    707     }
    708 
    709     @Override
    710     public int getSideBarColor(Context context) {
    711         return 0xffbdc7b8;
    712     }
    713 }
    714