blob: 8b0fb41cc3cd9dcdc1607341159cbd61a7220655 [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;
Ben Murdochdcc2b6f2009-09-21 14:29:20 +010049 private Bitmap mCurrentThumbnail;
The Android Open Source Project0c908882009-03-03 19:32:16 -080050 private Cursor mCursor;
51 private int mCount;
The Android Open Source Project0c908882009-03-03 19:32:16 -080052 private BrowserBookmarksPage mBookmarksPage;
53 private ContentResolver mContentResolver;
The Android Open Source Project0c908882009-03-03 19:32:16 -080054 private boolean mDataValid;
Ben Murdoch328ea872009-09-16 13:33:29 +010055 private BookmarkViewMode mViewMode;
Leon Scrogginsa5d669e2009-08-05 14:07:58 -040056 private boolean mMostVisited;
57 private boolean mNeedsOffset;
58 private int mExtraOffset;
The Android Open Source Project0c908882009-03-03 19:32:16 -080059
60 // Implementation of WebIconDatabase.IconListener
61 private class IconReceiver implements IconListener {
62 public void onReceivedIcon(String url, Bitmap icon) {
Patrick Scott3918d442009-08-04 13:22:29 -040063 updateBookmarkFavicon(mContentResolver, null, url, icon);
The Android Open Source Project0c908882009-03-03 19:32:16 -080064 }
65 }
66
67 // Instance of IconReceiver
68 private final IconReceiver mIconReceiver = new IconReceiver();
69
70 /**
71 * Create a new BrowserBookmarksAdapter.
The Android Open Source Project0c908882009-03-03 19:32:16 -080072 * @param b BrowserBookmarksPage that instantiated this.
73 * Necessary so it will adjust its focus
74 * appropriately after a search.
75 */
76 public BrowserBookmarksAdapter(BrowserBookmarksPage b, String curPage,
Ben Murdochdcc2b6f2009-09-21 14:29:20 +010077 String curTitle, Bitmap curThumbnail, boolean createShortcut,
78 boolean mostVisited) {
Leon Scrogginsa5d669e2009-08-05 14:07:58 -040079 mNeedsOffset = !(createShortcut || mostVisited);
80 mMostVisited = mostVisited;
81 mExtraOffset = mNeedsOffset ? 1 : 0;
The Android Open Source Project0c908882009-03-03 19:32:16 -080082 mBookmarksPage = b;
Leon Scroggins89c6d362009-07-15 16:54:37 -040083 mCurrentPage = b.getResources().getString(R.string.current_page)
84 + curPage;
85 mCurrentTitle = curTitle;
Ben Murdochdcc2b6f2009-09-21 14:29:20 +010086 mCurrentThumbnail = curThumbnail;
The Android Open Source Project0c908882009-03-03 19:32:16 -080087 mContentResolver = b.getContentResolver();
Ben Murdoch328ea872009-09-16 13:33:29 +010088 mViewMode = BookmarkViewMode.LIST;
Leon Scroggins892df312009-07-14 14:48:02 -040089
Leon Scrogginsa5d669e2009-08-05 14:07:58 -040090 String whereClause;
The Android Open Source Project0c908882009-03-03 19:32:16 -080091 // FIXME: Should have a default sort order that the user selects.
Leon Scroggins892df312009-07-14 14:48:02 -040092 String orderBy = Browser.BookmarkColumns.VISITS + " DESC";
Leon Scrogginsa5d669e2009-08-05 14:07:58 -040093 if (mostVisited) {
94 whereClause = Browser.BookmarkColumns.VISITS + " != 0";
95 } else {
96 whereClause = Browser.BookmarkColumns.BOOKMARK + " != 0";
97 }
Leon Scroggins892df312009-07-14 14:48:02 -040098 mCursor = b.managedQuery(Browser.BOOKMARKS_URI,
99 Browser.HISTORY_PROJECTION, whereClause, null, orderBy);
100 mCursor.registerContentObserver(new ChangeObserver());
101 mCursor.registerDataSetObserver(new MyDataSetObserver());
102
103 mDataValid = true;
104 notifyDataSetChanged();
105
106 mCount = mCursor.getCount() + mExtraOffset;
107
The Android Open Source Project0c908882009-03-03 19:32:16 -0800108 // FIXME: This requires another query of the database after the
Leon Scroggins89c6d362009-07-15 16:54:37 -0400109 // managedQuery. Can we optimize this?
The Android Open Source Project0c908882009-03-03 19:32:16 -0800110 Browser.requestAllIcons(mContentResolver,
111 Browser.BookmarkColumns.FAVICON + " is NULL AND " +
112 Browser.BookmarkColumns.BOOKMARK + " == 1", mIconReceiver);
113 }
114
115 /**
116 * Return a hashmap with one row's Title, Url, and favicon.
117 * @param position Position in the list.
118 * @return Bundle Stores title, url of row position, favicon, and id
119 * for the url. Return a blank map if position is out of
120 * range.
121 */
122 public Bundle getRow(int position) {
123 Bundle map = new Bundle();
124 if (position < mExtraOffset || position >= mCount) {
125 return map;
126 }
127 mCursor.moveToPosition(position- mExtraOffset);
128 String url = mCursor.getString(Browser.HISTORY_PROJECTION_URL_INDEX);
129 map.putString(Browser.BookmarkColumns.TITLE,
130 mCursor.getString(Browser.HISTORY_PROJECTION_TITLE_INDEX));
131 map.putString(Browser.BookmarkColumns.URL, url);
132 byte[] data = mCursor.getBlob(Browser.HISTORY_PROJECTION_FAVICON_INDEX);
133 if (data != null) {
134 map.putParcelable(Browser.BookmarkColumns.FAVICON,
135 BitmapFactory.decodeByteArray(data, 0, data.length));
136 }
137 map.putInt("id", mCursor.getInt(Browser.HISTORY_PROJECTION_ID_INDEX));
138 return map;
139 }
140
141 /**
142 * Update a row in the database with new information.
143 * Requeries the database if the information has changed.
144 * @param map Bundle storing id, title and url of new information
145 */
146 public void updateRow(Bundle map) {
147
148 // Find the record
149 int id = map.getInt("id");
150 int position = -1;
151 for (mCursor.moveToFirst(); !mCursor.isAfterLast(); mCursor.moveToNext()) {
152 if (mCursor.getInt(Browser.HISTORY_PROJECTION_ID_INDEX) == id) {
153 position = mCursor.getPosition();
154 break;
155 }
156 }
157 if (position < 0) {
158 return;
159 }
160
161 mCursor.moveToPosition(position);
162 ContentValues values = new ContentValues();
163 String title = map.getString(Browser.BookmarkColumns.TITLE);
164 if (!title.equals(mCursor
165 .getString(Browser.HISTORY_PROJECTION_TITLE_INDEX))) {
166 values.put(Browser.BookmarkColumns.TITLE, title);
167 }
168 String url = map.getString(Browser.BookmarkColumns.URL);
169 if (!url.equals(mCursor.
170 getString(Browser.HISTORY_PROJECTION_URL_INDEX))) {
171 values.put(Browser.BookmarkColumns.URL, url);
172 }
173 if (values.size() > 0
174 && mContentResolver.update(Browser.BOOKMARKS_URI, values,
175 "_id = " + id, null) != -1) {
176 refreshList();
177 }
178 }
179
180 /**
181 * Delete a row from the database. Requeries the database.
182 * Does nothing if the provided position is out of range.
183 * @param position Position in the list.
184 */
185 public void deleteRow(int position) {
186 if (position < mExtraOffset || position >= getCount()) {
187 return;
188 }
189 mCursor.moveToPosition(position- mExtraOffset);
190 String url = mCursor.getString(Browser.HISTORY_PROJECTION_URL_INDEX);
Andrei Popescuc9526192009-09-23 15:52:16 +0100191 String title = mCursor.getString(Browser.HISTORY_PROJECTION_TITLE_INDEX);
192 Bookmarks.removeFromBookmarks(null, mContentResolver, url, title);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800193 refreshList();
194 }
195
196 /**
197 * Delete all bookmarks from the db. Requeries the database.
198 * All bookmarks with become visited URLs or if never visited
199 * are removed
200 */
201 public void deleteAllRows() {
202 StringBuilder deleteIds = null;
203 StringBuilder convertIds = null;
204
205 for (mCursor.moveToFirst(); !mCursor.isAfterLast(); mCursor.moveToNext()) {
206 String url = mCursor.getString(Browser.HISTORY_PROJECTION_URL_INDEX);
207 WebIconDatabase.getInstance().releaseIconForPageUrl(url);
208 int id = mCursor.getInt(Browser.HISTORY_PROJECTION_ID_INDEX);
209 int numVisits = mCursor.getInt(Browser.HISTORY_PROJECTION_VISITS_INDEX);
210 if (0 == numVisits) {
211 if (deleteIds == null) {
212 deleteIds = new StringBuilder();
213 deleteIds.append("( ");
214 } else {
215 deleteIds.append(" OR ( ");
216 }
217 deleteIds.append(BookmarkColumns._ID);
218 deleteIds.append(" = ");
219 deleteIds.append(id);
220 deleteIds.append(" )");
221 } else {
222 // It is no longer a bookmark, but it is still a visited site.
223 if (convertIds == null) {
224 convertIds = new StringBuilder();
225 convertIds.append("( ");
226 } else {
227 convertIds.append(" OR ( ");
228 }
229 convertIds.append(BookmarkColumns._ID);
230 convertIds.append(" = ");
231 convertIds.append(id);
232 convertIds.append(" )");
233 }
234 }
235
236 if (deleteIds != null) {
237 mContentResolver.delete(Browser.BOOKMARKS_URI, deleteIds.toString(),
238 null);
239 }
240 if (convertIds != null) {
241 ContentValues values = new ContentValues();
242 values.put(Browser.BookmarkColumns.BOOKMARK, 0);
243 mContentResolver.update(Browser.BOOKMARKS_URI, values,
244 convertIds.toString(), null);
245 }
246 refreshList();
247 }
248
249 /**
250 * Refresh list to recognize a change in the database.
251 */
252 public void refreshList() {
Leon Scroggins892df312009-07-14 14:48:02 -0400253 mCursor.requery();
254 mCount = mCursor.getCount() + mExtraOffset;
255 notifyDataSetChanged();
The Android Open Source Project0c908882009-03-03 19:32:16 -0800256 }
257
258 /**
Patrick Scott3918d442009-08-04 13:22:29 -0400259 * Update the bookmark's favicon. This is a convenience method for updating
260 * a bookmark favicon for the originalUrl and url of the passed in WebView.
The Android Open Source Project0c908882009-03-03 19:32:16 -0800261 * @param cr The ContentResolver to use.
Patrick Scott15525d42009-09-21 13:39:37 -0400262 * @param originalUrl The original url before any redirects.
263 * @param url The current url.
The Android Open Source Project0c908882009-03-03 19:32:16 -0800264 * @param favicon The favicon bitmap to write to the db.
265 */
266 /* package */ static void updateBookmarkFavicon(ContentResolver cr,
Patrick Scott3918d442009-08-04 13:22:29 -0400267 String originalUrl, String url, Bitmap favicon) {
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400268 final Cursor c = queryBookmarksForUrl(cr, originalUrl, url, true);
Patrick Scott3918d442009-08-04 13:22:29 -0400269 if (c == null) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800270 return;
271 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800272 boolean succeed = c.moveToFirst();
273 ContentValues values = null;
274 while (succeed) {
275 if (values == null) {
276 final ByteArrayOutputStream os = new ByteArrayOutputStream();
277 favicon.compress(Bitmap.CompressFormat.PNG, 100, os);
278 values = new ContentValues();
279 values.put(Browser.BookmarkColumns.FAVICON, os.toByteArray());
280 }
281 cr.update(ContentUris.withAppendedId(Browser.BOOKMARKS_URI, c
282 .getInt(0)), values, null, null);
283 succeed = c.moveToNext();
284 }
285 c.close();
286 }
287
Patrick Scott3918d442009-08-04 13:22:29 -0400288 /* package */ static Cursor queryBookmarksForUrl(ContentResolver cr,
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400289 String originalUrl, String url, boolean onlyBookmarks) {
Patrick Scott3918d442009-08-04 13:22:29 -0400290 if (cr == null || url == null) {
291 return null;
292 }
293
294 // If originalUrl is null, just set it to url.
295 if (originalUrl == null) {
296 originalUrl = url;
297 }
298
299 // Look for both the original url and the actual url. This takes in to
300 // account redirects.
301 String originalUrlNoQuery = removeQuery(originalUrl);
302 String urlNoQuery = removeQuery(url);
303 originalUrl = originalUrlNoQuery + '?';
304 url = urlNoQuery + '?';
305
306 // Use NoQuery to search for the base url (i.e. if the url is
307 // http://www.yahoo.com/?rs=1, search for http://www.yahoo.com)
308 // Use url to match the base url with other queries (i.e. if the url is
309 // http://www.google.com/m, search for
310 // http://www.google.com/m?some_query)
311 final String[] selArgs = new String[] {
312 originalUrlNoQuery, urlNoQuery, originalUrl, url };
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400313 String where = BookmarkColumns.URL + " == ? OR "
Patrick Scott3918d442009-08-04 13:22:29 -0400314 + BookmarkColumns.URL + " == ? OR "
315 + BookmarkColumns.URL + " GLOB ? || '*' OR "
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400316 + BookmarkColumns.URL + " GLOB ? || '*'";
317 if (onlyBookmarks) {
318 where = "(" + where + ") AND " + BookmarkColumns.BOOKMARK + " == 1";
319 }
Patrick Scott3918d442009-08-04 13:22:29 -0400320 final String[] projection =
321 new String[] { Browser.BookmarkColumns._ID };
322 return cr.query(Browser.BOOKMARKS_URI, projection, where, selArgs,
323 null);
324 }
325
326 // Strip the query from the given url.
327 private static String removeQuery(String url) {
328 if (url == null) {
329 return null;
330 }
331 int query = url.indexOf('?');
332 String noQuery = url;
333 if (query != -1) {
334 noQuery = url.substring(0, query);
335 }
336 return noQuery;
337 }
338
The Android Open Source Project0c908882009-03-03 19:32:16 -0800339 /**
The Android Open Source Project0c908882009-03-03 19:32:16 -0800340 * How many items should be displayed in the list.
341 * @return Count of items.
342 */
343 public int getCount() {
344 if (mDataValid) {
345 return mCount;
346 } else {
347 return 0;
348 }
349 }
350
351 public boolean areAllItemsEnabled() {
352 return true;
353 }
354
355 public boolean isEnabled(int position) {
356 return true;
357 }
358
359 /**
360 * Get the data associated with the specified position in the list.
361 * @param position Index of the item whose data we want.
362 * @return The data at the specified position.
363 */
364 public Object getItem(int position) {
365 return null;
366 }
367
368 /**
369 * Get the row id associated with the specified position in the list.
370 * @param position Index of the item whose row id we want.
371 * @return The id of the item at the specified position.
372 */
373 public long getItemId(int position) {
374 return position;
375 }
376
Ben Murdoch328ea872009-09-16 13:33:29 +0100377 /* package */ void switchViewMode(BookmarkViewMode viewMode) {
378 mViewMode = viewMode;
Leon Scroggins892df312009-07-14 14:48:02 -0400379 }
380
381 /* package */ void populateBookmarkItem(BookmarkItem b, int position) {
382 mCursor.moveToPosition(position - mExtraOffset);
Patrick Scott8f0076b2009-09-17 13:51:30 -0400383 String url = mCursor.getString(Browser.HISTORY_PROJECTION_URL_INDEX);
384 b.setUrl(url);
Leon Scroggins892df312009-07-14 14:48:02 -0400385 b.setName(mCursor.getString(Browser.HISTORY_PROJECTION_TITLE_INDEX));
386 byte[] data = mCursor.getBlob(Browser.HISTORY_PROJECTION_FAVICON_INDEX);
Patrick Scott8f0076b2009-09-17 13:51:30 -0400387 Bitmap bitmap = null;
388 if (data == null) {
389 bitmap = CombinedBookmarkHistoryActivity.getIconListenerSet()
390 .getFavicon(url);
391 } else {
392 bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
393 }
Leon Scroggins892df312009-07-14 14:48:02 -0400394 b.setFavicon(bitmap);
395 }
396
The Android Open Source Project0c908882009-03-03 19:32:16 -0800397 /**
398 * Get a View that displays the data at the specified position
399 * in the list.
400 * @param position Index of the item whose view we want.
401 * @return A View corresponding to the data at the specified position.
402 */
403 public View getView(int position, View convertView, ViewGroup parent) {
404 if (!mDataValid) {
405 throw new IllegalStateException(
406 "this should only be called when the cursor is valid");
407 }
408 if (position < 0 || position > mCount) {
409 throw new AssertionError(
410 "BrowserBookmarksAdapter tried to get a view out of range");
411 }
Ben Murdoch328ea872009-09-16 13:33:29 +0100412 if (mViewMode == BookmarkViewMode.GRID) {
Leon Scroggins892df312009-07-14 14:48:02 -0400413 if (convertView == null || convertView instanceof AddNewBookmark
414 || convertView instanceof BookmarkItem) {
415 LayoutInflater factory = LayoutInflater.from(mBookmarksPage);
416 convertView
417 = factory.inflate(R.layout.bookmark_thumbnail, null);
418 }
Leon Scroggins89c6d362009-07-15 16:54:37 -0400419 View holder = convertView.findViewById(R.id.holder);
Leon Scroggins892df312009-07-14 14:48:02 -0400420 ImageView thumb = (ImageView) convertView.findViewById(R.id.thumb);
Leon Scroggins892df312009-07-14 14:48:02 -0400421 TextView tv = (TextView) convertView.findViewById(R.id.label);
422
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400423 if (0 == position && mNeedsOffset) {
Leon Scroggins892df312009-07-14 14:48:02 -0400424 // This is to create a bookmark for the current page.
Leon Scroggins89c6d362009-07-15 16:54:37 -0400425 holder.setVisibility(View.VISIBLE);
Leon Scroggins89c6d362009-07-15 16:54:37 -0400426 tv.setText(mCurrentTitle);
Ben Murdochdcc2b6f2009-09-21 14:29:20 +0100427
428 if (mCurrentThumbnail != null) {
429 thumb.setImageBitmap(mCurrentThumbnail);
430 } else {
431 thumb.setImageResource(
Leon Scrogginsf8551612009-09-24 16:06:02 -0400432 R.drawable.browser_thumbnail);
Ben Murdochdcc2b6f2009-09-21 14:29:20 +0100433 }
Leon Scroggins892df312009-07-14 14:48:02 -0400434 return convertView;
435 }
Leon Scroggins89c6d362009-07-15 16:54:37 -0400436 holder.setVisibility(View.GONE);
Leon Scroggins892df312009-07-14 14:48:02 -0400437 mCursor.moveToPosition(position - mExtraOffset);
438 tv.setText(mCursor.getString(
439 Browser.HISTORY_PROJECTION_TITLE_INDEX));
Ben Murdochaac7aa62009-09-17 16:57:40 +0100440 Bitmap thumbnail = getBitmap(Browser.HISTORY_PROJECTION_THUMBNAIL_INDEX, position);
441 if (thumbnail == null) {
Leon Scrogginsf8551612009-09-24 16:06:02 -0400442 thumb.setImageResource(R.drawable.browser_thumbnail);
Leon Scroggins892df312009-07-14 14:48:02 -0400443 } else {
Ben Murdochaac7aa62009-09-17 16:57:40 +0100444 thumb.setImageBitmap(thumbnail);
Leon Scroggins892df312009-07-14 14:48:02 -0400445 }
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}