mirror of
https://github.com/geometer/FBReaderJ.git
synced 2025-10-05 02:39:23 +02:00
added context menu for TOC
selected current item in TOC implemented tag tree in library implemented full library database git-svn-id: https://only.mawhrin.net/repos/FBReaderJ/trunk@909 6a642e6f-84f6-412e-ac94-c4a38d5a04b0
This commit is contained in:
parent
fad63e3659
commit
68167fe2bc
43 changed files with 1055 additions and 1237 deletions
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<org.geometerplus.android.fbreader.TOCTreeItemView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||
|
@ -39,4 +39,4 @@
|
|||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
</LinearLayout>
|
||||
</org.geometerplus.android.fbreader.TOCTreeItemView>
|
||||
</LinearLayout>
|
||||
|
|
|
@ -26,6 +26,8 @@ import org.geometerplus.zlibrary.ui.android.library.ZLAndroidActivity;
|
|||
public class FBReader extends ZLAndroidActivity {
|
||||
protected ZLApplication createApplication(String fileName) {
|
||||
String[] args = (fileName != null) ? new String[] { fileName } : new String[0];
|
||||
return new org.geometerplus.fbreader.fbreader.FBReader(args);
|
||||
ZLApplication application = new org.geometerplus.fbreader.fbreader.FBReader(args);
|
||||
new SQLiteBooksDatabase();
|
||||
return application;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,368 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Geometer Plus <contact@geometerplus.com>
|
||||
*
|
||||
* This program 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package org.geometerplus.android.fbreader;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteStatement;
|
||||
import android.database.SQLException;
|
||||
import android.database.Cursor;
|
||||
import org.geometerplus.zlibrary.ui.android.library.ZLAndroidApplication;
|
||||
|
||||
import org.geometerplus.fbreader.collection.*;
|
||||
|
||||
final class SQLiteBooksDatabase extends BooksDatabase {
|
||||
private final SQLiteDatabase myDatabase;
|
||||
|
||||
SQLiteBooksDatabase() {
|
||||
myDatabase = ZLAndroidApplication.Instance().openOrCreateDatabase("books.db", Context.MODE_PRIVATE, null);
|
||||
if (myDatabase.getVersion() == 0) {
|
||||
createTables();
|
||||
}
|
||||
}
|
||||
|
||||
public void executeAsATransaction(Runnable actions) {
|
||||
myDatabase.beginTransaction();
|
||||
try {
|
||||
actions.run();
|
||||
myDatabase.setTransactionSuccessful();
|
||||
} finally {
|
||||
myDatabase.endTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
private void createTables() {
|
||||
myDatabase.beginTransaction();
|
||||
/*
|
||||
myDatabase.execSQL("DROP TABLE Books");
|
||||
myDatabase.execSQL("DROP TABLE Authors");
|
||||
myDatabase.execSQL("DROP TABLE Series");
|
||||
myDatabase.execSQL("DROP TABLE Tags");
|
||||
myDatabase.execSQL("DROP TABLE BookAuthor");
|
||||
myDatabase.execSQL("DROP TABLE BookSeries");
|
||||
myDatabase.execSQL("DROP TABLE BookTag");
|
||||
*/
|
||||
myDatabase.execSQL(
|
||||
"CREATE TABLE Books(" +
|
||||
"book_id INTEGER PRIMARY KEY," +
|
||||
"encoding TEXT," +
|
||||
"language TEXT," +
|
||||
"title TEXT NOT NULL," +
|
||||
"file_name TEXT UNIQUE NOT NULL)");
|
||||
myDatabase.execSQL(
|
||||
"CREATE TABLE Authors(" +
|
||||
"author_id INTEGER PRIMARY KEY," +
|
||||
"name TEXT NOT NULL," +
|
||||
"sort_key TEXT NOT NULL," +
|
||||
"CONSTRAINT Authors_Unique UNIQUE (name, sort_key))");
|
||||
myDatabase.execSQL(
|
||||
"CREATE TABLE BookAuthor(" +
|
||||
"author_id INTEGER NOT NULL REFERENCES Authors(author_id)," +
|
||||
"book_id INTEGER NOT NULL REFERENCES Books(book_id)," +
|
||||
"author_index INTEGER NOT NULL," +
|
||||
"CONSTRAINT BookAuthor_Unique0 UNIQUE (author_id, book_id)," +
|
||||
"CONSTRAINT BookAuthor_Unique1 UNIQUE (book_id, author_index))");
|
||||
myDatabase.execSQL(
|
||||
"CREATE TABLE Series(" +
|
||||
"series_id INTEGER PRIMARY KEY," +
|
||||
"name TEXT UNIQUE NOT NULL)");
|
||||
myDatabase.execSQL(
|
||||
"CREATE TABLE BookSeries(" +
|
||||
"series_id INTEGER NOT NULL REFERENCES Series(series_id)," +
|
||||
"book_id INTEGER NOT NULL UNIQUE REFERENCES Books(book_id)," +
|
||||
"book_index INTEGER)");
|
||||
myDatabase.execSQL(
|
||||
"CREATE TABLE Tags(" +
|
||||
"tag_id INTEGER PRIMARY KEY," +
|
||||
"name TEXT NOT NULL," +
|
||||
"parent INTEGER REFERENCES Tags(tag_id)," +
|
||||
"CONSTRAINT Tags_Unique UNIQUE (name, parent))");
|
||||
myDatabase.execSQL(
|
||||
"CREATE TABLE BookTag(" +
|
||||
"tag_id INTEGER REFERENCES Tags(tag_id)," +
|
||||
"book_id INTEGER REFERENCES Books(book_id)," +
|
||||
"CONSTRAINT BookTag_Unique UNIQUE (tag_id, book_id))");
|
||||
myDatabase.setTransactionSuccessful();
|
||||
myDatabase.endTransaction();
|
||||
|
||||
myDatabase.setVersion(1);
|
||||
}
|
||||
|
||||
private static void bindString(SQLiteStatement statement, int index, String value) {
|
||||
if (value != null) {
|
||||
statement.bindString(index, value);
|
||||
} else {
|
||||
statement.bindNull(index);
|
||||
}
|
||||
}
|
||||
|
||||
private static final String BOOKS_TABLE = "Books";
|
||||
private static final String[] BOOKS_COLUMNS = { "book_id", "encoding", "language", "title" };
|
||||
private static final String FILE_NAME_CONDITION = "file_name = ?";
|
||||
public long loadBook(BookDescription description) {
|
||||
final Cursor cursor = myDatabase.query(
|
||||
BOOKS_TABLE,
|
||||
BOOKS_COLUMNS,
|
||||
FILE_NAME_CONDITION, new String[] { description.FileName },
|
||||
null, null, null, null
|
||||
);
|
||||
long id = -1;
|
||||
if (cursor.moveToNext()) {
|
||||
id = cursor.getLong(0);
|
||||
description.setEncoding(cursor.getString(1));
|
||||
description.setLanguage(cursor.getString(2));
|
||||
description.setTitle(cursor.getString(3));
|
||||
}
|
||||
cursor.close();
|
||||
return id;
|
||||
}
|
||||
|
||||
private SQLiteStatement myUpdateBookInfoStatement;
|
||||
public void updateBookInfo(long bookId, String encoding, String language, String title) {
|
||||
if (myUpdateBookInfoStatement == null) {
|
||||
myUpdateBookInfoStatement = myDatabase.compileStatement(
|
||||
"UPDATE Books SET encoding = ? language = ? title = ? WHERE book_id = ?"
|
||||
);
|
||||
}
|
||||
bindString(myUpdateBookInfoStatement, 1, encoding);
|
||||
bindString(myUpdateBookInfoStatement, 2, language);
|
||||
myUpdateBookInfoStatement.bindString(3, title);
|
||||
myUpdateBookInfoStatement.bindLong(4, bookId);
|
||||
myUpdateBookInfoStatement.execute();
|
||||
}
|
||||
|
||||
private SQLiteStatement myInsertBookInfoStatement;
|
||||
public long insertBookInfo(String fileName, String encoding, String language, String title) {
|
||||
if (myInsertBookInfoStatement == null) {
|
||||
myInsertBookInfoStatement = myDatabase.compileStatement(
|
||||
"INSERT INTO Books (encoding,language,title,file_name) VALUES (?,?,?,?)"
|
||||
);
|
||||
}
|
||||
bindString(myInsertBookInfoStatement, 1, encoding);
|
||||
bindString(myInsertBookInfoStatement, 2, language);
|
||||
myInsertBookInfoStatement.bindString(3, title);
|
||||
myInsertBookInfoStatement.bindString(4, fileName);
|
||||
return myInsertBookInfoStatement.executeInsert();
|
||||
}
|
||||
|
||||
private SQLiteStatement myGetAuthorIdStatement;
|
||||
private SQLiteStatement myInsertAuthorStatement;
|
||||
private SQLiteStatement myInsertBookAuthorStatement;
|
||||
public void saveBookAuthorInfo(long bookId, long index, Author author) {
|
||||
if (myGetAuthorIdStatement == null) {
|
||||
myGetAuthorIdStatement = myDatabase.compileStatement(
|
||||
"SELECT author_id FROM Authors WHERE name = ? AND sort_key = ?"
|
||||
);
|
||||
myInsertAuthorStatement = myDatabase.compileStatement(
|
||||
"INSERT INTO Authors (name,sort_key) VALUES (?,?)"
|
||||
);
|
||||
myInsertBookAuthorStatement = myDatabase.compileStatement(
|
||||
"INSERT OR IGNORE INTO BookAuthor (book_id,author_id,author_index) VALUES (?,?,?)"
|
||||
);
|
||||
}
|
||||
|
||||
long authorId;
|
||||
try {
|
||||
myGetAuthorIdStatement.bindString(1, author.DisplayName);
|
||||
myGetAuthorIdStatement.bindString(2, author.SortKey);
|
||||
authorId = myGetAuthorIdStatement.simpleQueryForLong();
|
||||
} catch (SQLException e) {
|
||||
myInsertAuthorStatement.bindString(1, author.DisplayName);
|
||||
myInsertAuthorStatement.bindString(2, author.SortKey);
|
||||
authorId = myInsertAuthorStatement.executeInsert();
|
||||
}
|
||||
myInsertBookAuthorStatement.bindLong(1, bookId);
|
||||
myInsertBookAuthorStatement.bindLong(2, authorId);
|
||||
myInsertBookAuthorStatement.bindLong(3, index);
|
||||
myInsertBookAuthorStatement.execute();
|
||||
}
|
||||
|
||||
public ArrayList<Author> loadAuthors(long bookId) {
|
||||
final Cursor cursor = myDatabase.rawQuery("SELECT Authors.name,Authors.sort_key FROM BookAuthor INNER JOIN Authors ON Authors.author_id = BookAuthor.author_id WHERE BookAuthor.book_id = ?", new String[] { "" + bookId });
|
||||
if (!cursor.moveToNext()) {
|
||||
return null;
|
||||
}
|
||||
ArrayList<Author> list = new ArrayList<Author>(cursor.getCount());
|
||||
do {
|
||||
list.add(new Author(cursor.getString(0), cursor.getString(1)));
|
||||
} while (cursor.moveToNext());
|
||||
cursor.close();
|
||||
return list;
|
||||
}
|
||||
|
||||
private HashMap<Tag,Long> myIdByTag = new HashMap<Tag,Long>();
|
||||
private HashMap<Long,Tag> myTagById = new HashMap<Long,Tag>();
|
||||
|
||||
private SQLiteStatement myGetTagIdStatement;
|
||||
private SQLiteStatement myCreateTagIdStatement;
|
||||
private long getTagId(Tag tag) {
|
||||
if (myGetTagIdStatement == null) {
|
||||
myGetTagIdStatement = myDatabase.compileStatement(
|
||||
"SELECT tag_id FROM Tags WHERE parent = ? AND name = ?"
|
||||
);
|
||||
myCreateTagIdStatement = myDatabase.compileStatement(
|
||||
"INSERT INTO Tags (parent,name) VALUES (?,?)"
|
||||
);
|
||||
}
|
||||
{
|
||||
final Long id = myIdByTag.get(tag);
|
||||
if (id != null) {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
if (tag.Parent != null) {
|
||||
myGetTagIdStatement.bindLong(1, getTagId(tag.Parent));
|
||||
} else {
|
||||
myGetTagIdStatement.bindNull(1);
|
||||
}
|
||||
myGetTagIdStatement.bindString(2, tag.Name);
|
||||
long id;
|
||||
try {
|
||||
id = myGetTagIdStatement.simpleQueryForLong();
|
||||
} catch (SQLException e) {
|
||||
if (tag.Parent != null) {
|
||||
myCreateTagIdStatement.bindLong(1, getTagId(tag.Parent));
|
||||
} else {
|
||||
myCreateTagIdStatement.bindNull(1);
|
||||
}
|
||||
myCreateTagIdStatement.bindString(2, tag.Name);
|
||||
id = myCreateTagIdStatement.executeInsert();
|
||||
}
|
||||
myIdByTag.put(tag, id);
|
||||
myTagById.put(id, tag);
|
||||
return id;
|
||||
}
|
||||
|
||||
private SQLiteStatement myInsertBookTagStatement;
|
||||
public void saveBookTagInfo(long bookId, Tag tag) {
|
||||
if (myInsertBookTagStatement == null) {
|
||||
myInsertBookTagStatement = myDatabase.compileStatement(
|
||||
"INSERT INTO BookTag (book_id,tag_id) VALUES (?,?)"
|
||||
);
|
||||
}
|
||||
myInsertBookTagStatement.bindLong(1, bookId);
|
||||
myInsertBookTagStatement.bindLong(2, getTagId(tag));
|
||||
myInsertBookTagStatement.execute();
|
||||
}
|
||||
|
||||
private Tag getTagById(long id) {
|
||||
Tag tag = myTagById.get(id);
|
||||
if (tag == null) {
|
||||
final Cursor cursor = myDatabase.rawQuery("SELECT parent,name FROM Tags WHERE tag_id = ?", new String[] { "" + id });
|
||||
if (cursor.moveToNext()) {
|
||||
final Tag parent = cursor.isNull(0) ? null : getTagById(cursor.getLong(0));
|
||||
tag = Tag.getTag(parent, cursor.getString(1));
|
||||
myIdByTag.put(tag, id);
|
||||
myTagById.put(id, tag);
|
||||
}
|
||||
cursor.close();
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
|
||||
public ArrayList<Tag> loadTags(long bookId) {
|
||||
final Cursor cursor = myDatabase.rawQuery("SELECT Tags.tag_id FROM BookTag INNER JOIN Tags ON Tags.tag_id = BookTag.tag_id WHERE BookTag.book_id = ?", new String[] { "" + bookId });
|
||||
if (!cursor.moveToNext()) {
|
||||
return null;
|
||||
}
|
||||
ArrayList<Tag> list = new ArrayList<Tag>(cursor.getCount());
|
||||
do {
|
||||
list.add(getTagById(cursor.getLong(0)));
|
||||
} while (cursor.moveToNext());
|
||||
cursor.close();
|
||||
return list;
|
||||
}
|
||||
|
||||
private SQLiteStatement myGetSeriesIdStatement;
|
||||
private SQLiteStatement myInsertSeriesStatement;
|
||||
private SQLiteStatement myInsertBookSeriesStatement;
|
||||
private SQLiteStatement myDeleteBookSeriesStatement;
|
||||
public void saveBookSeriesInfo(long bookId, SeriesInfo seriesInfo) {
|
||||
if (myGetSeriesIdStatement == null) {
|
||||
myGetSeriesIdStatement = myDatabase.compileStatement(
|
||||
"SELECT series_id FROM Series WHERE name = ?"
|
||||
);
|
||||
myInsertSeriesStatement = myDatabase.compileStatement(
|
||||
"INSERT INTO Series (name) VALUES (?)"
|
||||
);
|
||||
myInsertBookSeriesStatement = myDatabase.compileStatement(
|
||||
"INSERT OR REPLACE INTO BookSeries (book_id,series_id,book_index) VALUES (?,?,?)"
|
||||
);
|
||||
myDeleteBookSeriesStatement = myDatabase.compileStatement(
|
||||
"DELETE FROM BookSeries WHERE book_id = ?"
|
||||
);
|
||||
}
|
||||
|
||||
if (seriesInfo == null) {
|
||||
myDeleteBookSeriesStatement.bindLong(1, bookId);
|
||||
myDeleteBookSeriesStatement.execute();
|
||||
} else {
|
||||
long seriesId;
|
||||
try {
|
||||
myGetSeriesIdStatement.bindString(1, seriesInfo.Name);
|
||||
seriesId = myGetSeriesIdStatement.simpleQueryForLong();
|
||||
} catch (SQLException e) {
|
||||
myInsertSeriesStatement.bindString(1, seriesInfo.Name);
|
||||
seriesId = myInsertSeriesStatement.executeInsert();
|
||||
}
|
||||
myInsertBookSeriesStatement.bindLong(1, bookId);
|
||||
myInsertBookSeriesStatement.bindLong(2, seriesId);
|
||||
myInsertBookSeriesStatement.bindLong(3, seriesInfo.Index);
|
||||
myInsertBookSeriesStatement.execute();
|
||||
}
|
||||
}
|
||||
|
||||
public SeriesInfo loadSeriesInfo(long bookId) {
|
||||
final Cursor cursor = myDatabase.rawQuery("SELECT Series.name,BookSeries.book_index FROM BookSeries INNER JOIN Series ON Series.series_id = BookSeries.series_id WHERE BookSeries.book_id = ?", new String[] { "" + bookId });
|
||||
SeriesInfo info = null;
|
||||
if (cursor.moveToNext()) {
|
||||
info = new SeriesInfo(cursor.getString(0), cursor.getLong(1));
|
||||
}
|
||||
cursor.close();
|
||||
return info;
|
||||
}
|
||||
|
||||
private SQLiteStatement myResetBookInfoStatement;
|
||||
private final static String myBookIdWhereClause = "book_id = ?";
|
||||
public void resetBookInfo(String fileName) {
|
||||
if (myResetBookInfoStatement == null) {
|
||||
myResetBookInfoStatement = myDatabase.compileStatement(
|
||||
"SELECT book_id FROM Books WHERE file_name = ?"
|
||||
);
|
||||
}
|
||||
myResetBookInfoStatement.bindString(1, fileName);
|
||||
try {
|
||||
final long bookId = myResetBookInfoStatement.simpleQueryForLong();
|
||||
final String[] parameters = { "" + bookId };
|
||||
executeAsATransaction(new Runnable() {
|
||||
public void run() {
|
||||
myDatabase.delete("Books", myBookIdWhereClause, parameters);
|
||||
myDatabase.delete("BookAuthor", myBookIdWhereClause, parameters);
|
||||
myDatabase.delete("BookSeries", myBookIdWhereClause, parameters);
|
||||
myDatabase.delete("BookTag", myBookIdWhereClause, parameters);
|
||||
}
|
||||
});
|
||||
} catch (SQLException e) {
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,8 +21,7 @@ package org.geometerplus.android.fbreader;
|
|||
|
||||
import android.os.Bundle;
|
||||
import android.view.*;
|
||||
import android.widget.TextView;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.*;
|
||||
import android.content.Context;
|
||||
import android.app.ListActivity;
|
||||
import android.content.res.TypedArray;
|
||||
|
@ -30,22 +29,46 @@ import android.graphics.drawable.Drawable;
|
|||
|
||||
import org.geometerplus.zlibrary.core.application.ZLApplication;
|
||||
import org.geometerplus.zlibrary.core.tree.ZLTree;
|
||||
import org.geometerplus.zlibrary.core.tree.ZLStringTree;
|
||||
|
||||
import org.geometerplus.zlibrary.ui.android.R;
|
||||
|
||||
import org.geometerplus.fbreader.bookmodel.ContentsTree;
|
||||
import org.geometerplus.zlibrary.text.view.impl.ZLTextWordCursor;
|
||||
import org.geometerplus.fbreader.bookmodel.TOCTree;
|
||||
import org.geometerplus.fbreader.fbreader.FBReader;
|
||||
import org.geometerplus.fbreader.fbreader.BookTextView;
|
||||
|
||||
public class TOCActivity extends ListActivity {
|
||||
private TOCAdapter myAdapter;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle bundle) {
|
||||
super.onCreate(bundle);
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
|
||||
final FBReader fbreader = (FBReader)ZLApplication.Instance();
|
||||
new TOCAdapter(fbreader.Model.ContentsTree);
|
||||
final TOCTree root = fbreader.Model.TOCTree;
|
||||
myAdapter = new TOCAdapter(root);
|
||||
final ZLTextWordCursor cursor = fbreader.BookTextView.StartCursor;
|
||||
int index = cursor.getParagraphCursor().Index;
|
||||
if (cursor.isEndOfParagraph()) {
|
||||
++index;
|
||||
}
|
||||
TOCTree treeToSelect = null;
|
||||
// TODO: rewrite for better speed
|
||||
// TODO: process multi-model texts
|
||||
for (int i = 0; i < root.getSize(); ++i) {
|
||||
final TOCTree tree = root.getTree(i);
|
||||
final TOCTree.Reference reference = tree.getReference();
|
||||
if (reference == null) {
|
||||
continue;
|
||||
}
|
||||
if (reference.ParagraphIndex > index) {
|
||||
break;
|
||||
}
|
||||
treeToSelect = tree;
|
||||
}
|
||||
myAdapter.selectItem(treeToSelect);
|
||||
|
||||
/*
|
||||
int selectedIndex = adapter.getSelectedIndex();
|
||||
if (selectedIndex >= 0) {
|
||||
|
@ -54,31 +77,69 @@ public class TOCActivity extends ListActivity {
|
|||
*/
|
||||
}
|
||||
|
||||
private final class TOCAdapter extends ZLTreeAdapter {
|
||||
private final ContentsTree myContentsTree;
|
||||
private static final int PROCESS_TREE_ITEM_ID = 0;
|
||||
private static final int READ_BOOK_ITEM_ID = 1;
|
||||
|
||||
TOCAdapter(ContentsTree tree) {
|
||||
super(getListView(), tree);
|
||||
myContentsTree = tree;
|
||||
@Override
|
||||
public boolean onContextItemSelected(MenuItem item) {
|
||||
final int position = ((AdapterView.AdapterContextMenuInfo)item.getMenuInfo()).position;
|
||||
final TOCTree tree = (TOCTree)myAdapter.getItem(position);
|
||||
switch (item.getItemId()) {
|
||||
case PROCESS_TREE_ITEM_ID:
|
||||
myAdapter.runTreeItem(tree);
|
||||
return true;
|
||||
case READ_BOOK_ITEM_ID:
|
||||
myAdapter.openBookText(tree);
|
||||
return true;
|
||||
}
|
||||
return super.onContextItemSelected(item);
|
||||
}
|
||||
|
||||
private final class TOCAdapter extends ZLTreeAdapter {
|
||||
private final TOCTree myRoot;
|
||||
|
||||
TOCAdapter(TOCTree root) {
|
||||
super(getListView(), root);
|
||||
myRoot = root;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
|
||||
final int position = ((AdapterView.AdapterContextMenuInfo)menuInfo).position;
|
||||
final TOCTree tree = (TOCTree)getItem(position);
|
||||
if (tree.hasChildren()) {
|
||||
menu.setHeaderTitle(tree.getText());
|
||||
// TODO: use resources
|
||||
menu.add(0, PROCESS_TREE_ITEM_ID, 0, isOpen(tree) ? "Collapse tree" : "Expand tree");
|
||||
menu.add(0, READ_BOOK_ITEM_ID, 0, "Read book text");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
final View view = (convertView != null) ? convertView :
|
||||
LayoutInflater.from(parent.getContext()).inflate(R.layout.toc_tree_item, parent, false);
|
||||
final ZLStringTree tree = (ZLStringTree)getItem(position);
|
||||
final TOCTree tree = (TOCTree)getItem(position);
|
||||
setIcon((ImageView)view.findViewById(R.id.toc_tree_item_icon), tree);
|
||||
((TextView)view.findViewById(R.id.toc_tree_item_text)).setText(tree.getText());
|
||||
return view;
|
||||
}
|
||||
|
||||
void openBookText(TOCTree tree) {
|
||||
final TOCTree.Reference reference = tree.getReference();
|
||||
if (reference != null) {
|
||||
final FBReader fbreader = (FBReader)ZLApplication.Instance();
|
||||
fbreader.BookTextView.gotoParagraphSafe(reference.Model, reference.ParagraphIndex);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean runTreeItem(ZLTree tree) {
|
||||
if (super.runTreeItem(tree)) {
|
||||
return true;
|
||||
}
|
||||
final ContentsTree.Reference reference = myContentsTree.getReference((ZLStringTree)tree);
|
||||
final FBReader fbreader = (FBReader)ZLApplication.Instance();
|
||||
fbreader.BookTextView.gotoParagraphSafe(reference.Model, reference.ParagraphIndex);
|
||||
finish();
|
||||
openBookText((TOCTree)tree);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ import org.geometerplus.zlibrary.core.tree.ZLTree;
|
|||
|
||||
import org.geometerplus.zlibrary.ui.android.R;
|
||||
|
||||
abstract class ZLTreeAdapter extends BaseAdapter implements AdapterView.OnItemClickListener, View.OnCreateContextMenuListener, View.OnKeyListener {
|
||||
abstract class ZLTreeAdapter extends BaseAdapter implements AdapterView.OnItemClickListener, View.OnCreateContextMenuListener {
|
||||
private final ListView myParent;
|
||||
private final ZLTree myTree;
|
||||
private final ZLTree[] myItems;
|
||||
|
@ -56,14 +56,52 @@ abstract class ZLTreeAdapter extends BaseAdapter implements AdapterView.OnItemCl
|
|||
myOpenItems.add(tree);
|
||||
|
||||
parent.setAdapter(this);
|
||||
parent.setOnKeyListener(this);
|
||||
parent.setOnItemClickListener(this);
|
||||
parent.setOnCreateContextMenuListener(this);
|
||||
}
|
||||
|
||||
public final void openTree(ZLTree tree) {
|
||||
if (tree == null) {
|
||||
return;
|
||||
}
|
||||
while (!myOpenItems.contains(tree)) {
|
||||
myOpenItems.add(tree);
|
||||
tree = tree.getParent();
|
||||
}
|
||||
}
|
||||
|
||||
protected final boolean isOpen(ZLTree tree) {
|
||||
return myOpenItems.contains(tree);
|
||||
}
|
||||
|
||||
public final void selectItem(ZLTree tree) {
|
||||
if (tree == null) {
|
||||
return;
|
||||
}
|
||||
openTree(tree.getParent());
|
||||
int index = 0;
|
||||
while (true) {
|
||||
ZLTree<?> parent = tree.getParent();
|
||||
if (parent == null) {
|
||||
break;
|
||||
}
|
||||
for (ZLTree sibling : parent.subTrees()) {
|
||||
if (sibling == tree) {
|
||||
break;
|
||||
}
|
||||
index += getCount(sibling);
|
||||
}
|
||||
tree = parent;
|
||||
++index;
|
||||
}
|
||||
if (index > 0) {
|
||||
myParent.setSelection(index - 1);
|
||||
}
|
||||
}
|
||||
|
||||
private int getCount(ZLTree<?> tree) {
|
||||
int count = 1;
|
||||
if (myOpenItems.contains(tree)) {
|
||||
if (isOpen(tree)) {
|
||||
for (ZLTree subtree : tree.subTrees()) {
|
||||
count += getCount(subtree);
|
||||
}
|
||||
|
@ -119,7 +157,7 @@ abstract class ZLTreeAdapter extends BaseAdapter implements AdapterView.OnItemCl
|
|||
if (!tree.hasChildren()) {
|
||||
return false;
|
||||
}
|
||||
if (myOpenItems.contains(tree)) {
|
||||
if (isOpen(tree)) {
|
||||
myOpenItems.remove(tree);
|
||||
} else {
|
||||
myOpenItems.add(tree);
|
||||
|
@ -136,38 +174,13 @@ abstract class ZLTreeAdapter extends BaseAdapter implements AdapterView.OnItemCl
|
|||
private boolean myContextMenuInProgress;
|
||||
|
||||
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
|
||||
System.err.println("onCreateContextMenu");
|
||||
menu.add("Item 0");
|
||||
menu.add("Item 1");
|
||||
menu.add("Item 2");
|
||||
}
|
||||
|
||||
public final boolean onKey(View view, int keyCode, KeyEvent keyEvent) {
|
||||
switch (keyEvent.getAction()) {
|
||||
case KeyEvent.ACTION_UP:
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_DPAD_CENTER:
|
||||
case KeyEvent.KEYCODE_ENTER:
|
||||
runTreeItem((ZLTree)((ListView)view).getSelectedItem());
|
||||
return true;
|
||||
case KeyEvent.KEYCODE_BACK:
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case KeyEvent.ACTION_DOWN:
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_DPAD_CENTER:
|
||||
case KeyEvent.KEYCODE_ENTER:
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public abstract View getView(int position, View convertView, ViewGroup parent);
|
||||
|
||||
protected final void setIcon(ImageView imageView, ZLTree tree) {
|
||||
if (tree.hasChildren()) {
|
||||
if (myOpenItems.contains(tree)) {
|
||||
if (isOpen(tree)) {
|
||||
imageView.setImageResource(R.drawable.tree_icon_group_open);
|
||||
} else {
|
||||
imageView.setImageResource(R.drawable.tree_icon_group_closed);
|
||||
|
|
|
@ -26,13 +26,13 @@ import org.geometerplus.zlibrary.core.image.*;
|
|||
|
||||
import org.geometerplus.zlibrary.text.model.*;
|
||||
|
||||
import org.geometerplus.fbreader.description.BookDescription;
|
||||
import org.geometerplus.fbreader.collection.BookDescription;
|
||||
import org.geometerplus.fbreader.formats.*;
|
||||
|
||||
public final class BookModel {
|
||||
public final BookDescription Description;
|
||||
public final ZLTextPlainModel BookTextModel = new ZLTextPlainModel(65536, "/sdcard/Books/.FBReader", "cache");
|
||||
public final ContentsTree ContentsTree = new ContentsTree();
|
||||
public final TOCTree TOCTree = new TOCTree();
|
||||
|
||||
private final HashMap<String,ZLTextPlainModel> myFootnotes = new HashMap<String,ZLTextPlainModel>();
|
||||
private final HashMap myInternalHyperlinks = new HashMap();
|
||||
|
|
|
@ -24,7 +24,6 @@ import org.geometerplus.zlibrary.core.util.*;
|
|||
|
||||
import org.geometerplus.zlibrary.core.image.ZLImage;
|
||||
import org.geometerplus.zlibrary.text.model.*;
|
||||
import org.geometerplus.zlibrary.core.tree.ZLStringTree;
|
||||
|
||||
public class BookReader {
|
||||
public final BookModel Model;
|
||||
|
@ -46,11 +45,11 @@ public class BookReader {
|
|||
private boolean myInsideTitle = false;
|
||||
private boolean mySectionContainsRegularContents = false;
|
||||
|
||||
private ZLStringTree myCurrentContentsTree;
|
||||
private TOCTree myCurrentContentsTree;
|
||||
|
||||
public BookReader(BookModel model) {
|
||||
Model = model;
|
||||
myCurrentContentsTree = model.ContentsTree;
|
||||
myCurrentContentsTree = model.TOCTree;
|
||||
}
|
||||
|
||||
private final void flushTextBufferToParagraph() {
|
||||
|
@ -242,7 +241,7 @@ public class BookReader {
|
|||
if (referenceNumber == -1) {
|
||||
referenceNumber = textModel.getParagraphsNumber();
|
||||
}
|
||||
ZLStringTree parentTree = myCurrentContentsTree;
|
||||
TOCTree parentTree = myCurrentContentsTree;
|
||||
if (parentTree.getLevel() > 0) {
|
||||
final ZLTextBuffer contentsBuffer = myContentsBuffer;
|
||||
if (!contentsBuffer.isEmpty()) {
|
||||
|
@ -254,14 +253,14 @@ public class BookReader {
|
|||
} else {
|
||||
myContentsBuffer.clear();
|
||||
}
|
||||
ZLStringTree tree = parentTree.createSubTree();
|
||||
Model.ContentsTree.setReference(tree, myCurrentTextModel, referenceNumber);
|
||||
TOCTree tree = parentTree.createSubTree();
|
||||
tree.setReference(myCurrentTextModel, referenceNumber);
|
||||
myCurrentContentsTree = tree;
|
||||
}
|
||||
}
|
||||
|
||||
public final void endContentsParagraph() {
|
||||
final ZLStringTree tree = myCurrentContentsTree;
|
||||
final TOCTree tree = myCurrentContentsTree;
|
||||
final ZLTextBuffer contentsBuffer = myContentsBuffer;
|
||||
if (tree.getLevel() == 0) {
|
||||
contentsBuffer.clear();
|
||||
|
@ -281,10 +280,10 @@ public class BookReader {
|
|||
}
|
||||
|
||||
public final void setReference(int contentsParagraphNumber, ZLTextModel textModel, int referenceNumber) {
|
||||
final ContentsTree contentsTree = Model.ContentsTree;
|
||||
final TOCTree contentsTree = Model.TOCTree;
|
||||
if (contentsParagraphNumber < contentsTree.getSize()) {
|
||||
contentsTree.setReference(
|
||||
contentsTree.getTree(contentsParagraphNumber), textModel, referenceNumber
|
||||
contentsTree.getTree(contentsParagraphNumber).setReference(
|
||||
textModel, referenceNumber
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2007-2009 Geometer Plus <contact@geometerplus.com>
|
||||
* Copyright (C) 2009 Geometer Plus <contact@geometerplus.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -19,21 +19,42 @@
|
|||
|
||||
package org.geometerplus.fbreader.bookmodel;
|
||||
|
||||
import java.util.*;
|
||||
import org.geometerplus.zlibrary.core.util.*;
|
||||
import org.geometerplus.zlibrary.core.tree.ZLTree;
|
||||
|
||||
import org.geometerplus.zlibrary.text.model.ZLTextModel;
|
||||
import org.geometerplus.zlibrary.core.tree.ZLStringTree;
|
||||
|
||||
public class ContentsTree extends ZLStringTree {
|
||||
private final HashMap<ZLStringTree,Reference> myReferenceByTree = new HashMap<ZLStringTree,Reference>();
|
||||
public class TOCTree extends ZLTree<TOCTree> {
|
||||
private String myText;
|
||||
private Reference myReference;
|
||||
|
||||
public Reference getReference(ZLStringTree tree) {
|
||||
return myReferenceByTree.get(tree);
|
||||
protected TOCTree() {
|
||||
super();
|
||||
}
|
||||
|
||||
public void setReference(ZLStringTree tree, ZLTextModel model, int reference) {
|
||||
myReferenceByTree.put(tree, new Reference(reference, model));
|
||||
private TOCTree(TOCTree parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
public final String getText() {
|
||||
return myText;
|
||||
}
|
||||
|
||||
public final void setText(String text) {
|
||||
myText = text;
|
||||
}
|
||||
|
||||
public Reference getReference() {
|
||||
return myReference;
|
||||
}
|
||||
|
||||
public void setReference(ZLTextModel model, int reference) {
|
||||
myReference = new Reference(reference, model);
|
||||
}
|
||||
|
||||
public final TOCTree createSubTree() {
|
||||
TOCTree subtree = new TOCTree(this);
|
||||
addSubTree(subtree);
|
||||
return subtree;
|
||||
}
|
||||
|
||||
public static class Reference {
|
|
@ -1,167 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Geometer Plus <contact@geometerplus.com>
|
||||
*
|
||||
* This program 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package org.geometerplus.fbreader.booksdb;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
|
||||
public final class BookInfo {
|
||||
private static boolean equals(Object o0, Object o1) {
|
||||
if (o0 == null) {
|
||||
return o1 == null;
|
||||
}
|
||||
return o0.equals(o1);
|
||||
}
|
||||
|
||||
private final SQLiteDatabase myDatabase = BooksDatabase.Instance().Database;
|
||||
|
||||
private String myBookId;
|
||||
|
||||
public final String FileName;
|
||||
|
||||
private String myTitle;
|
||||
private String myAuthorName;
|
||||
private String myAuthorSortKey;
|
||||
private String myLanguage;
|
||||
private String myEncoding;
|
||||
private String mySeries;
|
||||
private int myNumberInSeries;
|
||||
|
||||
private boolean myIsSaved;
|
||||
private boolean myIsChanged;
|
||||
|
||||
public BookInfo(String fileName) {
|
||||
FileName = fileName;
|
||||
// TODO: implement
|
||||
myTitle = "";
|
||||
myLanguage = "";
|
||||
myEncoding = "";
|
||||
myAuthorName = "";
|
||||
myAuthorSortKey = "";
|
||||
myIsSaved = false;
|
||||
}
|
||||
|
||||
public boolean isSaved() {
|
||||
return myIsSaved;
|
||||
}
|
||||
|
||||
public void save() {
|
||||
if (myIsChanged) {
|
||||
// TODO: implement
|
||||
myIsChanged = false;
|
||||
//myIsSaved = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
final String whereClause = "book_id = ?";
|
||||
final String[] parameters = new String[] { myBookId };
|
||||
myDatabase.delete("Books", whereClause, parameters);
|
||||
myDatabase.delete("BookAuthor", whereClause, parameters);
|
||||
myDatabase.delete("BookSeries", whereClause, parameters);
|
||||
myDatabase.delete("BookTag", whereClause, parameters);
|
||||
myTitle = "";
|
||||
myLanguage = "";
|
||||
myEncoding = "";
|
||||
myAuthorName = "";
|
||||
myAuthorSortKey = "";
|
||||
mySeries = null;
|
||||
myNumberInSeries = 0;
|
||||
myIsChanged = false;
|
||||
myIsSaved = false;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return myTitle;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
if (!myTitle.equals(title)) {
|
||||
myTitle = title;
|
||||
myIsChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
public String getAuthorName() {
|
||||
return myAuthorName;
|
||||
}
|
||||
|
||||
public void setAuthorName(String authorName) {
|
||||
if (!myAuthorName.equals(authorName)) {
|
||||
myAuthorName = authorName;
|
||||
myIsChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
public String getAuthorSortKey() {
|
||||
return myAuthorSortKey;
|
||||
}
|
||||
|
||||
public void setAuthorSortKey(String authorSortKey) {
|
||||
if (!myAuthorSortKey.equals(authorSortKey)) {
|
||||
myAuthorSortKey = authorSortKey;
|
||||
myIsChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
public String getLanguage() {
|
||||
return myLanguage;
|
||||
}
|
||||
|
||||
public void setLanguage(String language) {
|
||||
if (!myLanguage.equals(language)) {
|
||||
myLanguage = language;
|
||||
myIsChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
public String getEncoding() {
|
||||
return myEncoding;
|
||||
}
|
||||
|
||||
public void setEncoding(String encoding) {
|
||||
if (!myEncoding.equals(encoding)) {
|
||||
myEncoding = encoding;
|
||||
myIsChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
public String getSeries() {
|
||||
return mySeries;
|
||||
}
|
||||
|
||||
public void setSeries(String series) {
|
||||
if (!equals(mySeries, series)) {
|
||||
mySeries = series;
|
||||
myIsChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
public int getNumberInSeries() {
|
||||
return myNumberInSeries;
|
||||
}
|
||||
|
||||
public void setNumberInSeries(int numberInSeries) {
|
||||
if (myNumberInSeries != numberInSeries) {
|
||||
myNumberInSeries = numberInSeries;
|
||||
myIsChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,96 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Geometer Plus <contact@geometerplus.com>
|
||||
*
|
||||
* This program 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package org.geometerplus.fbreader.booksdb;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import org.geometerplus.zlibrary.ui.android.library.ZLAndroidApplication;
|
||||
|
||||
class BooksDatabase {
|
||||
private static BooksDatabase ourInstance;
|
||||
|
||||
static BooksDatabase Instance() {
|
||||
if (ourInstance == null) {
|
||||
ourInstance = new BooksDatabase(ZLAndroidApplication.Instance());
|
||||
}
|
||||
return ourInstance;
|
||||
}
|
||||
|
||||
final SQLiteDatabase Database;
|
||||
|
||||
private BooksDatabase(Context context) {
|
||||
Database = context.openOrCreateDatabase("books.db", Context.MODE_PRIVATE, null);
|
||||
if (Database.getVersion() == 0) {
|
||||
Database.beginTransaction();
|
||||
/*
|
||||
Database.execSQL("DROP TABLE Books");
|
||||
Database.execSQL("DROP TABLE Authors");
|
||||
Database.execSQL("DROP TABLE Series");
|
||||
Database.execSQL("DROP TABLE Tags");
|
||||
Database.execSQL("DROP TABLE BookAuthor");
|
||||
Database.execSQL("DROP TABLE BookSeries");
|
||||
Database.execSQL("DROP TABLE BookTag");
|
||||
*/
|
||||
Database.execSQL(
|
||||
"CREATE TABLE Books(" +
|
||||
"book_id INTEGER PRIMARY KEY," +
|
||||
"encoding TEXT," +
|
||||
"lenguage TEXT," +
|
||||
"title TEXT NOT NULL," +
|
||||
"file_name TEXT UNIQUE NOT NULL)");
|
||||
Database.execSQL(
|
||||
"CREATE TABLE Authors(" +
|
||||
"author_id INTEGER PRIMARY KEY," +
|
||||
"name TEXT NOT NULL," +
|
||||
"sort_key TEXT NOT NULL," +
|
||||
"CONSTRAINT Authors_Unique UNIQUE (name, sort_key))");
|
||||
Database.execSQL(
|
||||
"CREATE TABLE BookAuthor(" +
|
||||
"author_id INTEGER NOT NULL REFERENCES Authors(author_id)," +
|
||||
"book_id INTEGER NOT NULL REFERENCES Books(book_id)," +
|
||||
"CONSTRAINT BookAuthor_Unique UNIQUE (author_id, book_id))");
|
||||
Database.execSQL(
|
||||
"CREATE TABLE Series(" +
|
||||
"series_id INTEGER PRIMARY KEY," +
|
||||
"name TEXT UNIQUE NOT NULL)");
|
||||
Database.execSQL(
|
||||
"CREATE TABLE BookSeries(" +
|
||||
"series_id INTEGER NOT NULL REFERENCES Series(series_id)," +
|
||||
"book_id INTEGER NOT NULL REFERENCES Books(book_id)," +
|
||||
"number_in_series INTEGER," +
|
||||
"CONSTRAINT BookSeries_Unique UNIQUE (series_id, book_id))");
|
||||
Database.execSQL(
|
||||
"CREATE TABLE Tags(" +
|
||||
"tag_id INTEGER PRIMARY KEY," +
|
||||
"name TEXT NOT NULL," +
|
||||
"parent INTEGER REFERENCES Tags(tag_id)," +
|
||||
"CONSTRAINT Tags_Unique UNIQUE (name, parent))");
|
||||
Database.execSQL(
|
||||
"CREATE TABLE BookTag(" +
|
||||
"tag_id INTEGER REFERENCES Tags(tag_id)," +
|
||||
"book_id INTEGER REFERENCES Books(book_id)," +
|
||||
"CONSTRAINT BookTag_Unique UNIQUE (tag_id, book_id))");
|
||||
Database.setTransactionSuccessful();
|
||||
Database.endTransaction();
|
||||
|
||||
Database.setVersion(1);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@
|
|||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package org.geometerplus.fbreader.description;
|
||||
package org.geometerplus.fbreader.collection;
|
||||
|
||||
import java.util.*;
|
||||
import org.geometerplus.zlibrary.core.util.*;
|
||||
|
@ -26,15 +26,12 @@ public final class Author {
|
|||
public final String DisplayName;
|
||||
public final String SortKey;
|
||||
|
||||
Author(String displayName, String sortKey) {
|
||||
public Author(String displayName, String sortKey) {
|
||||
DisplayName = displayName;
|
||||
SortKey = sortKey;
|
||||
}
|
||||
|
||||
Author() {
|
||||
this("Unknown Author", "___");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == this) {
|
||||
return true;
|
||||
|
@ -46,6 +43,7 @@ public final class Author {
|
|||
return SortKey.equals(a.SortKey) && DisplayName.equals(a.DisplayName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return SortKey.hashCode() + DisplayName.hashCode();
|
||||
}
|
|
@ -19,8 +19,6 @@
|
|||
|
||||
package org.geometerplus.fbreader.collection;
|
||||
|
||||
import org.geometerplus.fbreader.description.Author;
|
||||
|
||||
public class AuthorTree extends CollectionTree {
|
||||
private final Author myAuthor;
|
||||
|
||||
|
@ -36,10 +34,11 @@ public class AuthorTree extends CollectionTree {
|
|||
}
|
||||
|
||||
public String getName() {
|
||||
return myAuthor.DisplayName;
|
||||
// TODO: use resources
|
||||
return (myAuthor != null) ? myAuthor.DisplayName : "Unknown Author";
|
||||
}
|
||||
|
||||
protected String getSortKey() {
|
||||
return myAuthor.SortKey;
|
||||
return (myAuthor != null) ? myAuthor.SortKey : null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,10 +22,8 @@ package org.geometerplus.fbreader.collection;
|
|||
import java.util.*;
|
||||
import org.geometerplus.zlibrary.core.util.*;
|
||||
|
||||
import org.geometerplus.zlibrary.core.config.ZLConfig;
|
||||
import org.geometerplus.zlibrary.core.filesystem.*;
|
||||
|
||||
import org.geometerplus.fbreader.description.*;
|
||||
import org.geometerplus.fbreader.formats.PluginCollection;
|
||||
|
||||
public class BookCollection {
|
||||
|
@ -115,51 +113,63 @@ public class BookCollection {
|
|||
}
|
||||
}
|
||||
|
||||
private static final ArrayList ourNullList = new ArrayList(1);
|
||||
static {
|
||||
ourNullList.add(null);
|
||||
}
|
||||
|
||||
private TagTree getTagTree(Tag tag, HashMap<Tag,TagTree> tagTreeMap) {
|
||||
TagTree tagTree = tagTreeMap.get(tag);
|
||||
if (tagTree == null) {
|
||||
CollectionTree parent =
|
||||
((tag != null) && (tag.Parent != null)) ?
|
||||
getTagTree(tag.Parent, tagTreeMap) : myCollectionByTag;
|
||||
tagTree = parent.createTagSubTree(tag);
|
||||
tagTreeMap.put(tag, tagTree);
|
||||
}
|
||||
return tagTree;
|
||||
}
|
||||
|
||||
private void build() {
|
||||
final HashSet fileNamesSet = collectBookFileNames();
|
||||
final HashMap<String,TagTree> tagTreeMap = new HashMap<String,TagTree>();
|
||||
final HashMap<Tag,TagTree> tagTreeMap = new HashMap<Tag,TagTree>();
|
||||
final HashMap<Author,AuthorTree> authorTreeMap = new HashMap<Author,AuthorTree>();
|
||||
final HashMap<AuthorSeriesPair,SeriesTree> seriesTreeMap = new HashMap<AuthorSeriesPair,SeriesTree>();
|
||||
|
||||
for (Iterator it = fileNamesSet.iterator(); it.hasNext(); ) {
|
||||
final BookDescription description = BookDescription.getDescription((String)it.next());
|
||||
|
||||
final Author author = description.getAuthor();
|
||||
final String series = description.getSeriesName();
|
||||
AuthorTree authorTree = authorTreeMap.get(author);
|
||||
if (authorTree == null) {
|
||||
authorTree = myCollectionByAuthor.createAuthorSubTree(author);
|
||||
authorTreeMap.put(author, authorTree);
|
||||
List<Author> authors = description.authors();
|
||||
if (authors.isEmpty()) {
|
||||
authors = (List<Author>)ourNullList;
|
||||
}
|
||||
if (series.length() == 0) {
|
||||
authorTree.createBookSubTree(description);
|
||||
} else {
|
||||
final AuthorSeriesPair pair = new AuthorSeriesPair(author, series);
|
||||
SeriesTree seriesTree = seriesTreeMap.get(pair);
|
||||
if (seriesTree == null) {
|
||||
seriesTree = authorTree.createSeriesSubTree(series);
|
||||
seriesTreeMap.put(pair, seriesTree);
|
||||
final SeriesInfo seriesInfo = description.getSeriesInfo();
|
||||
for (Author a : authors) {
|
||||
AuthorTree authorTree = authorTreeMap.get(a);
|
||||
if (authorTree == null) {
|
||||
authorTree = myCollectionByAuthor.createAuthorSubTree(a);
|
||||
authorTreeMap.put(a, authorTree);
|
||||
}
|
||||
if (seriesInfo == null) {
|
||||
authorTree.createBookSubTree(description);
|
||||
} else {
|
||||
final String series = seriesInfo.Name;
|
||||
final AuthorSeriesPair pair = new AuthorSeriesPair(a, series);
|
||||
SeriesTree seriesTree = seriesTreeMap.get(pair);
|
||||
if (seriesTree == null) {
|
||||
seriesTree = authorTree.createSeriesSubTree(series);
|
||||
seriesTreeMap.put(pair, seriesTree);
|
||||
}
|
||||
seriesTree.createBookInSeriesSubTree(description);
|
||||
}
|
||||
seriesTree.createBookInSeriesSubTree(description);
|
||||
}
|
||||
|
||||
final List<String> tags = description.getTags();
|
||||
if (!tags.isEmpty()) {
|
||||
for (String tag : description.getTags()) {
|
||||
TagTree tagTree = tagTreeMap.get(tag);
|
||||
if (tagTree == null) {
|
||||
tagTree = myCollectionByTag.createTagSubTree(tag);
|
||||
tagTreeMap.put(tag, tagTree);
|
||||
}
|
||||
tagTree.createBookSubTree(description);
|
||||
}
|
||||
} else {
|
||||
TagTree tagTree = tagTreeMap.get(null);
|
||||
if (tagTree == null) {
|
||||
tagTree = myCollectionByTag.createTagSubTree(null);
|
||||
tagTreeMap.put(null, tagTree);
|
||||
}
|
||||
tagTree.createBookSubTree(description);
|
||||
List<Tag> tags = description.tags();
|
||||
if (tags.isEmpty()) {
|
||||
tags = (List<Tag>)ourNullList;
|
||||
}
|
||||
for (Tag t : tags) {
|
||||
getTagTree(t, tagTreeMap).createBookSubTree(description);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -169,7 +179,7 @@ public class BookCollection {
|
|||
myCollectionByAuthor.clear();
|
||||
myCollectionByTag.clear();
|
||||
|
||||
ZLConfig.Instance().executeAsATransaction(new Runnable() {
|
||||
BooksDatabase.Instance().executeAsATransaction(new Runnable() {
|
||||
public void run() {
|
||||
build();
|
||||
}
|
||||
|
|
257
src/org/geometerplus/fbreader/collection/BookDescription.java
Normal file
257
src/org/geometerplus/fbreader/collection/BookDescription.java
Normal file
|
@ -0,0 +1,257 @@
|
|||
/*
|
||||
* Copyright (C) 2007-2009 Geometer Plus <contact@geometerplus.com>
|
||||
*
|
||||
* This program 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package org.geometerplus.fbreader.collection;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.geometerplus.zlibrary.core.filesystem.ZLFile;
|
||||
|
||||
import org.geometerplus.fbreader.formats.*;
|
||||
|
||||
public class BookDescription {
|
||||
public final String FileName;
|
||||
|
||||
private long myBookId;
|
||||
|
||||
private String myEncoding;
|
||||
private String myLanguage;
|
||||
private String myTitle;
|
||||
private ArrayList<Author> myAuthors;
|
||||
private ArrayList<Tag> myTags;
|
||||
private SeriesInfo mySeriesInfo;
|
||||
|
||||
private boolean myIsSaved;
|
||||
private boolean myIsChanged;
|
||||
|
||||
private final static HashMap<String,BookDescription> ourDescriptions = new HashMap<String,BookDescription>();
|
||||
|
||||
public static BookDescription getDescription(String fileName) {
|
||||
return getDescription(fileName, true);
|
||||
}
|
||||
|
||||
public static BookDescription getDescription(String fileName, boolean checkFile) {
|
||||
if (fileName == null) {
|
||||
return null;
|
||||
}
|
||||
String physicalFileName = new ZLFile(fileName).getPhysicalFilePath();
|
||||
ZLFile file = new ZLFile(physicalFileName);
|
||||
if (checkFile && !file.exists()) {
|
||||
return null;
|
||||
}
|
||||
BookDescription description = ourDescriptions.get(fileName);
|
||||
if (description == null) {
|
||||
description = new BookDescription(fileName);
|
||||
ourDescriptions.put(fileName, description);
|
||||
}
|
||||
if ((!checkFile || BookDescriptionUtil.checkInfo(file)) && description.isSaved()) {
|
||||
return description;
|
||||
}
|
||||
|
||||
if (physicalFileName != fileName) {
|
||||
BookDescriptionUtil.resetZipInfo(file);
|
||||
}
|
||||
BookDescriptionUtil.saveInfo(file);
|
||||
|
||||
ZLFile bookFile = new ZLFile(fileName);
|
||||
|
||||
FormatPlugin plugin = PluginCollection.instance().getPlugin(bookFile, false);
|
||||
if ((plugin == null) || !plugin.readDescription(fileName, description)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String title = description.getTitle();
|
||||
if ((title == null) || (title.length() == 0)) {
|
||||
description.setTitle(bookFile.getName(true));
|
||||
}
|
||||
description.save();
|
||||
return description;
|
||||
}
|
||||
|
||||
private BookDescription(String fileName) {
|
||||
FileName = fileName;
|
||||
final BooksDatabase database = BooksDatabase.Instance();
|
||||
myBookId = database.loadBook(this);
|
||||
if (myBookId >= 0) {
|
||||
myAuthors = database.loadAuthors(myBookId);
|
||||
myTags = database.loadTags(myBookId);
|
||||
mySeriesInfo = database.loadSeriesInfo(myBookId);
|
||||
myIsSaved = true;
|
||||
myIsChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSaved() {
|
||||
return myIsSaved;
|
||||
}
|
||||
|
||||
public List<Author> authors() {
|
||||
return (myAuthors != null) ? Collections.unmodifiableList(myAuthors) : Collections.<Author>emptyList();
|
||||
}
|
||||
|
||||
private void addAuthor(Author author) {
|
||||
if (author == null) {
|
||||
return;
|
||||
}
|
||||
if (myAuthors == null) {
|
||||
myAuthors = new ArrayList<Author>();
|
||||
myAuthors.add(author);
|
||||
myIsChanged = true;
|
||||
} else {
|
||||
if (!myAuthors.contains(author)) {
|
||||
myAuthors.add(author);
|
||||
myIsChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addAuthor(String name) {
|
||||
addAuthor(name, "");
|
||||
}
|
||||
|
||||
public void addAuthor(String name, String sortKey) {
|
||||
String strippedName = name;
|
||||
strippedName.trim();
|
||||
if (strippedName.length() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
String strippedKey = sortKey;
|
||||
strippedKey.trim();
|
||||
if (strippedKey.length() == 0) {
|
||||
int index = strippedName.lastIndexOf(' ');
|
||||
if (index == -1) {
|
||||
strippedKey = strippedName;
|
||||
} else {
|
||||
strippedKey = strippedName.substring(index + 1);
|
||||
while ((index >= 0) && (strippedName.charAt(index) == ' ')) {
|
||||
--index;
|
||||
}
|
||||
strippedName = strippedName.substring(0, index + 1) + ' ' + strippedKey;
|
||||
}
|
||||
}
|
||||
|
||||
addAuthor(new Author(strippedName, strippedKey));
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return myTitle;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
if (!equals(myTitle, title)) {
|
||||
myTitle = title;
|
||||
myIsChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
public SeriesInfo getSeriesInfo() {
|
||||
return mySeriesInfo;
|
||||
}
|
||||
|
||||
public void setSeriesInfo(String name, long index) {
|
||||
if (mySeriesInfo == null) {
|
||||
if (name != null) {
|
||||
mySeriesInfo = new SeriesInfo(name, index);
|
||||
}
|
||||
} else if (name == null) {
|
||||
mySeriesInfo = null;
|
||||
} else if (!mySeriesInfo.Name.equals(name) || (mySeriesInfo.Index != index)) {
|
||||
mySeriesInfo = new SeriesInfo(name, index);
|
||||
}
|
||||
}
|
||||
|
||||
public String getLanguage() {
|
||||
return myLanguage;
|
||||
}
|
||||
|
||||
public void setLanguage(String language) {
|
||||
if (!equals(myLanguage, language)) {
|
||||
myLanguage = language;
|
||||
myIsChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
public String getEncoding() {
|
||||
return myEncoding;
|
||||
}
|
||||
|
||||
public void setEncoding(String encoding) {
|
||||
if (!equals(myEncoding, encoding)) {
|
||||
myEncoding = encoding;
|
||||
myIsChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
public List<Tag> tags() {
|
||||
return (myTags != null) ? Collections.unmodifiableList(myTags) : Collections.<Tag>emptyList();
|
||||
}
|
||||
|
||||
public void addTag(Tag tag) {
|
||||
if (tag != null) {
|
||||
if (myTags == null) {
|
||||
myTags = new ArrayList<Tag>();
|
||||
}
|
||||
if (!myTags.contains(tag)) {
|
||||
myTags.add(tag);
|
||||
myIsChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addTag(String tagName) {
|
||||
addTag(Tag.getTag(null, tagName));
|
||||
}
|
||||
|
||||
private void save() {
|
||||
if (!myIsChanged) {
|
||||
return;
|
||||
}
|
||||
final BooksDatabase database = BooksDatabase.Instance();
|
||||
database.executeAsATransaction(new Runnable() {
|
||||
public void run() {
|
||||
if (myBookId >= 0) {
|
||||
database.updateBookInfo(myBookId, myEncoding, myLanguage, myTitle);
|
||||
} else {
|
||||
myBookId = database.insertBookInfo(FileName, myEncoding, myLanguage, myTitle);
|
||||
}
|
||||
|
||||
long index = 0;
|
||||
for (Author author : authors()) {
|
||||
database.saveBookAuthorInfo(myBookId, index++, author);
|
||||
}
|
||||
for (Tag tag : tags()) {
|
||||
database.saveBookTagInfo(myBookId, tag);
|
||||
}
|
||||
database.saveBookSeriesInfo(myBookId, mySeriesInfo);
|
||||
}
|
||||
});
|
||||
|
||||
myIsChanged = false;
|
||||
myIsSaved = true;
|
||||
}
|
||||
|
||||
private static boolean equals(Object o0, Object o1) {
|
||||
if (o0 == null) {
|
||||
return o1 == null;
|
||||
}
|
||||
return o0.equals(o1);
|
||||
}
|
||||
|
||||
}
|
|
@ -17,18 +17,18 @@
|
|||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package org.geometerplus.fbreader.description;
|
||||
package org.geometerplus.fbreader.collection;
|
||||
|
||||
import java.util.*;
|
||||
import org.geometerplus.zlibrary.core.util.*;
|
||||
|
||||
import org.geometerplus.fbreader.description.BookDescription.BookInfo;
|
||||
import org.geometerplus.fbreader.formats.PluginCollection;
|
||||
import org.geometerplus.zlibrary.core.filesystem.ZLDir;
|
||||
import org.geometerplus.zlibrary.core.filesystem.ZLFile;
|
||||
import org.geometerplus.zlibrary.core.options.ZLIntegerOption;
|
||||
import org.geometerplus.zlibrary.core.options.ZLStringOption;
|
||||
|
||||
import org.geometerplus.fbreader.formats.PluginCollection;
|
||||
|
||||
public class BookDescriptionUtil {
|
||||
private static final String SIZE = "Size";
|
||||
private static final String ENTRY = "Entry";
|
||||
|
@ -37,7 +37,6 @@ public class BookDescriptionUtil {
|
|||
public static boolean checkInfo(ZLFile file) {
|
||||
ZLIntegerOption op = new ZLIntegerOption(file.getPath(), SIZE, -1);
|
||||
return op.getValue() == (int)file.size();
|
||||
|
||||
}
|
||||
|
||||
public static void saveInfo(ZLFile file) {
|
||||
|
@ -47,7 +46,6 @@ public class BookDescriptionUtil {
|
|||
public static void listZipEntries(ZLFile zipFile, ArrayList entries) {
|
||||
int entriesNumber = new ZLIntegerOption(zipFile.getPath(), ENTRIES_NUMBER, -1).getValue();
|
||||
if (entriesNumber == -1) {
|
||||
//??? why so??resetZipInfo(zipFile.path());
|
||||
resetZipInfo(zipFile);
|
||||
entriesNumber = new ZLIntegerOption(zipFile.getPath(), ENTRIES_NUMBER, -1).getValue();
|
||||
}
|
||||
|
@ -60,7 +58,6 @@ public class BookDescriptionUtil {
|
|||
entries.add(entry);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void resetZipInfo(ZLFile zipFile) {
|
||||
|
@ -80,36 +77,11 @@ public class BookDescriptionUtil {
|
|||
final String fullName = zipPrefix + entry;
|
||||
entryOption.changeName(ENTRY + counter);
|
||||
entryOption.setValue(fullName);
|
||||
new BookInfo(fullName).reset();
|
||||
BooksDatabase.Instance().resetBookInfo(fullName);
|
||||
++counter;
|
||||
}
|
||||
}
|
||||
new ZLIntegerOption(zipFile.getPath(), ENTRIES_NUMBER, -1).setValue(counter);
|
||||
}
|
||||
}
|
||||
|
||||
public static String removeWhiteSpacesFromTag(String tag) {
|
||||
int index = tag.indexOf('/');
|
||||
if (index == -1) {
|
||||
return tag.trim();
|
||||
} else {
|
||||
final StringBuilder result = new StringBuilder();
|
||||
int index0 = 0;
|
||||
while (true) {
|
||||
String subtag = (index == -1) ? tag.substring(index0).trim() : tag.substring(index0, index).trim();
|
||||
if (subtag.length() > 0) {
|
||||
if (result.length() > 0) {
|
||||
result.append("/");
|
||||
}
|
||||
result.append(subtag);
|
||||
}
|
||||
if (index == -1) {
|
||||
break;
|
||||
}
|
||||
index0 = index + 1;
|
||||
index = tag.indexOf('/', index0);
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,8 +19,6 @@
|
|||
|
||||
package org.geometerplus.fbreader.collection;
|
||||
|
||||
import org.geometerplus.fbreader.description.BookDescription;
|
||||
|
||||
public final class BookInSeriesTree extends BookTree {
|
||||
BookInSeriesTree(CollectionTree parent, BookDescription description) {
|
||||
super(parent, description);
|
||||
|
@ -29,9 +27,10 @@ public final class BookInSeriesTree extends BookTree {
|
|||
@Override
|
||||
public int compareTo(CollectionTree tree) {
|
||||
if (tree instanceof BookInSeriesTree) {
|
||||
final int difference = Description.getNumberInSeries() - ((BookTree)tree).Description.getNumberInSeries();
|
||||
final long difference =
|
||||
Description.getSeriesInfo().Index - ((BookTree)tree).Description.getSeriesInfo().Index;
|
||||
if (difference != 0) {
|
||||
return difference;
|
||||
return (int)difference;
|
||||
}
|
||||
}
|
||||
return super.compareTo(tree);
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
|
||||
package org.geometerplus.fbreader.collection;
|
||||
|
||||
import org.geometerplus.fbreader.description.BookDescription;
|
||||
|
||||
public class BookTree extends CollectionTree {
|
||||
public final BookDescription Description;
|
||||
|
||||
|
|
46
src/org/geometerplus/fbreader/collection/BooksDatabase.java
Normal file
46
src/org/geometerplus/fbreader/collection/BooksDatabase.java
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Geometer Plus <contact@geometerplus.com>
|
||||
*
|
||||
* This program 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package org.geometerplus.fbreader.collection;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public abstract class BooksDatabase {
|
||||
private static BooksDatabase ourInstance;
|
||||
|
||||
static BooksDatabase Instance() {
|
||||
return ourInstance;
|
||||
}
|
||||
|
||||
protected BooksDatabase() {
|
||||
ourInstance = this;
|
||||
}
|
||||
|
||||
public abstract void executeAsATransaction(Runnable actions);
|
||||
public abstract long loadBook(BookDescription description);
|
||||
public abstract ArrayList<Author> loadAuthors(long bookId);
|
||||
public abstract ArrayList<Tag> loadTags(long bookId);
|
||||
public abstract SeriesInfo loadSeriesInfo(long bookId);
|
||||
public abstract void updateBookInfo(long bookId, String encoding, String language, String title);
|
||||
public abstract long insertBookInfo(String fileName, String encoding, String language, String title);
|
||||
public abstract void saveBookAuthorInfo(long bookId, long index, Author author);
|
||||
public abstract void saveBookTagInfo(long bookId, Tag tag);
|
||||
public abstract void saveBookSeriesInfo(long bookId, SeriesInfo seriesInfo);
|
||||
public abstract void resetBookInfo(String fileName);
|
||||
}
|
|
@ -23,8 +23,6 @@ import java.util.Collections;
|
|||
import java.util.ArrayList;
|
||||
|
||||
import org.geometerplus.zlibrary.core.tree.ZLTree;
|
||||
import org.geometerplus.fbreader.description.BookDescription;
|
||||
import org.geometerplus.fbreader.description.Author;
|
||||
|
||||
public abstract class CollectionTree extends ZLTree<CollectionTree> implements Comparable<CollectionTree> {
|
||||
protected CollectionTree() {
|
||||
|
@ -35,7 +33,7 @@ public abstract class CollectionTree extends ZLTree<CollectionTree> implements C
|
|||
super(parent);
|
||||
}
|
||||
|
||||
TagTree createTagSubTree(String tag) {
|
||||
TagTree createTagSubTree(Tag tag) {
|
||||
TagTree tree = new TagTree(this, tag);
|
||||
addSubTree(tree);
|
||||
return tree;
|
||||
|
|
|
@ -25,7 +25,6 @@ import org.geometerplus.zlibrary.core.util.*;
|
|||
import org.geometerplus.zlibrary.core.config.ZLConfig;
|
||||
import org.geometerplus.zlibrary.core.options.ZLStringOption;
|
||||
|
||||
import org.geometerplus.fbreader.description.*;
|
||||
import org.geometerplus.fbreader.formats.PluginCollection;
|
||||
|
||||
public final class RecentBooks {
|
||||
|
|
|
@ -17,32 +17,14 @@
|
|||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package org.geometerplus.zlibrary.core.tree;
|
||||
package org.geometerplus.fbreader.collection;
|
||||
|
||||
import java.util.ArrayList;
|
||||
public final class SeriesInfo {
|
||||
public final String Name;
|
||||
public final long Index;
|
||||
|
||||
public class ZLStringTree extends ZLTree<ZLStringTree> {
|
||||
private String myText;
|
||||
|
||||
protected ZLStringTree() {
|
||||
super();
|
||||
}
|
||||
|
||||
private ZLStringTree(ZLStringTree parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
public final String getText() {
|
||||
return myText;
|
||||
}
|
||||
|
||||
public final void setText(String text) {
|
||||
myText = text;
|
||||
}
|
||||
|
||||
public final ZLStringTree createSubTree() {
|
||||
ZLStringTree subtree = new ZLStringTree(this);
|
||||
addSubTree(subtree);
|
||||
return subtree;
|
||||
public SeriesInfo(String name, long index) {
|
||||
Name = name;
|
||||
Index = index;
|
||||
}
|
||||
}
|
|
@ -19,8 +19,6 @@
|
|||
|
||||
package org.geometerplus.fbreader.collection;
|
||||
|
||||
import org.geometerplus.fbreader.description.BookDescription;
|
||||
|
||||
final class SeriesTree extends CollectionTree {
|
||||
private final String mySeries;
|
||||
|
||||
|
|
65
src/org/geometerplus/fbreader/collection/Tag.java
Normal file
65
src/org/geometerplus/fbreader/collection/Tag.java
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Geometer Plus <contact@geometerplus.com>
|
||||
*
|
||||
* This program 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package org.geometerplus.fbreader.collection;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public final class Tag {
|
||||
private static final HashMap<Tag,Tag> ourTagSet = new HashMap<Tag,Tag>();
|
||||
|
||||
public static Tag getTag(Tag parent, String name) {
|
||||
if (name == null) {
|
||||
return parent;
|
||||
}
|
||||
name = name.trim();
|
||||
if (name.length() == 0) {
|
||||
return parent;
|
||||
}
|
||||
Tag tag = new Tag(parent, name);
|
||||
Tag stored = ourTagSet.get(tag);
|
||||
if (stored != null) {
|
||||
return stored;
|
||||
}
|
||||
ourTagSet.put(tag, tag);
|
||||
return tag;
|
||||
}
|
||||
|
||||
public final Tag Parent;
|
||||
public final String Name;
|
||||
|
||||
private Tag(Tag parent, String name) {
|
||||
Parent = parent;
|
||||
Name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof Tag)) {
|
||||
return false;
|
||||
}
|
||||
Tag t = (Tag)o;
|
||||
return (Parent == t.Parent) && Name.equals(t.Name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (Parent == null) ? Name.hashCode() : Parent.hashCode() + Name.hashCode();
|
||||
}
|
||||
}
|
|
@ -20,19 +20,19 @@
|
|||
package org.geometerplus.fbreader.collection;
|
||||
|
||||
final class TagTree extends CollectionTree {
|
||||
private final String myTag;
|
||||
private final Tag myTag;
|
||||
|
||||
TagTree(CollectionTree parent, String tag) {
|
||||
TagTree(CollectionTree parent, Tag tag) {
|
||||
super(parent);
|
||||
myTag = tag;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
// TODO: use resources
|
||||
return (myTag != null) ? myTag : "Books with no tags";
|
||||
return (myTag != null) ? myTag.Name : "Books with no tags";
|
||||
}
|
||||
|
||||
protected String getSortKey() {
|
||||
return myTag;
|
||||
return (myTag != null) ? myTag.Name : null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,423 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2007-2009 Geometer Plus <contact@geometerplus.com>
|
||||
*
|
||||
* This program 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package org.geometerplus.fbreader.description;
|
||||
|
||||
import java.util.*;
|
||||
import org.geometerplus.zlibrary.core.util.*;
|
||||
|
||||
import org.geometerplus.zlibrary.core.filesystem.ZLFile;
|
||||
import org.geometerplus.zlibrary.core.options.*;
|
||||
|
||||
import org.geometerplus.fbreader.formats.*;
|
||||
|
||||
public class BookDescription {
|
||||
private static final String EMPTY = "";
|
||||
private static final String UNKNOWN = "unknown";
|
||||
|
||||
public final String FileName;
|
||||
|
||||
//private final TreeSet<Author> myAuthors = new TreeSet<Author>();
|
||||
private Author myAuthor;
|
||||
private String myTitle = "";
|
||||
private String mySeriesName = "";
|
||||
private int myNumberInSeries = 0;
|
||||
private String myLanguage = "";
|
||||
private String myEncoding = "";
|
||||
private final static HashMap ourDescriptions = new HashMap();
|
||||
private final ArrayList<String> myTags = new ArrayList<String>();
|
||||
|
||||
public static BookDescription getDescription(String fileName) {
|
||||
return getDescription(fileName, true);
|
||||
}
|
||||
|
||||
public static BookDescription getDescription(String fileName, boolean checkFile) {
|
||||
if (fileName == null) {
|
||||
return null;
|
||||
}
|
||||
String physicalFileName = new ZLFile(fileName).getPhysicalFilePath();
|
||||
ZLFile file = new ZLFile(physicalFileName);
|
||||
if (checkFile && !file.exists()) {
|
||||
return null;
|
||||
}
|
||||
BookDescription description = (BookDescription)ourDescriptions.get(fileName);
|
||||
if (description == null) {
|
||||
description = new BookDescription(fileName);
|
||||
ourDescriptions.put(fileName, description);
|
||||
}
|
||||
if (!checkFile || BookDescriptionUtil.checkInfo(file)) {
|
||||
//if (false) {
|
||||
BookInfo info = new BookInfo(fileName);
|
||||
description.myAuthor = new Author(info.AuthorDisplayNameOption.getValue(), info.AuthorSortKeyOption.getValue());
|
||||
description.myTitle = info.TitleOption.getValue();
|
||||
description.mySeriesName = info.SeriesNameOption.getValue();
|
||||
description.myNumberInSeries = info.NumberInSeriesOption.getValue();
|
||||
description.myLanguage = info.LanguageOption.getValue();
|
||||
description.myEncoding = info.EncodingOption.getValue();
|
||||
description.myTags.clear();
|
||||
final String tagList = info.TagsOption.getValue();
|
||||
if (tagList.length() > 0) {
|
||||
int index = 0;
|
||||
do {
|
||||
final int newIndex = tagList.indexOf(',', index);
|
||||
final String tagName = (newIndex == -1) ? tagList.substring(index) : tagList.substring(index, newIndex);
|
||||
description.addTag(tagName, true);
|
||||
index = newIndex + 1;
|
||||
} while (index != 0);
|
||||
}
|
||||
|
||||
if (info.isFull()) {
|
||||
return description;
|
||||
}
|
||||
} else {
|
||||
if (physicalFileName != fileName) {
|
||||
BookDescriptionUtil.resetZipInfo(file);
|
||||
}
|
||||
BookDescriptionUtil.saveInfo(file);
|
||||
}
|
||||
ZLFile bookFile = new ZLFile(fileName);
|
||||
|
||||
FormatPlugin plugin = PluginCollection.instance().getPlugin(bookFile, false);
|
||||
if ((plugin == null) || !plugin.readDescription(fileName, description)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (description.myTitle.length() == 0) {
|
||||
description.myTitle = bookFile.getName(true);
|
||||
}
|
||||
Author author = description.myAuthor;
|
||||
if (author == null || author.DisplayName.length() == 0) {
|
||||
description.myAuthor = new Author();
|
||||
}
|
||||
if (description.myEncoding.length() == 0) {
|
||||
description.myEncoding = "auto";
|
||||
}
|
||||
{
|
||||
BookInfo info = new BookInfo(fileName);
|
||||
info.AuthorDisplayNameOption.setValue(description.myAuthor.DisplayName);
|
||||
info.AuthorSortKeyOption.setValue(description.myAuthor.SortKey);
|
||||
info.TitleOption.setValue(description.myTitle);
|
||||
info.SeriesNameOption.setValue(description.mySeriesName);
|
||||
info.NumberInSeriesOption.setValue(description.myNumberInSeries);
|
||||
info.LanguageOption.setValue(description.myLanguage);
|
||||
info.EncodingOption.setValue(description.myEncoding);
|
||||
}
|
||||
return description;
|
||||
}
|
||||
|
||||
private BookDescription(String fileName) {
|
||||
FileName = fileName;
|
||||
myAuthor = null;
|
||||
myNumberInSeries = 0;
|
||||
}
|
||||
|
||||
public Author getAuthor() {
|
||||
return myAuthor;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return myTitle;
|
||||
}
|
||||
|
||||
public String getSeriesName() {
|
||||
return mySeriesName;
|
||||
}
|
||||
|
||||
public int getNumberInSeries() {
|
||||
return myNumberInSeries;
|
||||
}
|
||||
|
||||
public String getLanguage() {
|
||||
return myLanguage;
|
||||
}
|
||||
|
||||
public String getEncoding() {
|
||||
return myEncoding;
|
||||
}
|
||||
|
||||
public List<String> getTags() {
|
||||
return Collections.unmodifiableList(myTags);
|
||||
}
|
||||
|
||||
private boolean addTag(String tag, boolean check) {
|
||||
if (check) {
|
||||
tag = BookDescriptionUtil.removeWhiteSpacesFromTag(tag);
|
||||
}
|
||||
|
||||
if ((tag.length() > 0) && !myTags.contains(tag)) {
|
||||
myTags.add(tag);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void saveTags() {
|
||||
saveTags(new ZLStringOption(FileName, "TagList", EMPTY));
|
||||
}
|
||||
|
||||
private void saveTags(ZLStringOption tagsOption) {
|
||||
final ArrayList<String> tags = myTags;
|
||||
if (tags.isEmpty()) {
|
||||
tagsOption.setValue("");
|
||||
} else {
|
||||
final StringBuilder tagString = new StringBuilder();
|
||||
tagString.append(tags.get(0));
|
||||
final int len = tags.size();
|
||||
for (int i = 1; i < len; ++i) {
|
||||
tagString.append(",");
|
||||
tagString.append(tags.get(i));
|
||||
}
|
||||
tagsOption.setValue(tagString.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public static class BookInfo {
|
||||
public final ZLStringOption AuthorDisplayNameOption;
|
||||
public final ZLStringOption AuthorSortKeyOption;
|
||||
public final ZLStringOption TitleOption;
|
||||
public final ZLStringOption SeriesNameOption;
|
||||
public final ZLIntegerRangeOption NumberInSeriesOption;
|
||||
public final ZLStringOption LanguageOption;
|
||||
public final ZLStringOption EncodingOption;
|
||||
public final ZLStringOption TagsOption;
|
||||
|
||||
public BookInfo(String fileName) {
|
||||
AuthorDisplayNameOption = new ZLStringOption(fileName, "AuthorDisplayName", EMPTY);
|
||||
AuthorSortKeyOption = new ZLStringOption(fileName, "AuthorSortKey", EMPTY);
|
||||
TitleOption = new ZLStringOption(fileName, "Title", EMPTY);
|
||||
SeriesNameOption = new ZLStringOption(fileName, "Sequence", EMPTY);
|
||||
NumberInSeriesOption = new ZLIntegerRangeOption(fileName, "Number in seq", 0, 100, 0);
|
||||
LanguageOption = new ZLStringOption(fileName, "Language", UNKNOWN);
|
||||
EncodingOption = new ZLStringOption(fileName, "Encoding", EMPTY);
|
||||
TagsOption = new ZLStringOption(fileName, "TagList", EMPTY);
|
||||
}
|
||||
|
||||
public boolean isFull() {
|
||||
return
|
||||
(AuthorDisplayNameOption.getValue().length() != 0) &&
|
||||
(AuthorSortKeyOption.getValue().length() != 0) &&
|
||||
(TitleOption.getValue().length() != 0) &&
|
||||
(EncodingOption.getValue().length() != 0);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
AuthorDisplayNameOption.setValue(EMPTY);
|
||||
AuthorSortKeyOption.setValue(EMPTY);
|
||||
TitleOption.setValue(EMPTY);
|
||||
SeriesNameOption.setValue(EMPTY);
|
||||
NumberInSeriesOption.setValue(0);
|
||||
LanguageOption.setValue(UNKNOWN);
|
||||
EncodingOption.setValue(EMPTY);
|
||||
TagsOption.setValue(EMPTY);
|
||||
}
|
||||
}
|
||||
|
||||
static public class WritableBookDescription {
|
||||
private final BookDescription myDescription;
|
||||
|
||||
public WritableBookDescription(BookDescription description) {
|
||||
myDescription = description;
|
||||
}
|
||||
|
||||
public void addAuthor(String name) {
|
||||
addAuthor(name, "");
|
||||
}
|
||||
|
||||
public void addAuthor(String name, String sortKey) {
|
||||
String strippedName = name;
|
||||
strippedName.trim();
|
||||
if (strippedName.length() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
String strippedKey = sortKey;
|
||||
strippedKey.trim();
|
||||
if (strippedKey.length() == 0) {
|
||||
int index = strippedName.lastIndexOf(' ');
|
||||
if (index == -1) {
|
||||
strippedKey = strippedName;
|
||||
} else {
|
||||
strippedKey = strippedName.substring(index + 1);
|
||||
while ((index >= 0) && (strippedName.charAt(index) == ' ')) {
|
||||
--index;
|
||||
}
|
||||
strippedName = strippedName.substring(0, index + 1) + ' ' + strippedKey;
|
||||
}
|
||||
}
|
||||
Author author = new Author(strippedName, strippedKey);
|
||||
|
||||
if (myDescription.myAuthor == null) {
|
||||
myDescription.myAuthor = author;
|
||||
} else {
|
||||
// TODO: implement
|
||||
}
|
||||
}
|
||||
|
||||
public void clearAuthor() {
|
||||
myDescription.myAuthor = null;
|
||||
}
|
||||
|
||||
public Author getAuthor() {
|
||||
return myDescription.getAuthor();
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return myDescription.myTitle;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
myDescription.myTitle = title;
|
||||
}
|
||||
|
||||
public String getSeriesName() {
|
||||
return myDescription.mySeriesName;
|
||||
}
|
||||
|
||||
public void setSeriesName(String sequenceName) {
|
||||
myDescription.mySeriesName = sequenceName;
|
||||
}
|
||||
|
||||
public int getNumberInSeries() {
|
||||
return myDescription.myNumberInSeries;
|
||||
}
|
||||
|
||||
public void setNumberInSeries(int numberInSeries) {
|
||||
myDescription.myNumberInSeries = numberInSeries;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return myDescription.FileName;
|
||||
}
|
||||
|
||||
public String getLanguage() {
|
||||
return myDescription.myLanguage;
|
||||
}
|
||||
|
||||
public void setLanguage(String language) {
|
||||
myDescription.myLanguage = language;
|
||||
}
|
||||
|
||||
public String getEncoding() {
|
||||
return myDescription.myEncoding;
|
||||
}
|
||||
|
||||
public void setEncoding(String encoding) {
|
||||
myDescription.myEncoding = encoding;
|
||||
}
|
||||
|
||||
public void addTag(String tag, boolean check) {
|
||||
if (myDescription.addTag(tag, check)) {
|
||||
myDescription.saveTags();
|
||||
}
|
||||
}
|
||||
|
||||
public void removeTag(String tag, boolean includeSubTags) {
|
||||
final ArrayList<String> tags = myDescription.myTags;
|
||||
if (includeSubTags) {
|
||||
final String prefix = tag + '/';
|
||||
boolean changed = false;
|
||||
final int len = tags.size();
|
||||
ArrayList toRemove = null;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
String current = tags.get(i);
|
||||
if (current.equals(tag) || current.startsWith(prefix)) {
|
||||
if (toRemove == null) {
|
||||
toRemove = new ArrayList();
|
||||
}
|
||||
toRemove.add(i);
|
||||
}
|
||||
}
|
||||
if (toRemove != null) {
|
||||
for (int i = toRemove.size() - 1; i >= 0; --i) {
|
||||
tags.remove(((Integer)toRemove.get(i)).intValue());
|
||||
}
|
||||
myDescription.saveTags();
|
||||
}
|
||||
} else {
|
||||
if (tags.remove(tag)) {
|
||||
myDescription.saveTags();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void renameTag(String from, String to, boolean includeSubTags) {
|
||||
final ArrayList<String> tags = myDescription.myTags;
|
||||
if (includeSubTags) {
|
||||
final String prefix = from + '/';
|
||||
final HashSet tagSet = new HashSet();
|
||||
boolean changed = false;
|
||||
final int len = tags.size();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
final String value = tags.get(i);
|
||||
if (from.equals(value)) {
|
||||
tagSet.add(to);
|
||||
changed = true;
|
||||
} else if (value.startsWith(prefix)) {
|
||||
tagSet.add(to + '/' + value.substring(prefix.length()));
|
||||
changed = true;
|
||||
} else {
|
||||
tagSet.add(value);
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
tags.clear();
|
||||
tags.addAll(tagSet);
|
||||
myDescription.saveTags();
|
||||
}
|
||||
} else {
|
||||
if (tags.remove(from) && !tags.contains(to)) {
|
||||
tags.add(to);
|
||||
myDescription.saveTags();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void cloneTag(String from, String to, boolean includeSubTags) {
|
||||
final ArrayList<String> tags = myDescription.myTags;
|
||||
if (includeSubTags) {
|
||||
final String prefix = from + '/';
|
||||
final HashSet tagSet = new HashSet();
|
||||
final int len = tags.size();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
final String value = tags.get(i);
|
||||
if (value.equals(from)) {
|
||||
tagSet.add(to);
|
||||
} else if (value.startsWith(prefix)) {
|
||||
tagSet.add(to + '/' + value.substring(prefix.length()));
|
||||
}
|
||||
}
|
||||
if (!tagSet.isEmpty()) {
|
||||
tagSet.addAll(tags);
|
||||
tags.clear();
|
||||
tags.addAll(tagSet);
|
||||
myDescription.saveTags();
|
||||
}
|
||||
} else {
|
||||
if (tags.contains(from) && !tags.contains(to)) {
|
||||
tags.add(to);
|
||||
myDescription.saveTags();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllTags() {
|
||||
myDescription.myTags.clear();
|
||||
}
|
||||
};
|
||||
}
|
|
@ -40,7 +40,6 @@ public interface ActionCode {
|
|||
String DECREASE_FONT = "decreaseFont";
|
||||
String TOGGLE_FULLSCREEN = "toggleFullscreen";
|
||||
String FULLSCREEN_ON = "onFullscreen";
|
||||
String SHOW_BOOK_INFO = "bookInfo";
|
||||
String SHOW_HELP = "showHelp";
|
||||
String ROTATE_SCREEN = "rotate";
|
||||
String QUIT = "quit";
|
||||
|
|
|
@ -1,215 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2007-2009 Geometer Plus <contact@geometerplus.com>
|
||||
*
|
||||
* This program 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package org.geometerplus.fbreader.fbreader;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.geometerplus.zlibrary.core.dialogs.*;
|
||||
import org.geometerplus.zlibrary.core.filesystem.ZLFile;
|
||||
import org.geometerplus.zlibrary.core.language.ZLLanguageList;
|
||||
import org.geometerplus.zlibrary.core.optionEntries.*;
|
||||
|
||||
import org.geometerplus.fbreader.collection.BookCollection;
|
||||
import org.geometerplus.fbreader.description.*;
|
||||
import org.geometerplus.fbreader.formats.*;
|
||||
import org.geometerplus.fbreader.encodingOption.*;
|
||||
import org.geometerplus.fbreader.encodingOption.EncodingEntry;
|
||||
|
||||
public class BookInfoDialog {
|
||||
private final ZLOptionsDialog myDialog;
|
||||
private final BookCollection myCollection;
|
||||
// private final BookDescription.BookInfo myBookInfo;
|
||||
// private FormatInfoPage myFormatInfoPage;
|
||||
|
||||
private AuthorDisplayNameEntry myAuthorDisplayNameEntry;
|
||||
private AuthorSortKeyEntry myAuthorSortKeyEntry;
|
||||
private ZLComboOptionEntry myEncodingSetEntry;
|
||||
private ZLComboOptionEntry myEncodingEntry;
|
||||
private ZLComboOptionEntry myLanguageEntry;
|
||||
private SeriesTitleEntry mySeriesTitleEntry;
|
||||
private ZLSpinOptionEntry myBookNumberEntry;
|
||||
//private FormatInfoPage myFormatInfoPage;
|
||||
|
||||
public BookInfoDialog(String fileName, Runnable actionOnAccept) {
|
||||
myCollection = BookCollection.Instance();
|
||||
//myBookInfo = new BookDescription.BookInfo(fileName);
|
||||
myDialog = ZLDialogManager.getInstance().createOptionsDialog("InfoDialog", actionOnAccept, null, false);
|
||||
|
||||
ZLDialogContent commonTab = myDialog.createTab("Common");
|
||||
commonTab.addOption("file", new ZLStringInfoEntry(new ZLFile(fileName).getPath()));
|
||||
//commonTab.addOption("title", myBookInfo.TitleOption);
|
||||
|
||||
myAuthorDisplayNameEntry = new AuthorDisplayNameEntry();
|
||||
myAuthorSortKeyEntry = new AuthorSortKeyEntry();
|
||||
//myEncodingEntry = new EncodingEntry(myBookInfo.EncodingOption);
|
||||
myEncodingSetEntry =
|
||||
(!"auto".equals(myEncodingEntry.initialValue())) ?
|
||||
new EncodingSetEntry((EncodingEntry)myEncodingEntry) : null;
|
||||
ArrayList/*<std::string>*/ languageCodes = ZLLanguageList.languageCodes();
|
||||
languageCodes.add("de-traditional");
|
||||
//myLanguageEntry = new ZLLanguageOptionEntry(myBookInfo.LanguageOption, languageCodes);
|
||||
|
||||
mySeriesTitleEntry = new SeriesTitleEntry();
|
||||
//myBookNumberEntry = new ZLSimpleSpinOptionEntry(myBookInfo.NumberInSeriesOption, 1);
|
||||
|
||||
commonTab.addOption("authorDisplayName", myAuthorDisplayNameEntry);
|
||||
commonTab.addOption("authorSortKey", myAuthorSortKeyEntry);
|
||||
commonTab.addOption("language", myLanguageEntry);
|
||||
if (myEncodingSetEntry != null) {
|
||||
commonTab.addOption("encodingSet", myEncodingSetEntry);
|
||||
}
|
||||
commonTab.addOption("encoding", myEncodingEntry);
|
||||
|
||||
ZLDialogContent seriesTab = myDialog.createTab("Series");
|
||||
seriesTab.addOption("seriesTitle", mySeriesTitleEntry);
|
||||
seriesTab.addOption("bookNumber", myBookNumberEntry);
|
||||
mySeriesTitleEntry.onValueEdited(mySeriesTitleEntry.initialValue());
|
||||
|
||||
ZLDialogContent tagsTab = myDialog.createTab("Tags");
|
||||
//tagsTab.addOption("tags", myBookInfo.TagsOption);
|
||||
|
||||
//FormatPlugin plugin = PluginCollection.instance().getPlugin(new ZLFile(fileName), false);
|
||||
//if (plugin != null) {
|
||||
//myFormatInfoPage = plugin.createInfoPage(myDialog, fileName);
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
public ZLOptionsDialog getDialog() {
|
||||
return myDialog;
|
||||
}
|
||||
|
||||
private class AuthorSortKeyEntry extends ZLStringOptionEntry {
|
||||
public String initialValue() {
|
||||
Author currentAuthor = myAuthorDisplayNameEntry.myCurrentAuthor;
|
||||
return //currentAuthor == null ?
|
||||
//myBookInfo.AuthorSortKeyOption.getValue() :
|
||||
currentAuthor.SortKey;
|
||||
}
|
||||
|
||||
public void onAccept(String value) {
|
||||
//myBookInfo.AuthorSortKeyOption.setValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
private class AuthorDisplayNameEntry extends ZLComboOptionEntry {
|
||||
private final ArrayList myValues = new ArrayList();
|
||||
private Author myCurrentAuthor;
|
||||
|
||||
public AuthorDisplayNameEntry() {
|
||||
super(true);
|
||||
}
|
||||
|
||||
public ArrayList getValues() {
|
||||
if (myValues.size() == 0) {
|
||||
final String initial = initialValue();
|
||||
boolean addInitial = true;
|
||||
/*
|
||||
for (Author author : myCollection.authors()) {
|
||||
final String name = author.DisplayName;
|
||||
if (addInitial && name.equals(initial)) {
|
||||
addInitial = false;
|
||||
}
|
||||
myValues.add(name);
|
||||
}
|
||||
*/
|
||||
if (addInitial) {
|
||||
myValues.add(initial);
|
||||
}
|
||||
}
|
||||
return myValues;
|
||||
}
|
||||
|
||||
public String initialValue() {
|
||||
return "";//myBookInfo.AuthorDisplayNameOption.getValue();
|
||||
}
|
||||
|
||||
public void onAccept(String value) {
|
||||
//myBookInfo.AuthorDisplayNameOption.setValue(value);
|
||||
}
|
||||
|
||||
public void onValueSelected(int index) {
|
||||
/*
|
||||
final Collection<Author> authors = myCollection.authors();
|
||||
if (index < authors.size()) {
|
||||
myCurrentAuthor = new ArrayList<Author>(authors).get(index);
|
||||
}
|
||||
*/
|
||||
myAuthorSortKeyEntry.resetView();
|
||||
mySeriesTitleEntry.resetView();
|
||||
}
|
||||
}
|
||||
|
||||
private class SeriesTitleEntry extends ZLComboOptionEntry {
|
||||
private final ArrayList myValues = new ArrayList();
|
||||
private Author myOriginalAuthor;
|
||||
|
||||
public SeriesTitleEntry() {
|
||||
super(true);
|
||||
final String authorName = "";//myBookInfo.AuthorDisplayNameOption.getValue();
|
||||
final String authorKey = "";//myBookInfo.AuthorSortKeyOption.getValue();
|
||||
/*
|
||||
for (Author author : myCollection.authors()) {
|
||||
if ((authorName != null && authorName.equals(author.DisplayName)) &&
|
||||
(authorKey != null && authorKey.equals(author.SortKey))) {
|
||||
myOriginalAuthor = author;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
public boolean useOnValueEdited() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void onValueEdited(String value) {
|
||||
myBookNumberEntry.setVisible(value != null && !value.equals(""));;
|
||||
}
|
||||
|
||||
public void onValueSelected(int index) {
|
||||
myBookNumberEntry.setVisible(index != 0);
|
||||
}
|
||||
|
||||
public ArrayList getValues() {
|
||||
myValues.clear();
|
||||
HashSet valuesSet = new HashSet();
|
||||
valuesSet.add(initialValue());
|
||||
valuesSet.add("");
|
||||
if (myOriginalAuthor != null) {
|
||||
//myCollection.collectSeriesNames(myOriginalAuthor, valuesSet);
|
||||
}
|
||||
Author currentAuthor = myAuthorDisplayNameEntry.myCurrentAuthor;
|
||||
if (currentAuthor != null && (currentAuthor != myOriginalAuthor)) {
|
||||
//myCollection.collectSeriesNames(currentAuthor, valuesSet);
|
||||
}
|
||||
myValues.addAll(valuesSet);
|
||||
return myValues;
|
||||
}
|
||||
|
||||
public String initialValue() {
|
||||
return "";//myBookInfo.SeriesNameOption.getValue();
|
||||
}
|
||||
|
||||
public void onAccept(String value) {
|
||||
//myBookInfo.SeriesNameOption.setValue(value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -38,7 +38,7 @@ import org.geometerplus.zlibrary.text.hyphenation.ZLTextHyphenator;
|
|||
import org.geometerplus.fbreader.bookmodel.BookModel;
|
||||
import org.geometerplus.fbreader.collection.BookCollection;
|
||||
import org.geometerplus.fbreader.collection.RecentBooks;
|
||||
import org.geometerplus.fbreader.description.BookDescription;
|
||||
import org.geometerplus.fbreader.collection.BookDescription;
|
||||
|
||||
public final class FBReader extends ZLApplication {
|
||||
static interface ViewMode {
|
||||
|
@ -108,7 +108,6 @@ public final class FBReader extends ZLApplication {
|
|||
addAction(ActionCode.SHOW_LIBRARY, new ShowLibrary(this));
|
||||
addAction(ActionCode.SHOW_OPTIONS, new ShowOptionsDialogAction(this));
|
||||
addAction(ActionCode.SHOW_CONTENTS, new ShowTOCAction(this));
|
||||
addAction(ActionCode.SHOW_BOOK_INFO, new ShowBookInfoDialogAction(this));
|
||||
|
||||
addAction(ActionCode.SEARCH, new SearchAction(this));
|
||||
addAction(ActionCode.FIND_NEXT, new FindNextAction(this));
|
||||
|
@ -239,13 +238,10 @@ public final class FBReader extends ZLApplication {
|
|||
BookTextView.setModels(null, "");
|
||||
|
||||
Model = null;
|
||||
//android.os.Debug.startMethodTracing("/data/anr/loading");
|
||||
Model = new BookModel(description);
|
||||
//android.os.Debug.stopMethodTracing();
|
||||
final String fileName = description.FileName;
|
||||
myBookNameOption.setValue(fileName);
|
||||
ZLTextHyphenator.getInstance().load(description.getLanguage());
|
||||
// BookTextView.setModel(Model.BookTextModel, fileName);
|
||||
BookTextView.setModels(Model.getBookTextModels(), fileName);
|
||||
BookTextView.setCaption(description.getTitle());
|
||||
FootnoteView.setModel(null);
|
||||
|
@ -268,9 +264,7 @@ public final class FBReader extends ZLApplication {
|
|||
}
|
||||
|
||||
public void run() {
|
||||
//final long start = System.currentTimeMillis();
|
||||
openBookInternal(myDescription);
|
||||
//android.util.Log.w("openBook", "" + (System.currentTimeMillis() - start));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2007-2009 Geometer Plus <contact@geometerplus.com>
|
||||
*
|
||||
* This program 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package org.geometerplus.fbreader.fbreader;
|
||||
|
||||
import org.geometerplus.fbreader.collection.BookCollection;
|
||||
|
||||
class ShowBookInfoDialogAction extends FBAction {
|
||||
ShowBookInfoDialogAction(FBReader fbreader) {
|
||||
super(fbreader);
|
||||
}
|
||||
|
||||
public boolean isVisible() {
|
||||
return Reader.getMode() == FBReader.ViewMode.BOOK_TEXT;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
final String fileName = Reader.BookTextView.getFileName();
|
||||
Runnable action = new Runnable() {
|
||||
public void run() {
|
||||
Reader.openFile(fileName);
|
||||
Reader.refreshWindow();
|
||||
}
|
||||
};
|
||||
new BookInfoDialog(fileName, action).getDialog().run();
|
||||
}
|
||||
}
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
package org.geometerplus.fbreader.fbreader;
|
||||
|
||||
import org.geometerplus.fbreader.description.BookDescription;
|
||||
import org.geometerplus.fbreader.collection.BookDescription;
|
||||
|
||||
class ShowHelpAction extends FBAction {
|
||||
ShowHelpAction(FBReader fbreader) {
|
||||
|
|
|
@ -29,7 +29,7 @@ class ShowTOCAction extends FBAction {
|
|||
}
|
||||
|
||||
public boolean isVisible() {
|
||||
return Reader.Model.ContentsTree.hasChildren();
|
||||
return Reader.Model.TOCTree.hasChildren();
|
||||
}
|
||||
|
||||
public void run() {
|
||||
|
|
|
@ -23,8 +23,7 @@ import java.io.*;
|
|||
import java.util.*;
|
||||
|
||||
import org.geometerplus.fbreader.bookmodel.BookModel;
|
||||
import org.geometerplus.fbreader.description.BookDescription;
|
||||
import org.geometerplus.fbreader.description.BookDescription.WritableBookDescription;
|
||||
import org.geometerplus.fbreader.collection.BookDescription;
|
||||
import org.geometerplus.zlibrary.core.dialogs.ZLOptionsDialog;
|
||||
import org.geometerplus.zlibrary.core.filesystem.ZLFile;
|
||||
import org.geometerplus.zlibrary.core.language.ZLLanguageDetector;
|
||||
|
@ -72,8 +71,8 @@ public abstract class FormatPlugin {
|
|||
}
|
||||
}
|
||||
}
|
||||
new WritableBookDescription(description).setEncoding(encoding);
|
||||
new WritableBookDescription(description).setLanguage(language);
|
||||
description.setEncoding(encoding);
|
||||
description.setLanguage(language);
|
||||
}
|
||||
}
|
||||
//Last working version
|
||||
|
@ -84,24 +83,24 @@ public abstract class FormatPlugin {
|
|||
if (encoding == "unknown") {
|
||||
encoding = "windows-1252";
|
||||
}
|
||||
new WritableBookDescription(description).setEncoding(encoding);
|
||||
description.setEncoding(encoding);
|
||||
}
|
||||
|
||||
if (description.getLanguage() == "") {
|
||||
if ((encoding.equals("US-ASCII")) ||
|
||||
(encoding.equals("ISO-8859-1"))) {
|
||||
new WritableBookDescription(description).setLanguage("en");
|
||||
description.setLanguage("en");
|
||||
} else if ((description.getEncoding().equals("KOI8-R")) ||
|
||||
(encoding.equals("windows-1251")) ||
|
||||
(encoding.equals("ISO-8859-5")) ||
|
||||
(encoding.equals("IBM866"))) {
|
||||
new WritableBookDescription(description).setLanguage("ru");
|
||||
description.setLanguage("ru");
|
||||
} /*else if (
|
||||
(PluginCollection.instance().DefaultLanguageOption.getValue() == EncodingDetector.Language.CZECH) &&
|
||||
((encoding == "windows-1250") ||
|
||||
(encoding == "ISO-8859-2") ||
|
||||
(encoding == "IBM852"))) {
|
||||
new WritableBookDescription(description).setLanguage("cs");
|
||||
description.setLanguage("cs");
|
||||
}*/
|
||||
/*}
|
||||
|
||||
|
|
|
@ -23,8 +23,8 @@ import java.util.*;
|
|||
|
||||
import org.geometerplus.zlibrary.core.xml.*;
|
||||
|
||||
import org.geometerplus.fbreader.description.BookDescription;
|
||||
import org.geometerplus.fbreader.description.BookDescription.WritableBookDescription;
|
||||
import org.geometerplus.fbreader.collection.BookDescription;
|
||||
import org.geometerplus.fbreader.collection.Tag;
|
||||
|
||||
public class FB2DescriptionReader extends ZLXMLReaderAdapter {
|
||||
private final static int READ_NOTHING = 0;
|
||||
|
@ -37,18 +37,16 @@ public class FB2DescriptionReader extends ZLXMLReaderAdapter {
|
|||
private final static int READ_LANGUAGE = 7;
|
||||
private final static int READ_GENRE = 8;
|
||||
|
||||
private WritableBookDescription myDescription;
|
||||
private final BookDescription myDescription;
|
||||
private int myReadState = READ_NOTHING;
|
||||
|
||||
private final String[] myAuthorNames = new String[3];
|
||||
private final StringBuilder myGenreBuffer = new StringBuilder();
|
||||
private final StringBuilder myBuffer = new StringBuilder();
|
||||
|
||||
public FB2DescriptionReader(BookDescription description) {
|
||||
myDescription = new WritableBookDescription(description);
|
||||
myDescription.clearAuthor();
|
||||
myDescription.setTitle("");
|
||||
myDescription.setLanguage("");
|
||||
myDescription.removeAllTags();
|
||||
myDescription = description;
|
||||
myDescription.setTitle(null);
|
||||
myDescription.setLanguage(null);
|
||||
}
|
||||
|
||||
public boolean dontCacheAttributeValues() {
|
||||
|
@ -60,7 +58,7 @@ public class FB2DescriptionReader extends ZLXMLReaderAdapter {
|
|||
myAuthorNames[0] = "";
|
||||
myAuthorNames[1] = "";
|
||||
myAuthorNames[2] = "";
|
||||
myGenreBuffer.delete(0, myGenreBuffer.length());
|
||||
myBuffer.delete(0, myBuffer.length());
|
||||
return readDocument(fileName);
|
||||
}
|
||||
|
||||
|
@ -110,11 +108,11 @@ public class FB2DescriptionReader extends ZLXMLReaderAdapter {
|
|||
if (myReadState == READ_SOMETHING) {
|
||||
String name = attributes.getValue("name");
|
||||
if (name != null) {
|
||||
String sequenceName = name;
|
||||
sequenceName.trim();
|
||||
myDescription.setSeriesName(sequenceName);
|
||||
String number = attributes.getValue("number");
|
||||
myDescription.setNumberInSeries((number != null) ? Integer.parseInt(number) : 0);
|
||||
name.trim();
|
||||
if (name.length() != 0) {
|
||||
String index = attributes.getValue("number");
|
||||
myDescription.setSeriesInfo(name, (index != null) ? Integer.parseInt(index) : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -129,22 +127,21 @@ public class FB2DescriptionReader extends ZLXMLReaderAdapter {
|
|||
break;
|
||||
case FB2Tag.BOOK_TITLE:
|
||||
if (myReadState == READ_TITLE) {
|
||||
myDescription.setTitle(myBuffer.toString().trim());
|
||||
myReadState = READ_SOMETHING;
|
||||
}
|
||||
break;
|
||||
case FB2Tag.GENRE:
|
||||
if (myReadState == READ_GENRE) {
|
||||
final String genre = myGenreBuffer.toString().trim();
|
||||
myGenreBuffer.delete(0, myGenreBuffer.length());
|
||||
final String genre = myBuffer.toString().trim();
|
||||
if (genre.length() > 0) {
|
||||
final ArrayList tags = FB2TagManager.humanReadableTags(genre);
|
||||
final ArrayList<Tag> tags = FB2TagManager.humanReadableTags(genre);
|
||||
if (tags != null) {
|
||||
final int len = tags.size();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
myDescription.addTag((String)tags.get(i), false);
|
||||
for (Tag t : tags) {
|
||||
myDescription.addTag(t);
|
||||
}
|
||||
} else {
|
||||
myDescription.addTag(genre, true);
|
||||
myDescription.addTag(genre);
|
||||
}
|
||||
}
|
||||
myReadState = READ_SOMETHING;
|
||||
|
@ -173,6 +170,7 @@ public class FB2DescriptionReader extends ZLXMLReaderAdapter {
|
|||
break;
|
||||
case FB2Tag.LANG:
|
||||
if (myReadState == READ_LANGUAGE) {
|
||||
myDescription.setLanguage(myBuffer.toString().trim());
|
||||
myReadState = READ_SOMETHING;
|
||||
}
|
||||
break;
|
||||
|
@ -194,17 +192,12 @@ public class FB2DescriptionReader extends ZLXMLReaderAdapter {
|
|||
default:
|
||||
break;
|
||||
}
|
||||
myBuffer.delete(0, myBuffer.length());
|
||||
return false;
|
||||
}
|
||||
|
||||
public void characterDataHandler(char[] data, int start, int length) {
|
||||
switch (myReadState) {
|
||||
case READ_TITLE:
|
||||
myDescription.setTitle(myDescription.getTitle() + new String(data, start, length));
|
||||
break;
|
||||
case READ_LANGUAGE:
|
||||
myDescription.setLanguage(myDescription.getLanguage() + new String(data, start, length));
|
||||
break;
|
||||
case READ_AUTHOR_NAME_0:
|
||||
myAuthorNames[0] += new String(data, start, length);
|
||||
break;
|
||||
|
@ -214,8 +207,10 @@ public class FB2DescriptionReader extends ZLXMLReaderAdapter {
|
|||
case READ_AUTHOR_NAME_2:
|
||||
myAuthorNames[2] += new String(data, start, length);
|
||||
break;
|
||||
case READ_TITLE:
|
||||
case READ_LANGUAGE:
|
||||
case READ_GENRE:
|
||||
myGenreBuffer.append(data, start, length);
|
||||
myBuffer.append(data, start, length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
package org.geometerplus.fbreader.formats.fb2;
|
||||
|
||||
import org.geometerplus.fbreader.bookmodel.BookModel;
|
||||
import org.geometerplus.fbreader.description.BookDescription;
|
||||
import org.geometerplus.fbreader.collection.BookDescription;
|
||||
import org.geometerplus.fbreader.formats.FormatPlugin;
|
||||
import org.geometerplus.zlibrary.core.filesystem.ZLFile;
|
||||
|
||||
|
|
|
@ -25,16 +25,18 @@ import org.geometerplus.zlibrary.core.util.*;
|
|||
import org.geometerplus.zlibrary.core.library.ZLibrary;
|
||||
import org.geometerplus.zlibrary.core.xml.*;
|
||||
|
||||
abstract class FB2TagManager {
|
||||
private static final HashMap ourMap = new HashMap();
|
||||
import org.geometerplus.fbreader.collection.Tag;
|
||||
|
||||
static ArrayList humanReadableTags(String id) {
|
||||
abstract class FB2TagManager {
|
||||
private static final HashMap<String,ArrayList<Tag>> ourMap = new HashMap<String,ArrayList<Tag>>();
|
||||
|
||||
static ArrayList<Tag> humanReadableTags(String id) {
|
||||
if (ourMap.isEmpty()) {
|
||||
new FB2TagInfoReader().read(
|
||||
ZLibrary.JAR_DATA_PREFIX + "data/formats/fb2/fb2genres.xml"
|
||||
);
|
||||
}
|
||||
return (ArrayList)ourMap.get(id);
|
||||
return ourMap.get(id);
|
||||
}
|
||||
|
||||
private FB2TagManager() {
|
||||
|
@ -42,9 +44,9 @@ abstract class FB2TagManager {
|
|||
|
||||
private static class FB2TagInfoReader extends ZLXMLReaderAdapter {
|
||||
private final String myLanguage;
|
||||
private String myCategoryName;
|
||||
private String mySubCategoryName;
|
||||
private final ArrayList myGenreIds = new ArrayList();
|
||||
private Tag myCategoryTag;
|
||||
private Tag mySubCategoryTag;
|
||||
private final ArrayList<String> myGenreIds = new ArrayList<String>();
|
||||
|
||||
FB2TagInfoReader() {
|
||||
final String language = Locale.getDefault().getLanguage();
|
||||
|
@ -59,17 +61,11 @@ abstract class FB2TagManager {
|
|||
}
|
||||
} else if (tag == "root-descr") {
|
||||
if (myLanguage == attributes.getValue("lang")) {
|
||||
final String name = attributes.getValue("genre-title");
|
||||
if (name != null) {
|
||||
myCategoryName = name.trim();
|
||||
}
|
||||
myCategoryTag = Tag.getTag(null, attributes.getValue("genre-title"));
|
||||
}
|
||||
} else if (tag == "genre-descr") {
|
||||
if (myLanguage == attributes.getValue("lang")) {
|
||||
final String name = attributes.getValue("title");
|
||||
if (name != null) {
|
||||
mySubCategoryName = name.trim();
|
||||
}
|
||||
mySubCategoryTag = Tag.getTag(myCategoryTag, attributes.getValue("title"));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -77,24 +73,21 @@ abstract class FB2TagManager {
|
|||
|
||||
public boolean endElementHandler(String tag) {
|
||||
if (tag == "genre") {
|
||||
myCategoryName = null;
|
||||
mySubCategoryName = null;
|
||||
myCategoryTag = null;
|
||||
mySubCategoryTag = null;
|
||||
myGenreIds.clear();
|
||||
} else if (tag == "subgenre") {
|
||||
if ((myCategoryName != null) && (mySubCategoryName != null)) {
|
||||
final String fullTagName = myCategoryName + '/' + mySubCategoryName;
|
||||
final int len = myGenreIds.size();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
final Object id = myGenreIds.get(i);
|
||||
ArrayList list = (ArrayList)ourMap.get(id);
|
||||
if (mySubCategoryTag != null) {
|
||||
for (String id : myGenreIds) {
|
||||
ArrayList<Tag> list = ourMap.get(id);
|
||||
if (list == null) {
|
||||
list = new ArrayList();
|
||||
list = new ArrayList<Tag>();
|
||||
ourMap.put(id, list);
|
||||
}
|
||||
list.add(fullTagName);
|
||||
list.add(mySubCategoryTag);
|
||||
}
|
||||
}
|
||||
mySubCategoryName = null;
|
||||
mySubCategoryTag = null;
|
||||
myGenreIds.clear();
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -19,21 +19,19 @@
|
|||
|
||||
package org.geometerplus.fbreader.formats.html;
|
||||
|
||||
import org.geometerplus.fbreader.description.BookDescription;
|
||||
import org.geometerplus.fbreader.description.BookDescription.WritableBookDescription;
|
||||
import org.geometerplus.fbreader.collection.BookDescription;
|
||||
import org.geometerplus.zlibrary.core.xml.ZLStringMap;
|
||||
import org.geometerplus.zlibrary.core.xml.ZLXMLProcessor;
|
||||
import org.geometerplus.zlibrary.core.xml.ZLXMLProcessorFactory;
|
||||
import org.geometerplus.zlibrary.core.xml.ZLXMLReaderAdapter;
|
||||
|
||||
public class HtmlDescriptionReader extends ZLXMLReaderAdapter {
|
||||
|
||||
private WritableBookDescription myDescription;
|
||||
private final BookDescription myDescription;
|
||||
|
||||
private boolean myReadTitle;
|
||||
|
||||
public HtmlDescriptionReader(BookDescription description) {
|
||||
myDescription = new WritableBookDescription(description);
|
||||
myDescription = description;
|
||||
myDescription.setTitle("");
|
||||
}
|
||||
|
||||
|
|
|
@ -20,8 +20,7 @@
|
|||
package org.geometerplus.fbreader.formats.html;
|
||||
|
||||
import org.geometerplus.fbreader.bookmodel.BookModel;
|
||||
import org.geometerplus.fbreader.description.BookDescription;
|
||||
import org.geometerplus.fbreader.description.BookDescription.WritableBookDescription;
|
||||
import org.geometerplus.fbreader.collection.BookDescription;
|
||||
import org.geometerplus.fbreader.formats.FormatPlugin;
|
||||
import org.geometerplus.fbreader.formats.fb2.FB2DescriptionReader;
|
||||
import org.geometerplus.fbreader.formats.fb2.FB2Reader;
|
||||
|
|
|
@ -22,11 +22,11 @@ package org.geometerplus.fbreader.formats.oeb;
|
|||
import java.util.*;
|
||||
|
||||
import org.geometerplus.zlibrary.core.xml.*;
|
||||
import org.geometerplus.fbreader.description.BookDescription;
|
||||
import org.geometerplus.fbreader.collection.BookDescription;
|
||||
import org.geometerplus.fbreader.constants.XMLNamespace;
|
||||
|
||||
class OEBDescriptionReader extends ZLXMLReaderAdapter implements XMLNamespace {
|
||||
private final BookDescription.WritableBookDescription myDescription;
|
||||
private final BookDescription myDescription;
|
||||
|
||||
private String myDCMetadataTag = "dc-metadata";
|
||||
private String myMetadataTag = "metadata";
|
||||
|
@ -36,14 +36,13 @@ class OEBDescriptionReader extends ZLXMLReaderAdapter implements XMLNamespace {
|
|||
private String mySubjectTag;
|
||||
private String myLanguageTag;
|
||||
|
||||
private final ArrayList myAuthorList = new ArrayList();
|
||||
private final ArrayList myAuthorList2 = new ArrayList();
|
||||
private final ArrayList<String> myAuthorList = new ArrayList<String>();
|
||||
private final ArrayList<String> myAuthorList2 = new ArrayList<String>();
|
||||
|
||||
OEBDescriptionReader(BookDescription description) {
|
||||
myDescription = new BookDescription.WritableBookDescription(description);
|
||||
myDescription.clearAuthor();
|
||||
myDescription.setTitle("");
|
||||
myDescription.removeAllTags();
|
||||
myDescription = description;
|
||||
myDescription.setTitle(null);
|
||||
myDescription.setLanguage(null);
|
||||
}
|
||||
|
||||
boolean readDescription(String fileName) {
|
||||
|
@ -56,10 +55,15 @@ class OEBDescriptionReader extends ZLXMLReaderAdapter implements XMLNamespace {
|
|||
return false;
|
||||
}
|
||||
|
||||
final ArrayList authors = myAuthorList.isEmpty() ? myAuthorList2 : myAuthorList;
|
||||
final int len = authors.size();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
myDescription.addAuthor((String)authors.get(i));
|
||||
final ArrayList<String> authors = myAuthorList.isEmpty() ? myAuthorList2 : myAuthorList;
|
||||
for (String a : authors) {
|
||||
final int index = a.indexOf(',');
|
||||
if (index >= 0) {
|
||||
a = a.substring(index + 1).trim() + ' ' + a.substring(0, index).trim();
|
||||
} else {
|
||||
a = a.trim();
|
||||
}
|
||||
myDescription.addAuthor(a);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -158,7 +162,7 @@ class OEBDescriptionReader extends ZLXMLReaderAdapter implements XMLNamespace {
|
|||
myAuthorList2.add(bufferContent);
|
||||
break;
|
||||
case READ_SUBJECT:
|
||||
myDescription.addTag(bufferContent, true);
|
||||
myDescription.addTag(bufferContent);
|
||||
break;
|
||||
case READ_LANGUAGE:
|
||||
{
|
||||
|
|
|
@ -22,7 +22,7 @@ package org.geometerplus.fbreader.formats.oeb;
|
|||
import java.util.ArrayList;
|
||||
|
||||
import org.geometerplus.fbreader.bookmodel.BookModel;
|
||||
import org.geometerplus.fbreader.description.BookDescription;
|
||||
import org.geometerplus.fbreader.collection.BookDescription;
|
||||
import org.geometerplus.fbreader.formats.FormatPlugin;
|
||||
import org.geometerplus.zlibrary.core.filesystem.*;
|
||||
|
||||
|
@ -61,7 +61,6 @@ public class OEBPlugin extends FormatPlugin {
|
|||
|
||||
public boolean readDescription(String path, BookDescription description) {
|
||||
path = getOpfFileName(path);
|
||||
System.err.println("path = " + path);
|
||||
if (path == null) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ package org.geometerplus.fbreader.formats.pdb;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.geometerplus.fbreader.description.BookDescriptionUtil;
|
||||
import org.geometerplus.fbreader.collection.BookDescriptionUtil;
|
||||
import org.geometerplus.fbreader.formats.FormatPlugin;
|
||||
import org.geometerplus.fbreader.formats.plucker.PluckerTextStream;
|
||||
import org.geometerplus.zlibrary.core.filesystem.ZLFile;
|
||||
|
|
|
@ -22,7 +22,7 @@ package org.geometerplus.fbreader.formats.plucker;
|
|||
import java.io.IOException;
|
||||
|
||||
import org.geometerplus.fbreader.bookmodel.BookModel;
|
||||
import org.geometerplus.fbreader.description.BookDescription;
|
||||
import org.geometerplus.fbreader.collection.BookDescription;
|
||||
import org.geometerplus.fbreader.formats.pdb.PdbPlugin;
|
||||
import org.geometerplus.fbreader.formats.pdb.PdbStream;
|
||||
import org.geometerplus.zlibrary.core.filesystem.ZLFile;
|
||||
|
|
|
@ -127,7 +127,6 @@ public class KeyBindingsPage {
|
|||
|
||||
// dialogs
|
||||
addAction(ActionCode.SHOW_OPTIONS);
|
||||
addAction(ActionCode.SHOW_BOOK_INFO);
|
||||
|
||||
// quit
|
||||
addAction(ActionCode.CANCEL);
|
||||
|
|
|
@ -401,7 +401,6 @@ public abstract class ZLTextViewImpl extends ZLTextView {
|
|||
}
|
||||
|
||||
public synchronized void paint() {
|
||||
//android.os.Debug.startMethodTracing("/tmp/paint");
|
||||
myTextElementMap.clear();
|
||||
myTreeNodeMap.clear();
|
||||
|
||||
|
@ -445,7 +444,6 @@ public abstract class ZLTextViewImpl extends ZLTextView {
|
|||
for (int i = 0; i < lineInfosSize; ++i) {
|
||||
drawTextLine(context, lineInfos.getInfo(i), labels[i], labels[i + 1]);
|
||||
}
|
||||
//android.os.Debug.stopMethodTracing();
|
||||
}
|
||||
|
||||
private int sizeOfTextBeforeCursor(ZLTextWordCursor wordCursor) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue