BrowserBookmarksPage.java revision c3c46d7731006ba78497c61aa4fec34d58ac182e
1/* 2 * Copyright (C) 2006 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 17package com.android.browser; 18 19import android.app.Activity; 20import android.app.Fragment; 21import android.app.LoaderManager; 22import android.content.ClipData; 23import android.content.ClipboardManager; 24import android.content.ContentUris; 25import android.content.Context; 26import android.content.CursorLoader; 27import android.content.Intent; 28import android.content.Loader; 29import android.content.SharedPreferences; 30import android.content.res.Configuration; 31import android.content.res.Resources; 32import android.database.Cursor; 33import android.graphics.Bitmap; 34import android.graphics.BitmapFactory; 35import android.net.Uri; 36import android.os.AsyncTask; 37import android.os.Bundle; 38import android.provider.BrowserContract; 39import android.provider.BrowserContract.Accounts; 40import android.provider.BrowserContract.ChromeSyncColumns; 41import android.view.ActionMode; 42import android.view.ContextMenu; 43import android.view.ContextMenu.ContextMenuInfo; 44import android.view.LayoutInflater; 45import android.view.MenuInflater; 46import android.view.MenuItem; 47import android.view.View; 48import android.view.ViewGroup; 49import android.widget.ExpandableListView; 50import android.widget.ExpandableListView.OnChildClickListener; 51import android.widget.ImageView; 52import android.widget.LinearLayout; 53import android.widget.Toast; 54 55import com.android.browser.BookmarkDragHandler.BookmarkDragController; 56import com.android.browser.BookmarkDragHandler.BookmarkDragState; 57import com.android.browser.provider.BrowserProvider2; 58import com.android.browser.view.BookmarkExpandableView; 59import com.android.browser.view.BookmarkExpandableView.BookmarkContextMenuInfo; 60 61import org.json.JSONException; 62import org.json.JSONObject; 63 64import java.util.HashMap; 65 66interface BookmarksPageCallbacks { 67 // Return true if handled 68 boolean onBookmarkSelected(Cursor c, boolean isFolder); 69 // Return true if handled 70 boolean onOpenInNewWindow(String... urls); 71} 72 73/** 74 * View showing the user's bookmarks in the browser. 75 */ 76public class BrowserBookmarksPage extends Fragment implements View.OnCreateContextMenuListener, 77 LoaderManager.LoaderCallbacks<Cursor>, BreadCrumbView.Controller, 78 OnChildClickListener { 79 80 public static class ExtraDragState { 81 public int childPosition; 82 public int groupPosition; 83 } 84 85 static final String LOGTAG = "browser"; 86 87 static final int LOADER_ACCOUNTS = 1; 88 static final int LOADER_BOOKMARKS = 100; 89 90 static final String EXTRA_DISABLE_WINDOW = "disable_new_window"; 91 static final String PREF_GROUP_STATE = "bbp_group_state"; 92 93 static final String ACCOUNT_TYPE = "account_type"; 94 static final String ACCOUNT_NAME = "account_name"; 95 96 public static final int VIEW_THUMBNAILS = 1; 97 public static final int VIEW_LIST = 2; 98 99 BookmarksPageCallbacks mCallbacks; 100 View mRoot; 101 BookmarkExpandableView mGrid; 102 boolean mDisableNewWindow; 103 boolean mEnableContextMenu = true; 104 View mEmptyView; 105 View mHeader; 106 HashMap<Integer, BrowserBookmarksAdapter> mBookmarkAdapters = new HashMap<Integer, BrowserBookmarksAdapter>(); 107 BookmarkDragHandler mDragHandler; 108 JSONObject mState; 109 110 @Override 111 public Loader<Cursor> onCreateLoader(int id, Bundle args) { 112 if (id == LOADER_ACCOUNTS) { 113 return new AccountsLoader(getActivity()); 114 } else if (id >= LOADER_BOOKMARKS) { 115 String accountType = args.getString(ACCOUNT_TYPE); 116 String accountName = args.getString(ACCOUNT_NAME); 117 BookmarksLoader bl = new BookmarksLoader(getActivity(), 118 accountType, accountName); 119 return bl; 120 } else { 121 throw new UnsupportedOperationException("Unknown loader id " + id); 122 } 123 } 124 125 @Override 126 public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { 127 if (loader.getId() == LOADER_ACCOUNTS) { 128 LoaderManager lm = getLoaderManager(); 129 int id = LOADER_BOOKMARKS; 130 while (cursor.moveToNext()) { 131 String accountName = cursor.getString(0); 132 String accountType = cursor.getString(1); 133 Bundle args = new Bundle(); 134 args.putString(ACCOUNT_NAME, accountName); 135 args.putString(ACCOUNT_TYPE, accountType); 136 BrowserBookmarksAdapter adapter = new BrowserBookmarksAdapter( 137 getActivity(), VIEW_THUMBNAILS); 138 mBookmarkAdapters.put(id, adapter); 139 boolean expand = true; 140 try { 141 expand = mState.getBoolean(accountName != null ? accountName 142 : BookmarkExpandableView.LOCAL_ACCOUNT_NAME); 143 } catch (JSONException e) {} // no state for accountName 144 mGrid.addAccount(accountName, adapter, expand); 145 lm.restartLoader(id, args, this); 146 id++; 147 } 148 // TODO: Figure out what a reload of these means 149 // Currently, a reload is triggered whenever bookmarks change 150 // This is less than ideal 151 // It also causes UI flickering as a new adapter is created 152 // instead of re-using an existing one when the account_name is the 153 // same. 154 // For now, this is a one-shot load 155 getLoaderManager().destroyLoader(LOADER_ACCOUNTS); 156 } else if (loader.getId() >= LOADER_BOOKMARKS) { 157 BrowserBookmarksAdapter adapter = mBookmarkAdapters.get(loader.getId()); 158 adapter.changeCursor(cursor); 159 } 160 } 161 162 @Override 163 public void onLoaderReset(Loader<Cursor> loader) { 164 } 165 166 @Override 167 public boolean onContextItemSelected(MenuItem item) { 168 if (!(item.getMenuInfo() instanceof BookmarkContextMenuInfo)) { 169 return false; 170 } 171 BookmarkContextMenuInfo i = (BookmarkContextMenuInfo) item.getMenuInfo(); 172 // If we have no menu info, we can't tell which item was selected. 173 if (i == null) { 174 return false; 175 } 176 177 if (handleContextItem(item.getItemId(), i.groupPosition, i.childPosition)) { 178 return true; 179 } 180 return super.onContextItemSelected(item); 181 } 182 183 public boolean handleContextItem(int itemId, int groupPosition, 184 int childPosition) { 185 final Activity activity = getActivity(); 186 BrowserBookmarksAdapter adapter = getChildAdapter(groupPosition); 187 188 switch (itemId) { 189 case R.id.open_context_menu_id: 190 loadUrl(adapter, childPosition); 191 break; 192 case R.id.edit_context_menu_id: 193 editBookmark(adapter, childPosition); 194 break; 195 case R.id.shortcut_context_menu_id: 196 Cursor c = adapter.getItem(childPosition); 197 activity.sendBroadcast(createShortcutIntent(getActivity(), c)); 198 break; 199 case R.id.delete_context_menu_id: 200 displayRemoveBookmarkDialog(adapter, childPosition); 201 break; 202 case R.id.new_window_context_menu_id: 203 openInNewWindow(adapter, childPosition); 204 break; 205 case R.id.share_link_context_menu_id: { 206 Cursor cursor = adapter.getItem(childPosition); 207 Controller.sharePage(activity, 208 cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE), 209 cursor.getString(BookmarksLoader.COLUMN_INDEX_URL), 210 getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_FAVICON), 211 getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_THUMBNAIL)); 212 break; 213 } 214 case R.id.copy_url_context_menu_id: 215 copy(getUrl(adapter, childPosition)); 216 break; 217 case R.id.homepage_context_menu_id: { 218 BrowserSettings.getInstance().setHomePage(getUrl(adapter, childPosition)); 219 Toast.makeText(activity, R.string.homepage_set, Toast.LENGTH_LONG).show(); 220 break; 221 } 222 // Only for the Most visited page 223 case R.id.save_to_bookmarks_menu_id: { 224 Cursor cursor = adapter.getItem(childPosition); 225 String name = cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE); 226 String url = cursor.getString(BookmarksLoader.COLUMN_INDEX_URL); 227 // If the site is bookmarked, the item becomes remove from 228 // bookmarks. 229 Bookmarks.removeFromBookmarks(activity, activity.getContentResolver(), url, name); 230 break; 231 } 232 default: 233 return false; 234 } 235 return true; 236 } 237 238 static Bitmap getBitmap(Cursor cursor, int columnIndex) { 239 byte[] data = cursor.getBlob(columnIndex); 240 if (data == null) { 241 return null; 242 } 243 return BitmapFactory.decodeByteArray(data, 0, data.length); 244 } 245 246 private MenuItem.OnMenuItemClickListener mContextItemClickListener = 247 new MenuItem.OnMenuItemClickListener() { 248 @Override 249 public boolean onMenuItemClick(MenuItem item) { 250 return onContextItemSelected(item); 251 } 252 }; 253 254 @Override 255 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { 256 BookmarkContextMenuInfo info = (BookmarkContextMenuInfo) menuInfo; 257 BrowserBookmarksAdapter adapter = getChildAdapter(info.groupPosition); 258 Cursor cursor = adapter.getItem(info.childPosition); 259 if (!canEdit(cursor)) { 260 return; 261 } 262 boolean isFolder 263 = cursor.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) != 0; 264 265 final Activity activity = getActivity(); 266 MenuInflater inflater = activity.getMenuInflater(); 267 inflater.inflate(R.menu.bookmarkscontext, menu); 268 if (isFolder) { 269 menu.setGroupVisible(R.id.FOLDER_CONTEXT_MENU, true); 270 } else { 271 menu.setGroupVisible(R.id.BOOKMARK_CONTEXT_MENU, true); 272 if (mDisableNewWindow) { 273 menu.findItem(R.id.new_window_context_menu_id).setVisible(false); 274 } 275 } 276 BookmarkItem header = new BookmarkItem(activity); 277 populateBookmarkItem(cursor, header, isFolder); 278 menu.setHeaderView(header); 279 280 int count = menu.size(); 281 for (int i = 0; i < count; i++) { 282 menu.getItem(i).setOnMenuItemClickListener(mContextItemClickListener); 283 } 284 } 285 286 boolean canEdit(Cursor c) { 287 String unique = c.getString(BookmarksLoader.COLUMN_INDEX_SERVER_UNIQUE); 288 return !ChromeSyncColumns.FOLDER_NAME_OTHER_BOOKMARKS.equals(unique); 289 } 290 291 private void populateBookmarkItem(Cursor cursor, BookmarkItem item, boolean isFolder) { 292 item.setName(cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE)); 293 if (isFolder) { 294 item.setUrl(null); 295 Bitmap bitmap = 296 BitmapFactory.decodeResource(getResources(), R.drawable.ic_folder_holo_dark); 297 item.setFavicon(bitmap); 298 new LookupBookmarkCount(getActivity(), item) 299 .execute(cursor.getLong(BookmarksLoader.COLUMN_INDEX_ID)); 300 } else { 301 String url = cursor.getString(BookmarksLoader.COLUMN_INDEX_URL); 302 item.setUrl(url); 303 Bitmap bitmap = getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_FAVICON); 304 item.setFavicon(bitmap); 305 } 306 } 307 308 /** 309 * Create a new BrowserBookmarksPage. 310 */ 311 @Override 312 public void onCreate(Bundle icicle) { 313 super.onCreate(icicle); 314 SharedPreferences prefs = BrowserSettings.getInstance().getPreferences(); 315 try { 316 mState = new JSONObject(prefs.getString(PREF_GROUP_STATE, "{}")); 317 } catch (JSONException e) { 318 // Parse failed, clear preference and start with empty state 319 prefs.edit().remove(PREF_GROUP_STATE).apply(); 320 mState = new JSONObject(); 321 } 322 Bundle args = getArguments(); 323 mDisableNewWindow = args == null ? false : args.getBoolean(EXTRA_DISABLE_WINDOW, false); 324 setHasOptionsMenu(true); 325 if (mCallbacks == null && getActivity() instanceof CombinedBookmarksCallbacks) { 326 mCallbacks = new CombinedBookmarksCallbackWrapper( 327 (CombinedBookmarksCallbacks) getActivity()); 328 } 329 } 330 331 @Override 332 public void onPause() { 333 super.onPause(); 334 try { 335 mState = mGrid.saveGroupState(); 336 // Save state 337 SharedPreferences prefs = BrowserSettings.getInstance().getPreferences(); 338 prefs.edit() 339 .putString(PREF_GROUP_STATE, mState.toString()) 340 .apply(); 341 } catch (JSONException e) { 342 // Not critical, ignore 343 } 344 } 345 346 private static class CombinedBookmarksCallbackWrapper 347 implements BookmarksPageCallbacks { 348 349 private CombinedBookmarksCallbacks mCombinedCallback; 350 351 private CombinedBookmarksCallbackWrapper(CombinedBookmarksCallbacks cb) { 352 mCombinedCallback = cb; 353 } 354 355 @Override 356 public boolean onOpenInNewWindow(String... urls) { 357 mCombinedCallback.openInNewTab(urls); 358 return true; 359 } 360 361 @Override 362 public boolean onBookmarkSelected(Cursor c, boolean isFolder) { 363 if (isFolder) { 364 return false; 365 } 366 mCombinedCallback.openUrl(BrowserBookmarksPage.getUrl(c)); 367 return true; 368 } 369 }; 370 371 @Override 372 public View onCreateView(LayoutInflater inflater, ViewGroup container, 373 Bundle savedInstanceState) { 374 mRoot = inflater.inflate(R.layout.bookmarks, container, false); 375 mEmptyView = mRoot.findViewById(android.R.id.empty); 376 377 mGrid = (BookmarkExpandableView) mRoot.findViewById(R.id.grid); 378 mGrid.setOnChildClickListener(this); 379 mGrid.setColumnWidthFromLayout(R.layout.bookmark_thumbnail); 380 mGrid.setBreadcrumbController(this); 381 setEnableContextMenu(mEnableContextMenu); 382 mDragHandler = new BookmarkDragHandler(getActivity(), mDragController, 383 mGrid.getDragAdapter()); 384 385 // Start the loaders 386 LoaderManager lm = getLoaderManager(); 387 lm.restartLoader(LOADER_ACCOUNTS, null, this); 388 389 return mRoot; 390 } 391 392 @Override 393 public void onDestroyView() { 394 super.onDestroyView(); 395 mGrid.setBreadcrumbController(null); 396 mGrid.clearAccounts(); 397 LoaderManager lm = getLoaderManager(); 398 lm.destroyLoader(LOADER_ACCOUNTS); 399 for (int id : mBookmarkAdapters.keySet()) { 400 lm.destroyLoader(id); 401 } 402 mBookmarkAdapters.clear(); 403 } 404 405 private BrowserBookmarksAdapter getChildAdapter(int groupPosition) { 406 return mGrid.getChildAdapter(groupPosition); 407 } 408 409 private BreadCrumbView getBreadCrumbs(int groupPosition) { 410 return mGrid.getBreadCrumbs(groupPosition); 411 } 412 413 @Override 414 public boolean onChildClick(ExpandableListView parent, View v, 415 int groupPosition, int childPosition, long id) { 416 BrowserBookmarksAdapter adapter = getChildAdapter(groupPosition); 417 Cursor cursor = adapter.getItem(childPosition); 418 boolean isFolder = cursor.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) != 0; 419 if (mCallbacks != null && 420 mCallbacks.onBookmarkSelected(cursor, isFolder)) { 421 return true; 422 } 423 424 // TODO: Folder stuff 425 if (isFolder) { 426 String title = cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE); 427 Uri uri = ContentUris.withAppendedId( 428 BrowserContract.Bookmarks.CONTENT_URI_DEFAULT_FOLDER, id); 429 BreadCrumbView crumbs = getBreadCrumbs(groupPosition); 430 if (crumbs != null) { 431 // update crumbs 432 crumbs.pushView(title, uri); 433 } 434 loadFolder(groupPosition, uri); 435 } 436 return true; 437 } 438 439 /* package */ static Intent createShortcutIntent(Context context, Cursor cursor) { 440 String url = cursor.getString(BookmarksLoader.COLUMN_INDEX_URL); 441 String title = cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE); 442 Bitmap touchIcon = getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_TOUCH_ICON); 443 Bitmap favicon = getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_FAVICON); 444 return BookmarkUtils.createAddToHomeIntent(context, url, title, touchIcon, favicon); 445 } 446 447 private void loadUrl(BrowserBookmarksAdapter adapter, int position) { 448 if (mCallbacks != null && adapter != null) { 449 mCallbacks.onBookmarkSelected(adapter.getItem(position), false); 450 } 451 } 452 453 private void openInNewWindow(BrowserBookmarksAdapter adapter, int position) { 454 if (mCallbacks != null) { 455 Cursor c = adapter.getItem(position); 456 boolean isFolder = c.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) == 1; 457 if (isFolder) { 458 long id = c.getLong(BookmarksLoader.COLUMN_INDEX_ID); 459 new OpenAllInTabsTask(id).execute(); 460 } else { 461 mCallbacks.onOpenInNewWindow(BrowserBookmarksPage.getUrl(c)); 462 } 463 } 464 } 465 466 class OpenAllInTabsTask extends AsyncTask<Void, Void, Cursor> { 467 long mFolderId; 468 public OpenAllInTabsTask(long id) { 469 mFolderId = id; 470 } 471 472 @Override 473 protected Cursor doInBackground(Void... params) { 474 Context c = getActivity(); 475 if (c == null) return null; 476 return c.getContentResolver().query(BookmarkUtils.getBookmarksUri(c), 477 BookmarksLoader.PROJECTION, BrowserContract.Bookmarks.PARENT + "=?", 478 new String[] { Long.toString(mFolderId) }, null); 479 } 480 481 @Override 482 protected void onPostExecute(Cursor result) { 483 if (mCallbacks != null && result.getCount() > 0) { 484 String[] urls = new String[result.getCount()]; 485 int i = 0; 486 while (result.moveToNext()) { 487 urls[i++] = BrowserBookmarksPage.getUrl(result); 488 } 489 mCallbacks.onOpenInNewWindow(urls); 490 } 491 } 492 493 } 494 495 private void editBookmark(BrowserBookmarksAdapter adapter, int position) { 496 Intent intent = new Intent(getActivity(), AddBookmarkPage.class); 497 Cursor cursor = adapter.getItem(position); 498 Bundle item = new Bundle(); 499 item.putString(BrowserContract.Bookmarks.TITLE, 500 cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE)); 501 item.putString(BrowserContract.Bookmarks.URL, 502 cursor.getString(BookmarksLoader.COLUMN_INDEX_URL)); 503 byte[] data = cursor.getBlob(BookmarksLoader.COLUMN_INDEX_FAVICON); 504 if (data != null) { 505 item.putParcelable(BrowserContract.Bookmarks.FAVICON, 506 BitmapFactory.decodeByteArray(data, 0, data.length)); 507 } 508 item.putLong(BrowserContract.Bookmarks._ID, 509 cursor.getLong(BookmarksLoader.COLUMN_INDEX_ID)); 510 item.putLong(BrowserContract.Bookmarks.PARENT, 511 cursor.getLong(BookmarksLoader.COLUMN_INDEX_PARENT)); 512 intent.putExtra(AddBookmarkPage.EXTRA_EDIT_BOOKMARK, item); 513 intent.putExtra(AddBookmarkPage.EXTRA_IS_FOLDER, 514 cursor.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) == 1); 515 startActivity(intent); 516 } 517 518 private void displayRemoveBookmarkDialog(BrowserBookmarksAdapter adapter, 519 int position) { 520 // Put up a dialog asking if the user really wants to 521 // delete the bookmark 522 Cursor cursor = adapter.getItem(position); 523 long id = cursor.getLong(BookmarksLoader.COLUMN_INDEX_ID); 524 String title = cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE); 525 Context context = getActivity(); 526 BookmarkUtils.displayRemoveBookmarkDialog(id, title, context, null); 527 } 528 529 private String getUrl(BrowserBookmarksAdapter adapter, int position) { 530 return getUrl(adapter.getItem(position)); 531 } 532 533 /* package */ static String getUrl(Cursor c) { 534 return c.getString(BookmarksLoader.COLUMN_INDEX_URL); 535 } 536 537 private void copy(CharSequence text) { 538 ClipboardManager cm = (ClipboardManager) getActivity().getSystemService( 539 Context.CLIPBOARD_SERVICE); 540 cm.setPrimaryClip(ClipData.newRawUri(null, Uri.parse(text.toString()))); 541 } 542 543 @Override 544 public void onConfigurationChanged(Configuration newConfig) { 545 super.onConfigurationChanged(newConfig); 546 Resources res = getActivity().getResources(); 547 mGrid.setColumnWidthFromLayout(R.layout.bookmark_thumbnail); 548 int paddingTop = (int) res.getDimension(R.dimen.combo_paddingTop); 549 mRoot.setPadding(0, paddingTop, 0, 0); 550 getActivity().invalidateOptionsMenu(); 551 } 552 553 /** 554 * BreadCrumb controller callback 555 */ 556 @Override 557 public void onTop(BreadCrumbView view, int level, Object data) { 558 int groupPosition = (Integer) view.getTag(R.id.group_position); 559 Uri uri = (Uri) data; 560 if (uri == null) { 561 // top level 562 uri = BrowserContract.Bookmarks.CONTENT_URI_DEFAULT_FOLDER; 563 } 564 loadFolder(groupPosition, uri); 565 } 566 567 /** 568 * @param uri 569 */ 570 private void loadFolder(int groupPosition, Uri uri) { 571 LoaderManager manager = getLoaderManager(); 572 // This assumes groups are ordered the same as loaders 573 BookmarksLoader loader = (BookmarksLoader) ((Loader<?>) 574 manager.getLoader(LOADER_BOOKMARKS + groupPosition)); 575 loader.setUri(uri); 576 loader.forceLoad(); 577 } 578 579 public void setCallbackListener(BookmarksPageCallbacks callbackListener) { 580 mCallbacks = callbackListener; 581 } 582 583 public void setEnableContextMenu(boolean enable) { 584 mEnableContextMenu = enable; 585 if (mGrid != null) { 586 if (mEnableContextMenu) { 587 registerForContextMenu(mGrid); 588 } else { 589 unregisterForContextMenu(mGrid); 590 mGrid.setLongClickable(false); 591 } 592 } 593 } 594 595 private BookmarkDragController mDragController = new BookmarkDragController() { 596 597 @Override 598 public boolean startDrag(Cursor item) { 599 return canEdit(item); 600 } 601 602 @Override 603 public ViewGroup getActionModeView(ActionMode mode, 604 BookmarkDragState state) { 605 LayoutInflater inflater = LayoutInflater.from(getActivity()); 606 LinearLayout view = (LinearLayout) inflater.inflate( 607 R.layout.bookmarks_drag_actionmode, null); 608 view.setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE); 609 ExtraDragState extraState = (ExtraDragState) state.extraState; 610 BrowserBookmarksAdapter adapter = getChildAdapter(extraState.groupPosition); 611 Cursor c = adapter.getItem(extraState.childPosition); 612 boolean isFolder = c.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) != 0; 613 if (isFolder) { 614 view.findViewById(R.id.open_context_menu_id).setVisibility(View.GONE); 615 ImageView iv = (ImageView) view.findViewById( 616 R.id.new_window_context_menu_id); 617 iv.setImageResource(R.drawable.ic_windows_holo_dark); 618 } 619 return view; 620 } 621 622 @Override 623 public void actionItemClicked(View v, BookmarkDragState state) { 624 if (v.getId() == R.id.info) { 625 mGrid.showContextMenuForState(state); 626 } else { 627 ExtraDragState extraState = (ExtraDragState) state.extraState; 628 handleContextItem(v.getId(), extraState.groupPosition, 629 extraState.childPosition); 630 } 631 } 632 }; 633 634 private static class LookupBookmarkCount extends AsyncTask<Long, Void, Integer> { 635 Context mContext; 636 BookmarkItem mHeader; 637 638 public LookupBookmarkCount(Context context, BookmarkItem header) { 639 mContext = context.getApplicationContext(); 640 mHeader = header; 641 } 642 643 @Override 644 protected Integer doInBackground(Long... params) { 645 if (params.length != 1) { 646 throw new IllegalArgumentException("Missing folder id!"); 647 } 648 Uri uri = BookmarkUtils.getBookmarksUri(mContext); 649 Cursor c = mContext.getContentResolver().query(uri, 650 null, BrowserContract.Bookmarks.PARENT + "=?", 651 new String[] {params[0].toString()}, null); 652 return c.getCount(); 653 } 654 655 @Override 656 protected void onPostExecute(Integer result) { 657 if (result > 0) { 658 mHeader.setUrl(mContext.getString(R.string.contextheader_folder_bookmarkcount, 659 result)); 660 } else if (result == 0) { 661 mHeader.setUrl(mContext.getString(R.string.contextheader_folder_empty)); 662 } 663 } 664 } 665 666 static class AccountsLoader extends CursorLoader { 667 668 static String[] ACCOUNTS_PROJECTION = new String[] { 669 Accounts.ACCOUNT_NAME, 670 Accounts.ACCOUNT_TYPE 671 }; 672 673 public AccountsLoader(Context context) { 674 super(context, Accounts.CONTENT_URI 675 .buildUpon() 676 .appendQueryParameter(BrowserProvider2.PARAM_ALLOW_EMPTY_ACCOUNTS, "false") 677 .build(), 678 ACCOUNTS_PROJECTION, null, null, null); 679 } 680 681 } 682} 683