542 lines
18 KiB
Java
542 lines
18 KiB
Java
/*
|
|
* @copyright 2010 Evan Leybourn
|
|
* @license GNU General Public License
|
|
*
|
|
* This file is part of Book Catalogue.
|
|
*
|
|
* Book Catalogue is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Book Catalogue is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with Book Catalogue. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
package com.eleybourn.bookcatalogue;
|
|
|
|
//import android.R;
|
|
import android.app.ExpandableListActivity;
|
|
import android.app.SearchManager;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.database.Cursor;
|
|
import android.graphics.drawable.BitmapDrawable;
|
|
import android.graphics.drawable.Drawable;
|
|
import android.os.Bundle;
|
|
import android.util.Log;
|
|
import android.view.ContextMenu;
|
|
import android.view.Menu;
|
|
import android.view.MenuItem;
|
|
import android.view.View;
|
|
import android.view.ContextMenu.ContextMenuInfo;
|
|
import android.widget.AdapterView;
|
|
import android.widget.ArrayAdapter;
|
|
import android.widget.ExpandableListAdapter;
|
|
import android.widget.ExpandableListView;
|
|
import android.widget.SimpleCursorTreeAdapter;
|
|
import android.widget.Spinner;
|
|
import android.widget.TextView;
|
|
import android.widget.Toast;
|
|
import android.widget.AdapterView.OnItemSelectedListener;
|
|
import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
|
|
import android.widget.ExpandableListView.OnGroupClickListener;
|
|
|
|
/*
|
|
* A book catalogue application that integrates with Google Books.
|
|
*/
|
|
public class BookCatalogue extends ExpandableListActivity {
|
|
private static final int ACTIVITY_CREATE=0;
|
|
private static final int ACTIVITY_EDIT=1;
|
|
private static final int ACTIVITY_SORT=2;
|
|
private static final int ACTIVITY_ISBN=3;
|
|
private static final int ACTIVITY_SCAN=4;
|
|
private static final int ACTIVITY_BOOKSHELF=5;
|
|
|
|
private CatalogueDBAdapter mDbHelper;
|
|
private int mGroupIdColumnIndex;
|
|
private static final int SORT_BY_AUTHOR_EXPANDED = Menu.FIRST + 1;
|
|
private static final int SORT_BY_AUTHOR_COLLAPSED = Menu.FIRST + 2;
|
|
private static final int SORT_BY_TITLE = Menu.FIRST + 3;
|
|
private static final int INSERT_ID = Menu.FIRST + 4;
|
|
private static final int INSERT_ISBN_ID = Menu.FIRST + 5;
|
|
private static final int INSERT_BARCODE_ID = Menu.FIRST + 6;
|
|
private static final int DELETE_ID = Menu.FIRST + 7;
|
|
private static final int BOOKSHELVES = Menu.FIRST + 8;
|
|
private static final int SORT_BY_AUTHOR = Menu.FIRST + 9;
|
|
|
|
public String bookshelf = "";
|
|
private ArrayAdapter<String> spinnerAdapter;
|
|
private Menu optionsMenu;
|
|
|
|
public int sort = 0;
|
|
public int numAuthors = 0;
|
|
|
|
/** Called when the activity is first created. */
|
|
@Override
|
|
public void onCreate(Bundle savedInstanceState) {
|
|
try {
|
|
super.onCreate(savedInstanceState);
|
|
setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
|
|
setContentView(R.layout.list_authors);
|
|
mDbHelper = new CatalogueDBAdapter(this);
|
|
mDbHelper.open();
|
|
bookshelf = getString(R.string.all_books);
|
|
bookshelf();
|
|
//fillData();
|
|
registerForContextMenu(getExpandableListView());
|
|
} catch (Exception e) {
|
|
Log.e("Book Catalogue", "Unknown Exception - BC onCreate - " + e.getMessage() );
|
|
}
|
|
}
|
|
|
|
|
|
private void bookshelf() {
|
|
// Setup the Bookshelf Spinner
|
|
Spinner mBookshelfText = (Spinner) findViewById(R.id.bookshelf_name);
|
|
spinnerAdapter = new ArrayAdapter<String>(this, R.layout.spinner_frontpage);
|
|
spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
|
mBookshelfText.setAdapter(spinnerAdapter);
|
|
|
|
/* Add the default All Books bookshelf */
|
|
spinnerAdapter.add(getString(R.string.all_books));
|
|
|
|
Cursor bookshelves = mDbHelper.fetchAllBookshelves();
|
|
if (bookshelves.moveToFirst()) {
|
|
do {
|
|
spinnerAdapter.add(bookshelves.getString(1));
|
|
}
|
|
while (bookshelves.moveToNext());
|
|
}
|
|
|
|
mBookshelfText.setOnItemSelectedListener(new OnItemSelectedListener() {
|
|
public void onItemSelected(AdapterView<?> parentView, View view, int position, long id) {
|
|
bookshelf = spinnerAdapter.getItem(position);
|
|
fillData();
|
|
}
|
|
|
|
public void onNothingSelected(AdapterView<?> parentView) {
|
|
// Do Nothing
|
|
|
|
}
|
|
});
|
|
|
|
}
|
|
|
|
private void fillData() {
|
|
if (sort == 1) {
|
|
fillDataTitle();
|
|
} else {
|
|
fillDataAuthor();
|
|
}
|
|
}
|
|
|
|
private void fillDataAuthor() {
|
|
Intent intent = getIntent();
|
|
// base the layout and the query on the sort order
|
|
int layout = R.layout.row_authors;
|
|
int layout_child = R.layout.row_authors_books;
|
|
|
|
// Get all of the rows from the database and create the item list
|
|
Cursor BooksCursor = null;
|
|
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
|
|
String query = intent.getStringExtra(SearchManager.QUERY);
|
|
BooksCursor = mDbHelper.searchAuthors(query, bookshelf);
|
|
} else {
|
|
BooksCursor = mDbHelper.fetchAllAuthors(bookshelf);
|
|
}
|
|
numAuthors = BooksCursor.getCount();
|
|
mGroupIdColumnIndex = BooksCursor.getColumnIndexOrThrow("_id");
|
|
startManagingCursor(BooksCursor);
|
|
|
|
// Create an array to specify the fields we want to display in the list
|
|
String[] from = new String[]{CatalogueDBAdapter.KEY_FAMILY_NAME, CatalogueDBAdapter.KEY_GIVEN_NAMES};
|
|
String[] exp_from = new String[]{CatalogueDBAdapter.KEY_TITLE, CatalogueDBAdapter.KEY_SERIES, CatalogueDBAdapter.KEY_SERIES_NUM};
|
|
|
|
// and an array of the fields we want to bind those fields to (in this case just text1)
|
|
int[] to = new int[]{R.id.row_family, R.id.row_given};
|
|
int[] exp_to = new int[]{R.id.row_title, R.id.row_series, R.id.row_series_num};
|
|
|
|
ExpandableListAdapter books = new AuthorBookListAdapter(BooksCursor, this, layout, layout_child, from, to, exp_from, exp_to);
|
|
|
|
/* Handle the click event. Do not open, but goto the book edit page */
|
|
ExpandableListView expandableList = getExpandableListView();
|
|
expandableList.setOnGroupClickListener(new OnGroupClickListener() {
|
|
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
|
|
return false;
|
|
}
|
|
});
|
|
|
|
/* Hide the default expandable icon */
|
|
Drawable indicator = this.getResources().getDrawable(R.drawable.expander_group);
|
|
expandableList.setGroupIndicator(indicator);
|
|
|
|
setListAdapter(books);
|
|
}
|
|
|
|
private void fillDataTitle() {
|
|
Intent intent = getIntent();
|
|
// base the layout and the query on the sort order
|
|
int layout = R.layout.row_books;
|
|
int layout_child = R.layout.row_books;
|
|
|
|
// Get all of the rows from the database and create the item list
|
|
Cursor BooksCursor = null;
|
|
String order = CatalogueDBAdapter.KEY_TITLE + ", " + CatalogueDBAdapter.KEY_FAMILY_NAME;
|
|
//TODO: Title Search
|
|
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
|
|
String query = intent.getStringExtra(SearchManager.QUERY);
|
|
BooksCursor = mDbHelper.searchBooks(query, order, bookshelf);
|
|
} else {
|
|
BooksCursor = mDbHelper.fetchAllBooks(order, bookshelf);
|
|
}
|
|
numAuthors = BooksCursor.getCount();
|
|
mGroupIdColumnIndex = BooksCursor.getColumnIndexOrThrow("_id");
|
|
startManagingCursor(BooksCursor);
|
|
|
|
// Create an array to specify the fields we want to display in the list
|
|
String[] from = new String[]{CatalogueDBAdapter.KEY_AUTHOR, CatalogueDBAdapter.KEY_TITLE, CatalogueDBAdapter.KEY_PUBLISHER, CatalogueDBAdapter.KEY_SERIES, CatalogueDBAdapter.KEY_SERIES_NUM};
|
|
String[] exp_from = new String[]{};
|
|
|
|
// and an array of the fields we want to bind those fields to (in this case just text1)
|
|
int[] to = new int[]{R.id.row_author, R.id.row_title, R.id.row_publisher, R.id.row_series, R.id.row_series_num};
|
|
int[] exp_to = new int[]{};
|
|
|
|
ExpandableListAdapter books = new BooksBookListAdapter(BooksCursor, this, layout, layout_child, from, to, exp_from, exp_to);
|
|
|
|
/* Handle the click event. Do not open, but goto the book edit page */
|
|
ExpandableListView expandableList = getExpandableListView();
|
|
/* Hack. So we can pass the current context into the onGroupClick event */
|
|
final BookCatalogue pthis = this;
|
|
expandableList.setOnGroupClickListener(new OnGroupClickListener() {
|
|
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
|
|
Intent i = new Intent(pthis, BookEdit.class);
|
|
i.putExtra(CatalogueDBAdapter.KEY_ROWID, id);
|
|
startActivityForResult(i, ACTIVITY_EDIT);
|
|
return true;
|
|
}
|
|
});
|
|
|
|
/* Hide the default expandable icon */
|
|
Drawable indicator = new BitmapDrawable();
|
|
indicator.setVisible(false, true);
|
|
expandableList.setGroupIndicator(indicator);
|
|
setListAdapter(books);
|
|
}
|
|
|
|
public class AuthorBookListAdapter extends SimpleCursorTreeAdapter {
|
|
|
|
boolean series = false;
|
|
|
|
public AuthorBookListAdapter(Cursor cursor, Context context, int groupLayout, int childLayout, String[] groupFrom, int[] groupTo, String[] childrenFrom, int[] childrenTo) {
|
|
super(context, cursor, groupLayout, groupFrom, groupTo, childLayout, childrenFrom, childrenTo);
|
|
}
|
|
|
|
@Override
|
|
protected Cursor getChildrenCursor(Cursor groupCursor) {
|
|
return mDbHelper.fetchAllBooksByAuthor(groupCursor.getInt(mGroupIdColumnIndex), bookshelf);
|
|
}
|
|
|
|
@Override
|
|
public void setViewText(TextView v, String text) {
|
|
if (v.getId() == R.id.row_series) {
|
|
if (text.equals("")) {
|
|
series = false;
|
|
} else {
|
|
series = true;
|
|
text = "(" + text;
|
|
}
|
|
} else if (v.getId() == R.id.row_series_num) {
|
|
if (series == false) {
|
|
text = "";
|
|
} else if (series == true) {
|
|
if (text.equals("")) {
|
|
text = ")";
|
|
} else {
|
|
text = " #" + text + ")";
|
|
}
|
|
}
|
|
|
|
} else if (v.getId() == R.id.row_family) {
|
|
text = text + ", ";
|
|
}
|
|
v.setText(text);
|
|
}
|
|
|
|
}
|
|
|
|
public class BooksBookListAdapter extends SimpleCursorTreeAdapter {
|
|
|
|
boolean series = false;
|
|
|
|
public BooksBookListAdapter(Cursor cursor, Context context, int groupLayout, int childLayout, String[] groupFrom, int[] groupTo, String[] childrenFrom, int[] childrenTo) {
|
|
super(context, cursor, groupLayout, groupFrom, groupTo, childLayout, childrenFrom, childrenTo);
|
|
}
|
|
|
|
@Override
|
|
public void setViewText(TextView v, String text) {
|
|
if (v.getId() == R.id.row_series) {
|
|
if (text.equals("")) {
|
|
series = false;
|
|
} else {
|
|
series = true;
|
|
text = "(" + text;
|
|
}
|
|
} else if (v.getId() == R.id.row_series_num) {
|
|
if (series == false) {
|
|
text = "";
|
|
} else if (series == true) {
|
|
if (text.equals("")) {
|
|
text = ")";
|
|
} else {
|
|
text = " #" + text + ")";
|
|
}
|
|
}
|
|
}
|
|
v.setText(text);
|
|
}
|
|
|
|
@Override
|
|
protected Cursor getChildrenCursor(Cursor groupCursor) {
|
|
return null;
|
|
}
|
|
|
|
}
|
|
|
|
@Override
|
|
public boolean onCreateOptionsMenu(Menu menu) {
|
|
super.onCreateOptionsMenu(menu);
|
|
optionsMenu = menu;
|
|
if (sort == 0) {
|
|
MenuItem collapse = menu.add(0, SORT_BY_AUTHOR_EXPANDED, 0, R.string.menu_sort_by_author_collapsed);
|
|
collapse.setIcon(R.drawable.ic_menu_collapse);
|
|
|
|
MenuItem expand = menu.add(0, SORT_BY_AUTHOR_COLLAPSED, 1, R.string.menu_sort_by_author_expanded);
|
|
expand.setIcon(R.drawable.ic_menu_expand);
|
|
}
|
|
|
|
MenuItem insert = menu.add(1, INSERT_ID, 2, R.string.menu_insert);
|
|
insert.setIcon(android.R.drawable.ic_menu_add);
|
|
|
|
MenuItem insertBC = menu.add(1, INSERT_BARCODE_ID, 3, R.string.menu_insert_barcode);
|
|
insertBC.setIcon(R.drawable.ic_menu_insert_barcode);
|
|
|
|
MenuItem insertISBN = menu.add(1, INSERT_ISBN_ID, 4, R.string.menu_insert_isbn);
|
|
insertISBN.setIcon(android.R.drawable.ic_menu_zoom);
|
|
|
|
if (sort == 0) {
|
|
MenuItem title = menu.add(2, SORT_BY_TITLE, 4, R.string.menu_sort_by_title);
|
|
title.setIcon(android.R.drawable.ic_menu_sort_alphabetically);
|
|
} else {
|
|
MenuItem title = menu.add(2, SORT_BY_AUTHOR, 4, R.string.menu_sort_by_author);
|
|
title.setIcon(android.R.drawable.ic_menu_sort_alphabetically);
|
|
}
|
|
|
|
MenuItem bookshelf = menu.add(2, BOOKSHELVES, 4, R.string.menu_bookshelf);
|
|
bookshelf.setIcon(R.drawable.ic_menu_bookshelves);
|
|
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean onMenuItemSelected(int featureId, MenuItem item) {
|
|
switch(item.getItemId()) {
|
|
case SORT_BY_AUTHOR_COLLAPSED:
|
|
expandAll();
|
|
return true;
|
|
case SORT_BY_AUTHOR_EXPANDED:
|
|
collapseAll();
|
|
return true;
|
|
case SORT_BY_TITLE:
|
|
sortByTitle();
|
|
return true;
|
|
case SORT_BY_AUTHOR:
|
|
sortByAuthor();
|
|
return true;
|
|
case INSERT_ID:
|
|
//createDemoBook();
|
|
//fillData();
|
|
createBook();
|
|
return true;
|
|
case INSERT_ISBN_ID:
|
|
createBookISBN();
|
|
return true;
|
|
case INSERT_BARCODE_ID:
|
|
createBookScan();
|
|
return true;
|
|
case BOOKSHELVES:
|
|
manageBookselves();
|
|
return true;
|
|
}
|
|
|
|
return super.onMenuItemSelected(featureId, item);
|
|
}
|
|
|
|
/*
|
|
* Expand all Author Groups
|
|
*/
|
|
public void expandAll() {
|
|
int i = 0;
|
|
while (i < numAuthors) {
|
|
ExpandableListView view = this.getExpandableListView();
|
|
boolean expand = view.expandGroup(i);
|
|
if (!expand) {
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Collapse all Author Groups
|
|
*/
|
|
public void collapseAll() {
|
|
int i = 0;
|
|
while (i < numAuthors) {
|
|
ExpandableListView view = this.getExpandableListView();
|
|
boolean expand = view.collapseGroup(i);
|
|
if (!expand) {
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
|
|
super.onCreateContextMenu(menu, v, menuInfo);
|
|
ExpandableListView.ExpandableListContextMenuInfo info = (ExpandableListView.ExpandableListContextMenuInfo) menuInfo;
|
|
try {
|
|
// Only delete titles, not authors
|
|
if (ExpandableListView.getPackedPositionType(info.packedPosition) == 1) {
|
|
MenuItem delete = menu.add(0, DELETE_ID, 0, R.string.menu_delete);
|
|
delete.setIcon(android.R.drawable.ic_menu_delete);
|
|
}
|
|
} catch (NullPointerException e) {
|
|
// do nothing
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean onContextItemSelected(MenuItem item) {
|
|
switch(item.getItemId()) {
|
|
case DELETE_ID:
|
|
ExpandableListContextMenuInfo info = (ExpandableListContextMenuInfo) item.getMenuInfo();
|
|
mDbHelper.deleteBook(info.id);
|
|
fillData();
|
|
return true;
|
|
}
|
|
return super.onContextItemSelected(item);
|
|
}
|
|
|
|
/*
|
|
* Load the BookCatalogueTitle Activity
|
|
*
|
|
* return void
|
|
*/
|
|
private void sortByTitle() {
|
|
//Intent i = new Intent(this, BookCatalogueTitle.class);
|
|
//startActivityForResult(i, ACTIVITY_SORT);
|
|
sort = 1;
|
|
optionsMenu.clear();
|
|
onCreateOptionsMenu(optionsMenu);
|
|
fillData();
|
|
}
|
|
|
|
/*
|
|
* Load the BookCatalogueTitle Activity
|
|
*
|
|
* return void
|
|
*/
|
|
private void sortByAuthor() {
|
|
sort = 0;
|
|
optionsMenu.clear();
|
|
onCreateOptionsMenu(optionsMenu);
|
|
fillData();
|
|
}
|
|
|
|
/*
|
|
* Load the BookEdit Activity
|
|
*
|
|
* return void
|
|
*/
|
|
private void createBook() {
|
|
Intent i = new Intent(this, BookEdit.class);
|
|
startActivityForResult(i, ACTIVITY_CREATE);
|
|
}
|
|
|
|
/*
|
|
* Load the BookEdit Activity
|
|
*
|
|
* return void
|
|
*/
|
|
private void createBookISBN() {
|
|
Intent i = new Intent(this, BookISBNSearch.class);
|
|
startActivityForResult(i, ACTIVITY_ISBN);
|
|
}
|
|
|
|
/*
|
|
* Load the BookEdit Activity
|
|
*
|
|
* return void
|
|
*/
|
|
private void createBookScan() {
|
|
Intent intent = new Intent("com.google.zxing.client.android.SCAN");
|
|
//intent.putExtra("SCAN_MODE", "EAN_13");
|
|
startActivityForResult(intent, ACTIVITY_SCAN);
|
|
}
|
|
|
|
/*
|
|
* Load the BookEdit Activity
|
|
*
|
|
* return void
|
|
*/
|
|
private void manageBookselves() {
|
|
Intent i = new Intent(this, Bookshelf.class);
|
|
startActivityForResult(i, ACTIVITY_BOOKSHELF);
|
|
}
|
|
|
|
@Override
|
|
public boolean onChildClick(ExpandableListView l, View v, int position, int childPosition, long id) {
|
|
boolean result = super.onChildClick(l, v, position, childPosition, id);
|
|
if (sort == 0) {
|
|
Intent i = new Intent(this, BookEdit.class);
|
|
i.putExtra(CatalogueDBAdapter.KEY_ROWID, id);
|
|
startActivityForResult(i, ACTIVITY_EDIT);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
@Override
|
|
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
|
|
super.onActivityResult(requestCode, resultCode, intent);
|
|
switch(requestCode) {
|
|
case ACTIVITY_SCAN:
|
|
try {
|
|
String contents = intent.getStringExtra("SCAN_RESULT");
|
|
Toast.makeText(this, R.string.isbn_found, Toast.LENGTH_LONG).show();
|
|
Intent i = new Intent(this, BookISBNSearch.class);
|
|
i.putExtra("isbn", contents);
|
|
startActivityForResult(i, ACTIVITY_ISBN);
|
|
} catch (NullPointerException e) {
|
|
// This is not a scan result, but a normal return
|
|
fillData();
|
|
}
|
|
break;
|
|
case ACTIVITY_CREATE:
|
|
case ACTIVITY_EDIT:
|
|
case ACTIVITY_SORT:
|
|
case ACTIVITY_ISBN:
|
|
case ACTIVITY_BOOKSHELF:
|
|
fillData();
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
} |