mirror of
https://github.com/geometer/FBReaderJ.git
synced 2025-10-04 18:29:23 +02:00
Support for external books in the Library
git-svn-id: https://only.mawhrin.net/repos/FBReaderJ/trunk@1738 6a642e6f-84f6-412e-ac94-c4a38d5a04b0
This commit is contained in:
parent
5f4f6ac801
commit
b9b7f61ad9
7 changed files with 120 additions and 11 deletions
|
@ -15,6 +15,7 @@ DONE Возможность открывать локальные файлы и
|
||||||
DONE На этой странице есть ссылка на epub-файл "для ПК". http://www.zone4iphone.ru/index.php?p_id=7&b_id=18413
|
DONE На этой странице есть ссылка на epub-файл "для ПК". http://www.zone4iphone.ru/index.php?p_id=7&b_id=18413
|
||||||
Проверить скачивание книги браузером и возможность чтения из папки, куда файл был скачан.
|
Проверить скачивание книги браузером и возможность чтения из папки, куда файл был скачан.
|
||||||
** добавлять в библиотеку (сделать таблицу добавленных вручную книг)
|
** добавлять в библиотеку (сделать таблицу добавленных вручную книг)
|
||||||
|
** сделать новый диалог удаления файлов (удаление файла / удаление из библиотеки)
|
||||||
|
|
||||||
------------------------------
|
------------------------------
|
||||||
|
|
||||||
|
|
|
@ -173,7 +173,8 @@ public class LibraryTabActivity extends TabActivity implements MenuItem.OnMenuIt
|
||||||
menu.setHeaderTitle(tree.getName());
|
menu.setHeaderTitle(tree.getName());
|
||||||
final ZLResource resource = ZLResource.resource("libraryView");
|
final ZLResource resource = ZLResource.resource("libraryView");
|
||||||
menu.add(0, OPEN_BOOK_ITEM_ID, 0, resource.getResource("openBook").getValue());
|
menu.add(0, OPEN_BOOK_ITEM_ID, 0, resource.getResource("openBook").getValue());
|
||||||
if (Library.Instance().canDeleteBook(((BookTree)tree).Book)) {
|
if ((Library.Instance().getRemoveBookMode(((BookTree)tree).Book)
|
||||||
|
& Library.REMOVE_FROM_DISK) != 0) {
|
||||||
menu.add(0, DELETE_BOOK_ITEM_ID, 0, resource.getResource("deleteBook").getValue());
|
menu.add(0, DELETE_BOOK_ITEM_ID, 0, resource.getResource("deleteBook").getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -263,9 +264,11 @@ public class LibraryTabActivity extends TabActivity implements MenuItem.OnMenuIt
|
||||||
|
|
||||||
private class BookDeleter implements DialogInterface.OnClickListener {
|
private class BookDeleter implements DialogInterface.OnClickListener {
|
||||||
private final Book myBook;
|
private final Book myBook;
|
||||||
|
private final int myMode;
|
||||||
|
|
||||||
BookDeleter(Book book) {
|
BookDeleter(Book book, int removeMode) {
|
||||||
myBook = book;
|
myBook = book;
|
||||||
|
myMode = removeMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void invalidateView(View v) {
|
private void invalidateView(View v) {
|
||||||
|
@ -276,7 +279,7 @@ public class LibraryTabActivity extends TabActivity implements MenuItem.OnMenuIt
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
Library.Instance().deleteBook(myBook);
|
Library.Instance().removeBook(myBook, myMode);
|
||||||
|
|
||||||
invalidateView(findViewById(R.id.by_author));
|
invalidateView(findViewById(R.id.by_author));
|
||||||
invalidateView(findViewById(R.id.by_tag));
|
invalidateView(findViewById(R.id.by_tag));
|
||||||
|
@ -293,7 +296,7 @@ public class LibraryTabActivity extends TabActivity implements MenuItem.OnMenuIt
|
||||||
.setTitle(book.getTitle())
|
.setTitle(book.getTitle())
|
||||||
.setMessage(boxResource.getResource("message").getValue())
|
.setMessage(boxResource.getResource("message").getValue())
|
||||||
.setIcon(0)
|
.setIcon(0)
|
||||||
.setPositiveButton(buttonResource.getResource("yes").getValue(), new BookDeleter(book))
|
.setPositiveButton(buttonResource.getResource("yes").getValue(), new BookDeleter(book, Library.REMOVE_FROM_DISK))
|
||||||
.setNegativeButton(buttonResource.getResource("no").getValue(), null)
|
.setNegativeButton(buttonResource.getResource("no").getValue(), null)
|
||||||
.create().show();
|
.create().show();
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,8 @@ final class SQLiteBooksDatabase extends BooksDatabase {
|
||||||
|
|
||||||
private void migrate() {
|
private void migrate() {
|
||||||
final int version = myDatabase.getVersion();
|
final int version = myDatabase.getVersion();
|
||||||
if (version >= 8) {
|
final int currentVersion = 9;
|
||||||
|
if (version >= currentVersion) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ZLDialogManager.Instance().wait((version == 0) ? "creatingBooksDatabase" : "updatingBooksDatabase", new Runnable() {
|
ZLDialogManager.Instance().wait((version == 0) ? "creatingBooksDatabase" : "updatingBooksDatabase", new Runnable() {
|
||||||
|
@ -82,12 +83,14 @@ final class SQLiteBooksDatabase extends BooksDatabase {
|
||||||
updateTables6();
|
updateTables6();
|
||||||
case 7:
|
case 7:
|
||||||
updateTables7();
|
updateTables7();
|
||||||
|
case 8:
|
||||||
|
updateTables8();
|
||||||
}
|
}
|
||||||
myDatabase.setTransactionSuccessful();
|
myDatabase.setTransactionSuccessful();
|
||||||
myDatabase.endTransaction();
|
myDatabase.endTransaction();
|
||||||
|
|
||||||
myDatabase.execSQL("VACUUM");
|
myDatabase.execSQL("VACUUM");
|
||||||
myDatabase.setVersion(8);
|
myDatabase.setVersion(currentVersion);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -768,6 +771,42 @@ final class SQLiteBooksDatabase extends BooksDatabase {
|
||||||
myStorePositionStatement.execute();
|
myStorePositionStatement.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private SQLiteStatement myInsertIntoBookListStatement;
|
||||||
|
protected boolean insertIntoBookList(long bookId) {
|
||||||
|
if (myInsertIntoBookListStatement == null) {
|
||||||
|
myInsertIntoBookListStatement = myDatabase.compileStatement(
|
||||||
|
"INSERT OR IGNORE INTO BookList(book_id) VALUES (?)"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
myInsertIntoBookListStatement.bindLong(1, bookId);
|
||||||
|
myInsertIntoBookListStatement.execute();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SQLiteStatement myDeleteFromBookListStatement;
|
||||||
|
protected boolean deleteFromBookList(long bookId) {
|
||||||
|
if (myDeleteFromBookListStatement == null) {
|
||||||
|
myDeleteFromBookListStatement = myDatabase.compileStatement(
|
||||||
|
"DELETE FROM BookList WHERE book_id = ?"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
myDeleteFromBookListStatement.bindLong(1, bookId);
|
||||||
|
myDeleteFromBookListStatement.execute();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SQLiteStatement myCheckBookListStatement;
|
||||||
|
protected boolean checkBookList(long bookId) {
|
||||||
|
if (myCheckBookListStatement == null) {
|
||||||
|
myCheckBookListStatement = myDatabase.compileStatement(
|
||||||
|
"SELECT COUNT(*) FROM BookList WHERE book_id = ?"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
myCheckBookListStatement.bindLong(1, bookId);
|
||||||
|
return myCheckBookListStatement.simpleQueryForLong() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void createTables() {
|
private void createTables() {
|
||||||
myDatabase.execSQL(
|
myDatabase.execSQL(
|
||||||
"CREATE TABLE Books(" +
|
"CREATE TABLE Books(" +
|
||||||
|
@ -1014,4 +1053,10 @@ final class SQLiteBooksDatabase extends BooksDatabase {
|
||||||
myDatabase.execSQL("DELETE FROM BookTag WHERE book_id=" + id);
|
myDatabase.execSQL("DELETE FROM BookTag WHERE book_id=" + id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateTables8() {
|
||||||
|
myDatabase.execSQL(
|
||||||
|
"CREATE TABLE IF NOT EXISTS BookList ( " +
|
||||||
|
"book_id INTEGER UNIQUE NOT NULL REFERENCES Books (book_id))");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -234,6 +234,7 @@ public final class FBReader extends ZLApplication {
|
||||||
}
|
}
|
||||||
Book book = Book.getByFile(file);
|
Book book = Book.getByFile(file);
|
||||||
if (book != null) {
|
if (book != null) {
|
||||||
|
book.insertIntoBookList();
|
||||||
return book;
|
return book;
|
||||||
}
|
}
|
||||||
if (file.isArchive()) {
|
if (file.isArchive()) {
|
||||||
|
|
|
@ -73,7 +73,7 @@ public class Book {
|
||||||
book.loadLists();
|
book.loadLists();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fileInfos.check(physicalFile) && (book != null)) {
|
if (book != null && fileInfos.check(physicalFile)) {
|
||||||
return book;
|
return book;
|
||||||
}
|
}
|
||||||
fileInfos.save();
|
fileInfos.save();
|
||||||
|
@ -346,6 +346,12 @@ public class Book {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void insertIntoBookList() {
|
||||||
|
if (myId != -1) {
|
||||||
|
BooksDatabase.Instance().insertIntoBookList(myId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return (int)myId;
|
return (int)myId;
|
||||||
|
|
|
@ -95,4 +95,8 @@ public abstract class BooksDatabase {
|
||||||
|
|
||||||
protected abstract ZLTextPosition getStoredPosition(long bookId);
|
protected abstract ZLTextPosition getStoredPosition(long bookId);
|
||||||
protected abstract void storePosition(long bookId, ZLTextPosition position);
|
protected abstract void storePosition(long bookId, ZLTextPosition position);
|
||||||
|
|
||||||
|
protected abstract boolean insertIntoBookList(long bookId);
|
||||||
|
protected abstract boolean deleteFromBookList(long bookId);
|
||||||
|
protected abstract boolean checkBookList(long bookId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ public final class Library {
|
||||||
}
|
}
|
||||||
|
|
||||||
private final LinkedList<Book> myBooks = new LinkedList<Book>();
|
private final LinkedList<Book> myBooks = new LinkedList<Book>();
|
||||||
|
private final HashSet<Book> myExternalBooks = new HashSet<Book>();
|
||||||
private final LibraryTree myLibraryByAuthor = new RootTree();
|
private final LibraryTree myLibraryByAuthor = new RootTree();
|
||||||
private final LibraryTree myLibraryByTag = new RootTree();
|
private final LibraryTree myLibraryByTag = new RootTree();
|
||||||
private final LibraryTree myRecentBooks = new RootTree();
|
private final LibraryTree myRecentBooks = new RootTree();
|
||||||
|
@ -52,6 +53,7 @@ public final class Library {
|
||||||
myDoRebuild = true;
|
myDoRebuild = true;
|
||||||
|
|
||||||
myBooks.clear();
|
myBooks.clear();
|
||||||
|
myExternalBooks.clear();
|
||||||
myLibraryByAuthor.clear();
|
myLibraryByAuthor.clear();
|
||||||
myLibraryByTag.clear();
|
myLibraryByTag.clear();
|
||||||
myRecentBooks.clear();
|
myRecentBooks.clear();
|
||||||
|
@ -70,7 +72,7 @@ public final class Library {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Book getBook(ZLFile bookFile, FileInfoSet fileInfos, Map<Long,Book> saved, boolean doReadMetaInfo) {
|
private static Book getBook(ZLFile bookFile, FileInfoSet fileInfos, Map<Long,Book> saved, boolean doReadMetaInfo) {
|
||||||
Book book = saved.get(fileInfos.getId(bookFile));
|
Book book = saved.remove(fileInfos.getId(bookFile));
|
||||||
if (book == null) {
|
if (book == null) {
|
||||||
doReadMetaInfo = true;
|
doReadMetaInfo = true;
|
||||||
book = new Book(bookFile);
|
book = new Book(bookFile);
|
||||||
|
@ -98,6 +100,33 @@ public final class Library {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void collectExternalBooks(FileInfoSet fileInfos, Map<Long,Book> savedBooks) {
|
||||||
|
final HashSet<ZLPhysicalFile> myUpdatedFiles = new HashSet<ZLPhysicalFile>();
|
||||||
|
final HashSet<Long> files = new HashSet<Long>(savedBooks.keySet());
|
||||||
|
for (Long fileId: files) {
|
||||||
|
final ZLFile bookFile = fileInfos.getFile(fileId);
|
||||||
|
if (bookFile == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final ZLPhysicalFile physicalFile = bookFile.getPhysicalFile();
|
||||||
|
if (!physicalFile.exists()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
boolean reloadMetaInfo = false;
|
||||||
|
if (myUpdatedFiles.contains(physicalFile)) {
|
||||||
|
reloadMetaInfo = true;
|
||||||
|
} else if (!fileInfos.check(physicalFile)) {
|
||||||
|
reloadMetaInfo = true;
|
||||||
|
myUpdatedFiles.add(physicalFile);
|
||||||
|
}
|
||||||
|
final Book book = getBook(bookFile, fileInfos, savedBooks, reloadMetaInfo);
|
||||||
|
if (book != null) {
|
||||||
|
myBooks.add(book);
|
||||||
|
myExternalBooks.add(book);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private List<ZLPhysicalFile> collectPhysicalFiles() {
|
private List<ZLPhysicalFile> collectPhysicalFiles() {
|
||||||
final Queue<ZLFile> dirQueue = new LinkedList<ZLFile>();
|
final Queue<ZLFile> dirQueue = new LinkedList<ZLFile>();
|
||||||
final HashSet<ZLFile> dirSet = new HashSet<ZLFile>();
|
final HashSet<ZLFile> dirSet = new HashSet<ZLFile>();
|
||||||
|
@ -147,6 +176,8 @@ public final class Library {
|
||||||
//android.os.Debug.stopMethodTracing();
|
//android.os.Debug.stopMethodTracing();
|
||||||
//System.err.println("books have been synchronized " + (System.currentTimeMillis() - start));
|
//System.err.println("books have been synchronized " + (System.currentTimeMillis() - start));
|
||||||
|
|
||||||
|
collectExternalBooks(fileInfos, savedBooks);
|
||||||
|
|
||||||
//android.os.Debug.startMethodTracing("/sdcard/ll4");
|
//android.os.Debug.startMethodTracing("/sdcard/ll4");
|
||||||
fileInfos.save();
|
fileInfos.save();
|
||||||
//android.os.Debug.stopMethodTracing();
|
//android.os.Debug.stopMethodTracing();
|
||||||
|
@ -315,7 +346,18 @@ public final class Library {
|
||||||
db.saveRecentBookIds(ids);
|
db.saveRecentBookIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canDeleteBook(Book book) {
|
public static final int REMOVE_DONT_REMOVE = 0x00;
|
||||||
|
public static final int REMOVE_FROM_LIBRARY = 0x01;
|
||||||
|
public static final int REMOVE_FROM_DISK = 0x02;
|
||||||
|
public static final int REMOVE_FROM_LIBRARY_AND_DISK = REMOVE_FROM_LIBRARY | REMOVE_FROM_DISK;
|
||||||
|
|
||||||
|
public int getRemoveBookMode(Book book) {
|
||||||
|
synchronize();
|
||||||
|
return (myExternalBooks.contains(book) ? REMOVE_FROM_LIBRARY : REMOVE_DONT_REMOVE)
|
||||||
|
| (canDeleteBookFile(book) ? REMOVE_FROM_DISK : REMOVE_DONT_REMOVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean canDeleteBookFile(Book book) {
|
||||||
ZLFile file = book.File;
|
ZLFile file = book.File;
|
||||||
if (file.getPhysicalFile() == null) {
|
if (file.getPhysicalFile() == null) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -329,7 +371,10 @@ public final class Library {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteBook(Book book) {
|
public void removeBook(Book book, int removeMode) {
|
||||||
|
if (removeMode == REMOVE_DONT_REMOVE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
synchronize();
|
synchronize();
|
||||||
myBooks.remove(book);
|
myBooks.remove(book);
|
||||||
myLibraryByAuthor.removeBook(book);
|
myLibraryByAuthor.removeBook(book);
|
||||||
|
@ -341,6 +386,10 @@ public final class Library {
|
||||||
db.saveRecentBookIds(ids);
|
db.saveRecentBookIds(ids);
|
||||||
}
|
}
|
||||||
mySearchResult.removeBook(book);
|
mySearchResult.removeBook(book);
|
||||||
book.File.getPhysicalFile().delete();
|
|
||||||
|
BooksDatabase.Instance().deleteFromBookList(book.getId());
|
||||||
|
if ((removeMode & REMOVE_FROM_DISK) != 0) {
|
||||||
|
book.File.getPhysicalFile().delete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue