blob: e2c09cfb8fc54b10701ade63b5f678121c73382d [file] [log] [blame]
The Android Open Source Project0c908882009-03-03 19:32:16 -08001/*
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.content.ContentResolver;
20import android.content.ContentUris;
21import android.content.ContentValues;
22import android.database.ContentObserver;
23import android.database.Cursor;
24import android.database.DataSetObserver;
25import android.graphics.Bitmap;
26import android.graphics.BitmapFactory;
27import android.net.Uri;
28import android.os.Bundle;
29import android.os.Handler;
30import android.provider.Browser;
31import android.provider.Browser.BookmarkColumns;
32import android.view.KeyEvent;
Leon Scroggins892df312009-07-14 14:48:02 -040033import android.view.LayoutInflater;
The Android Open Source Project0c908882009-03-03 19:32:16 -080034import android.view.View;
35import android.view.ViewGroup;
36import android.webkit.WebIconDatabase;
37import android.webkit.WebIconDatabase.IconListener;
Patrick Scott3918d442009-08-04 13:22:29 -040038import android.webkit.WebView;
The Android Open Source Project0c908882009-03-03 19:32:16 -080039import android.widget.BaseAdapter;
Leon Scroggins892df312009-07-14 14:48:02 -040040import android.widget.ImageView;
41import android.widget.TextView;
The Android Open Source Project0c908882009-03-03 19:32:16 -080042
43import java.io.ByteArrayOutputStream;
44
45class BrowserBookmarksAdapter extends BaseAdapter {
46
The Android Open Source Project0c908882009-03-03 19:32:16 -080047 private String mCurrentPage;
Leon Scroggins89c6d362009-07-15 16:54:37 -040048 private String mCurrentTitle;
The Android Open Source Project0c908882009-03-03 19:32:16 -080049 private Cursor mCursor;
50 private int mCount;
The Android Open Source Project0c908882009-03-03 19:32:16 -080051 private BrowserBookmarksPage mBookmarksPage;
52 private ContentResolver mContentResolver;
The Android Open Source Project0c908882009-03-03 19:32:16 -080053 private boolean mDataValid;
Ben Murdoch328ea872009-09-16 13:33:29 +010054 private BookmarkViewMode mViewMode;
Leon Scrogginsa5d669e2009-08-05 14:07:58 -040055 private boolean mMostVisited;
56 private boolean mNeedsOffset;
57 private int mExtraOffset;
The Android Open Source Project0c908882009-03-03 19:32:16 -080058
59 // Implementation of WebIconDatabase.IconListener
60 private class IconReceiver implements IconListener {
61 public void onReceivedIcon(String url, Bitmap icon) {
Patrick Scott3918d442009-08-04 13:22:29 -040062 updateBookmarkFavicon(mContentResolver, null, url, icon);
The Android Open Source Project0c908882009-03-03 19:32:16 -080063 }
64 }
65
66 // Instance of IconReceiver
67 private final IconReceiver mIconReceiver = new IconReceiver();
68
69 /**
70 * Create a new BrowserBookmarksAdapter.
The Android Open Source Project0c908882009-03-03 19:32:16 -080071 * @param b BrowserBookmarksPage that instantiated this.
72 * Necessary so it will adjust its focus
73 * appropriately after a search.
74 */
75 public BrowserBookmarksAdapter(BrowserBookmarksPage b, String curPage,
Leon Scrogginsa5d669e2009-08-05 14:07:58 -040076 String curTitle, boolean createShortcut, boolean mostVisited) {
77 mNeedsOffset = !(createShortcut || mostVisited);
78 mMostVisited = mostVisited;
79 mExtraOffset = mNeedsOffset ? 1 : 0;
The Android Open Source Project0c908882009-03-03 19:32:16 -080080 mBookmarksPage = b;
Leon Scroggins89c6d362009-07-15 16:54:37 -040081 mCurrentPage = b.getResources().getString(R.string.current_page)
82 + curPage;
83 mCurrentTitle = curTitle;
The Android Open Source Project0c908882009-03-03 19:32:16 -080084 mContentResolver = b.getContentResolver();
Ben Murdoch328ea872009-09-16 13:33:29 +010085 mViewMode = BookmarkViewMode.LIST;
Leon Scroggins892df312009-07-14 14:48:02 -040086
Leon Scrogginsa5d669e2009-08-05 14:07:58 -040087 String whereClause;
The Android Open Source Project0c908882009-03-03 19:32:16 -080088 // FIXME: Should have a default sort order that the user selects.
Leon Scroggins892df312009-07-14 14:48:02 -040089 String orderBy = Browser.BookmarkColumns.VISITS + " DESC";
Leon Scrogginsa5d669e2009-08-05 14:07:58 -040090 if (mostVisited) {
91 whereClause = Browser.BookmarkColumns.VISITS + " != 0";
92 } else {
93 whereClause = Browser.BookmarkColumns.BOOKMARK + " != 0";
94 }
Leon Scroggins892df312009-07-14 14:48:02 -040095 mCursor = b.managedQuery(Browser.BOOKMARKS_URI,
96 Browser.HISTORY_PROJECTION, whereClause, null, orderBy);
97 mCursor.registerContentObserver(new ChangeObserver());
98 mCursor.registerDataSetObserver(new MyDataSetObserver());
99
100 mDataValid = true;
101 notifyDataSetChanged();
102
103 mCount = mCursor.getCount() + mExtraOffset;
104
The Android Open Source Project0c908882009-03-03 19:32:16 -0800105 // FIXME: This requires another query of the database after the
Leon Scroggins89c6d362009-07-15 16:54:37 -0400106 // managedQuery. Can we optimize this?
The Android Open Source Project0c908882009-03-03 19:32:16 -0800107 Browser.requestAllIcons(mContentResolver,
108 Browser.BookmarkColumns.FAVICON + " is NULL AND " +
109 Browser.BookmarkColumns.BOOKMARK + " == 1", mIconReceiver);
110 }
111
112 /**
113 * Return a hashmap with one row's Title, Url, and favicon.
114 * @param position Position in the list.
115 * @return Bundle Stores title, url of row position, favicon, and id
116 * for the url. Return a blank map if position is out of
117 * range.
118 */
119 public Bundle getRow(int position) {
120 Bundle map = new Bundle();
121 if (position < mExtraOffset || position >= mCount) {
122 return map;
123 }
124 mCursor.moveToPosition(position- mExtraOffset);
125 String url = mCursor.getString(Browser.HISTORY_PROJECTION_URL_INDEX);
126 map.putString(Browser.BookmarkColumns.TITLE,
127 mCursor.getString(Browser.HISTORY_PROJECTION_TITLE_INDEX));
128 map.putString(Browser.BookmarkColumns.URL, url);
129 byte[] data = mCursor.getBlob(Browser.HISTORY_PROJECTION_FAVICON_INDEX);
130 if (data != null) {
131 map.putParcelable(Browser.BookmarkColumns.FAVICON,
132 BitmapFactory.decodeByteArray(data, 0, data.length));
133 }
134 map.putInt("id", mCursor.getInt(Browser.HISTORY_PROJECTION_ID_INDEX));
135 return map;
136 }
137
138 /**
139 * Update a row in the database with new information.
140 * Requeries the database if the information has changed.
141 * @param map Bundle storing id, title and url of new information
142 */
143 public void updateRow(Bundle map) {
144
145 // Find the record
146 int id = map.getInt("id");
147 int position = -1;
148 for (mCursor.moveToFirst(); !mCursor.isAfterLast(); mCursor.moveToNext()) {
149 if (mCursor.getInt(Browser.HISTORY_PROJECTION_ID_INDEX) == id) {
150 position = mCursor.getPosition();
151 break;
152 }
153 }
154 if (position < 0) {
155 return;
156 }
157
158 mCursor.moveToPosition(position);
159 ContentValues values = new ContentValues();
160 String title = map.getString(Browser.BookmarkColumns.TITLE);
161 if (!title.equals(mCursor
162 .getString(Browser.HISTORY_PROJECTION_TITLE_INDEX))) {
163 values.put(Browser.BookmarkColumns.TITLE, title);
164 }
165 String url = map.getString(Browser.BookmarkColumns.URL);
166 if (!url.equals(mCursor.
167 getString(Browser.HISTORY_PROJECTION_URL_INDEX))) {
168 values.put(Browser.BookmarkColumns.URL, url);
169 }
170 if (values.size() > 0
171 && mContentResolver.update(Browser.BOOKMARKS_URI, values,
172 "_id = " + id, null) != -1) {
173 refreshList();
174 }
175 }
176
177 /**
178 * Delete a row from the database. Requeries the database.
179 * Does nothing if the provided position is out of range.
180 * @param position Position in the list.
181 */
182 public void deleteRow(int position) {
183 if (position < mExtraOffset || position >= getCount()) {
184 return;
185 }
186 mCursor.moveToPosition(position- mExtraOffset);
187 String url = mCursor.getString(Browser.HISTORY_PROJECTION_URL_INDEX);
Leon Scrogginse372c022009-06-12 17:07:29 -0400188 Bookmarks.removeFromBookmarks(null, mContentResolver, url);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800189 refreshList();
190 }
191
192 /**
193 * Delete all bookmarks from the db. Requeries the database.
194 * All bookmarks with become visited URLs or if never visited
195 * are removed
196 */
197 public void deleteAllRows() {
198 StringBuilder deleteIds = null;
199 StringBuilder convertIds = null;
200
201 for (mCursor.moveToFirst(); !mCursor.isAfterLast(); mCursor.moveToNext()) {
202 String url = mCursor.getString(Browser.HISTORY_PROJECTION_URL_INDEX);
203 WebIconDatabase.getInstance().releaseIconForPageUrl(url);
204 int id = mCursor.getInt(Browser.HISTORY_PROJECTION_ID_INDEX);
205 int numVisits = mCursor.getInt(Browser.HISTORY_PROJECTION_VISITS_INDEX);
206 if (0 == numVisits) {
207 if (deleteIds == null) {
208 deleteIds = new StringBuilder();
209 deleteIds.append("( ");
210 } else {
211 deleteIds.append(" OR ( ");
212 }
213 deleteIds.append(BookmarkColumns._ID);
214 deleteIds.append(" = ");
215 deleteIds.append(id);
216 deleteIds.append(" )");
217 } else {
218 // It is no longer a bookmark, but it is still a visited site.
219 if (convertIds == null) {
220 convertIds = new StringBuilder();
221 convertIds.append("( ");
222 } else {
223 convertIds.append(" OR ( ");
224 }
225 convertIds.append(BookmarkColumns._ID);
226 convertIds.append(" = ");
227 convertIds.append(id);
228 convertIds.append(" )");
229 }
230 }
231
232 if (deleteIds != null) {
233 mContentResolver.delete(Browser.BOOKMARKS_URI, deleteIds.toString(),
234 null);
235 }
236 if (convertIds != null) {
237 ContentValues values = new ContentValues();
238 values.put(Browser.BookmarkColumns.BOOKMARK, 0);
239 mContentResolver.update(Browser.BOOKMARKS_URI, values,
240 convertIds.toString(), null);
241 }
242 refreshList();
243 }
244
245 /**
246 * Refresh list to recognize a change in the database.
247 */
248 public void refreshList() {
Leon Scroggins892df312009-07-14 14:48:02 -0400249 mCursor.requery();
250 mCount = mCursor.getCount() + mExtraOffset;
251 notifyDataSetChanged();
The Android Open Source Project0c908882009-03-03 19:32:16 -0800252 }
253
254 /**
Patrick Scott3918d442009-08-04 13:22:29 -0400255 * Update the bookmark's favicon. This is a convenience method for updating
256 * a bookmark favicon for the originalUrl and url of the passed in WebView.
The Android Open Source Project0c908882009-03-03 19:32:16 -0800257 * @param cr The ContentResolver to use.
Patrick Scott3918d442009-08-04 13:22:29 -0400258 * @param WebView The WebView containing the url to update.
The Android Open Source Project0c908882009-03-03 19:32:16 -0800259 * @param favicon The favicon bitmap to write to the db.
260 */
261 /* package */ static void updateBookmarkFavicon(ContentResolver cr,
Patrick Scott3918d442009-08-04 13:22:29 -0400262 WebView view, Bitmap favicon) {
263 if (view != null) {
264 updateBookmarkFavicon(cr, view.getOriginalUrl(), view.getUrl(),
265 favicon);
266 }
267 }
268
269 private static void updateBookmarkFavicon(ContentResolver cr,
270 String originalUrl, String url, Bitmap favicon) {
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400271 final Cursor c = queryBookmarksForUrl(cr, originalUrl, url, true);
Patrick Scott3918d442009-08-04 13:22:29 -0400272 if (c == null) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800273 return;
274 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800275 boolean succeed = c.moveToFirst();
276 ContentValues values = null;
277 while (succeed) {
278 if (values == null) {
279 final ByteArrayOutputStream os = new ByteArrayOutputStream();
280 favicon.compress(Bitmap.CompressFormat.PNG, 100, os);
281 values = new ContentValues();
282 values.put(Browser.BookmarkColumns.FAVICON, os.toByteArray());
283 }
284 cr.update(ContentUris.withAppendedId(Browser.BOOKMARKS_URI, c
285 .getInt(0)), values, null, null);
286 succeed = c.moveToNext();
287 }
288 c.close();
289 }
290
Patrick Scott3918d442009-08-04 13:22:29 -0400291 /* package */ static Cursor queryBookmarksForUrl(ContentResolver cr,
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400292 String originalUrl, String url, boolean onlyBookmarks) {
Patrick Scott3918d442009-08-04 13:22:29 -0400293 if (cr == null || url == null) {
294 return null;
295 }
296
297 // If originalUrl is null, just set it to url.
298 if (originalUrl == null) {
299 originalUrl = url;
300 }
301
302 // Look for both the original url and the actual url. This takes in to
303 // account redirects.
304 String originalUrlNoQuery = removeQuery(originalUrl);
305 String urlNoQuery = removeQuery(url);
306 originalUrl = originalUrlNoQuery + '?';
307 url = urlNoQuery + '?';
308
309 // Use NoQuery to search for the base url (i.e. if the url is
310 // http://www.yahoo.com/?rs=1, search for http://www.yahoo.com)
311 // Use url to match the base url with other queries (i.e. if the url is
312 // http://www.google.com/m, search for
313 // http://www.google.com/m?some_query)
314 final String[] selArgs = new String[] {
315 originalUrlNoQuery, urlNoQuery, originalUrl, url };
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400316 String where = BookmarkColumns.URL + " == ? OR "
Patrick Scott3918d442009-08-04 13:22:29 -0400317 + BookmarkColumns.URL + " == ? OR "
318 + BookmarkColumns.URL + " GLOB ? || '*' OR "
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400319 + BookmarkColumns.URL + " GLOB ? || '*'";
320 if (onlyBookmarks) {
321 where = "(" + where + ") AND " + BookmarkColumns.BOOKMARK + " == 1";
322 }
Patrick Scott3918d442009-08-04 13:22:29 -0400323 final String[] projection =
324 new String[] { Browser.BookmarkColumns._ID };
325 return cr.query(Browser.BOOKMARKS_URI, projection, where, selArgs,
326 null);
327 }
328
329 // Strip the query from the given url.
330 private static String removeQuery(String url) {
331 if (url == null) {
332 return null;
333 }
334 int query = url.indexOf('?');
335 String noQuery = url;
336 if (query != -1) {
337 noQuery = url.substring(0, query);
338 }
339 return noQuery;
340 }
341
The Android Open Source Project0c908882009-03-03 19:32:16 -0800342 /**
The Android Open Source Project0c908882009-03-03 19:32:16 -0800343 * How many items should be displayed in the list.
344 * @return Count of items.
345 */
346 public int getCount() {
347 if (mDataValid) {
348 return mCount;
349 } else {
350 return 0;
351 }
352 }
353
354 public boolean areAllItemsEnabled() {
355 return true;
356 }
357
358 public boolean isEnabled(int position) {
359 return true;
360 }
361
362 /**
363 * Get the data associated with the specified position in the list.
364 * @param position Index of the item whose data we want.
365 * @return The data at the specified position.
366 */
367 public Object getItem(int position) {
368 return null;
369 }
370
371 /**
372 * Get the row id associated with the specified position in the list.
373 * @param position Index of the item whose row id we want.
374 * @return The id of the item at the specified position.
375 */
376 public long getItemId(int position) {
377 return position;
378 }
379
Ben Murdoch328ea872009-09-16 13:33:29 +0100380 /* package */ void switchViewMode(BookmarkViewMode viewMode) {
381 mViewMode = viewMode;
Leon Scroggins892df312009-07-14 14:48:02 -0400382 }
383
384 /* package */ void populateBookmarkItem(BookmarkItem b, int position) {
385 mCursor.moveToPosition(position - mExtraOffset);
Patrick Scott8f0076b2009-09-17 13:51:30 -0400386 String url = mCursor.getString(Browser.HISTORY_PROJECTION_URL_INDEX);
387 b.setUrl(url);
Leon Scroggins892df312009-07-14 14:48:02 -0400388 b.setName(mCursor.getString(Browser.HISTORY_PROJECTION_TITLE_INDEX));
389 byte[] data = mCursor.getBlob(Browser.HISTORY_PROJECTION_FAVICON_INDEX);
Patrick Scott8f0076b2009-09-17 13:51:30 -0400390 Bitmap bitmap = null;
391 if (data == null) {
392 bitmap = CombinedBookmarkHistoryActivity.getIconListenerSet()
393 .getFavicon(url);
394 } else {
395 bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
396 }
Leon Scroggins892df312009-07-14 14:48:02 -0400397 b.setFavicon(bitmap);
398 }
399
The Android Open Source Project0c908882009-03-03 19:32:16 -0800400 /**
401 * Get a View that displays the data at the specified position
402 * in the list.
403 * @param position Index of the item whose view we want.
404 * @return A View corresponding to the data at the specified position.
405 */
406 public View getView(int position, View convertView, ViewGroup parent) {
407 if (!mDataValid) {
408 throw new IllegalStateException(
409 "this should only be called when the cursor is valid");
410 }
411 if (position < 0 || position > mCount) {
412 throw new AssertionError(
413 "BrowserBookmarksAdapter tried to get a view out of range");
414 }
Ben Murdoch328ea872009-09-16 13:33:29 +0100415 if (mViewMode == BookmarkViewMode.GRID) {
Leon Scroggins892df312009-07-14 14:48:02 -0400416 if (convertView == null || convertView instanceof AddNewBookmark
417 || convertView instanceof BookmarkItem) {
418 LayoutInflater factory = LayoutInflater.from(mBookmarksPage);
419 convertView
420 = factory.inflate(R.layout.bookmark_thumbnail, null);
421 }
Leon Scroggins89c6d362009-07-15 16:54:37 -0400422 View holder = convertView.findViewById(R.id.holder);
Leon Scroggins892df312009-07-14 14:48:02 -0400423 ImageView thumb = (ImageView) convertView.findViewById(R.id.thumb);
Leon Scroggins892df312009-07-14 14:48:02 -0400424 TextView tv = (TextView) convertView.findViewById(R.id.label);
425
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400426 if (0 == position && mNeedsOffset) {
Leon Scroggins892df312009-07-14 14:48:02 -0400427 // This is to create a bookmark for the current page.
Leon Scroggins89c6d362009-07-15 16:54:37 -0400428 holder.setVisibility(View.VISIBLE);
Leon Scroggins89c6d362009-07-15 16:54:37 -0400429 tv.setText(mCurrentTitle);
430 // FIXME: Want to show the screenshot of the current page
431 thumb.setImageResource(R.drawable.blank);
Leon Scroggins892df312009-07-14 14:48:02 -0400432 return convertView;
433 }
Leon Scroggins89c6d362009-07-15 16:54:37 -0400434 holder.setVisibility(View.GONE);
Leon Scroggins892df312009-07-14 14:48:02 -0400435 mCursor.moveToPosition(position - mExtraOffset);
436 tv.setText(mCursor.getString(
437 Browser.HISTORY_PROJECTION_TITLE_INDEX));
438 byte[] data = mCursor.getBlob(
439 Browser.HISTORY_PROJECTION_THUMBNAIL_INDEX);
440 if (data == null) {
Leon Scrogginsb40bf272009-09-14 18:43:27 -0400441 thumb.setImageResource(R.drawable.ic_launcher_shortcut_browser_bookmark);
Leon Scroggins892df312009-07-14 14:48:02 -0400442 } else {
443 thumb.setImageBitmap(
444 BitmapFactory.decodeByteArray(data, 0, data.length));
445 }
Leon Scroggins89c6d362009-07-15 16:54:37 -0400446
Leon Scroggins892df312009-07-14 14:48:02 -0400447 return convertView;
448
449 }
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400450 if (position == 0 && mNeedsOffset) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800451 AddNewBookmark b;
452 if (convertView instanceof AddNewBookmark) {
453 b = (AddNewBookmark) convertView;
454 } else {
455 b = new AddNewBookmark(mBookmarksPage);
456 }
457 b.setUrl(mCurrentPage);
458 return b;
459 }
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400460 if (mMostVisited) {
461 if (convertView == null || !(convertView instanceof HistoryItem)) {
462 convertView = new HistoryItem(mBookmarksPage);
463 }
464 } else {
465 if (convertView == null || !(convertView instanceof BookmarkItem)) {
466 convertView = new BookmarkItem(mBookmarksPage);
467 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800468 }
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400469 bind((BookmarkItem) convertView, position);
470 if (mMostVisited) {
471 ((HistoryItem) convertView).setIsBookmark(
472 getIsBookmark(position));
473 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800474 return convertView;
475 }
476
477 /**
478 * Return the title for this item in the list.
479 */
480 public String getTitle(int position) {
481 return getString(Browser.HISTORY_PROJECTION_TITLE_INDEX, position);
482 }
483
484 /**
485 * Return the Url for this item in the list.
486 */
487 public String getUrl(int position) {
488 return getString(Browser.HISTORY_PROJECTION_URL_INDEX, position);
489 }
490
491 /**
Patrick Scotte09761e2009-03-24 20:43:37 -0700492 * Return the favicon for this item in the list.
493 */
494 public Bitmap getFavicon(int position) {
Patrick Scott3918d442009-08-04 13:22:29 -0400495 return getBitmap(Browser.HISTORY_PROJECTION_FAVICON_INDEX, position);
496 }
497
498 public Bitmap getTouchIcon(int position) {
499 return getBitmap(Browser.HISTORY_PROJECTION_TOUCH_ICON_INDEX, position);
500 }
501
502 private Bitmap getBitmap(int cursorIndex, int position) {
Patrick Scotte09761e2009-03-24 20:43:37 -0700503 if (position < mExtraOffset || position > mCount) {
504 return null;
505 }
506 mCursor.moveToPosition(position - mExtraOffset);
Patrick Scott3918d442009-08-04 13:22:29 -0400507 byte[] data = mCursor.getBlob(cursorIndex);
Patrick Scotte09761e2009-03-24 20:43:37 -0700508 if (data == null) {
509 return null;
510 }
511 return BitmapFactory.decodeByteArray(data, 0, data.length);
512 }
513
514 /**
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400515 * Return whether or not this item represents a bookmarked site.
516 */
517 public boolean getIsBookmark(int position) {
518 if (position < mExtraOffset || position > mCount) {
519 return false;
520 }
521 mCursor.moveToPosition(position - mExtraOffset);
522 return (1 == mCursor.getInt(Browser.HISTORY_PROJECTION_BOOKMARK_INDEX));
523 }
524
525 /**
The Android Open Source Project0c908882009-03-03 19:32:16 -0800526 * Private helper function to return the title or url.
527 */
528 private String getString(int cursorIndex, int position) {
529 if (position < mExtraOffset || position > mCount) {
530 return "";
531 }
532 mCursor.moveToPosition(position- mExtraOffset);
533 return mCursor.getString(cursorIndex);
534 }
535
536 private void bind(BookmarkItem b, int position) {
537 mCursor.moveToPosition(position- mExtraOffset);
538
539 String title = mCursor.getString(Browser.HISTORY_PROJECTION_TITLE_INDEX);
540 if (title.length() > BrowserSettings.MAX_TEXTVIEW_LEN) {
541 title = title.substring(0, BrowserSettings.MAX_TEXTVIEW_LEN);
542 }
543 b.setName(title);
544 String url = mCursor.getString(Browser.HISTORY_PROJECTION_URL_INDEX);
545 if (url.length() > BrowserSettings.MAX_TEXTVIEW_LEN) {
546 url = url.substring(0, BrowserSettings.MAX_TEXTVIEW_LEN);
547 }
548 b.setUrl(url);
549 byte[] data = mCursor.getBlob(Browser.HISTORY_PROJECTION_FAVICON_INDEX);
550 if (data != null) {
551 b.setFavicon(BitmapFactory.decodeByteArray(data, 0, data.length));
552 } else {
Patrick Scott8f0076b2009-09-17 13:51:30 -0400553 b.setFavicon(CombinedBookmarkHistoryActivity.getIconListenerSet()
554 .getFavicon(url));
The Android Open Source Project0c908882009-03-03 19:32:16 -0800555 }
556 }
557
558 private class ChangeObserver extends ContentObserver {
559 public ChangeObserver() {
560 super(new Handler());
561 }
562
563 @Override
564 public boolean deliverSelfNotifications() {
565 return true;
566 }
567
568 @Override
569 public void onChange(boolean selfChange) {
570 refreshList();
571 }
572 }
573
574 private class MyDataSetObserver extends DataSetObserver {
575 @Override
576 public void onChanged() {
577 mDataValid = true;
578 notifyDataSetChanged();
579 }
580
581 @Override
582 public void onInvalidated() {
583 mDataValid = false;
584 notifyDataSetInvalidated();
585 }
586 }
587}