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