1
0
Fork 0
mirror of https://github.com/geometer/FBReaderJ.git synced 2025-10-04 18:29:23 +02:00

labels work as other book properties

This commit is contained in:
Nikolay Pultsin 2013-04-21 21:49:41 +02:00
parent 87eb3a9726
commit 6696447327
13 changed files with 148 additions and 170 deletions

View file

@ -202,7 +202,7 @@ public class LibraryActivity extends TreeActivity<LibraryTree> implements MenuIt
if (book.File.getPhysicalFile() != null) {
menu.add(0, SHARE_BOOK_ITEM_ID, 0, resource.getResource("shareBook").getValue());
}
if (myRootTree.Collection.labels(book).contains(Book.FAVORITE_LABEL)) {
if (book.labels().contains(Book.FAVORITE_LABEL)) {
menu.add(0, REMOVE_FROM_FAVORITES_ITEM_ID, 0, resource.getResource("removeFromFavorites").getValue());
} else {
menu.add(0, ADD_TO_FAVORITES_ITEM_ID, 0, resource.getResource("addToFavorites").getValue());
@ -234,10 +234,12 @@ public class LibraryActivity extends TreeActivity<LibraryTree> implements MenuIt
FBUtil.shareBook(this, book);
return true;
case ADD_TO_FAVORITES_ITEM_ID:
myRootTree.Collection.setLabel(book, Book.FAVORITE_LABEL);
book.addLabel(Book.FAVORITE_LABEL);
myRootTree.Collection.saveBook(book, false);
return true;
case REMOVE_FROM_FAVORITES_ITEM_ID:
myRootTree.Collection.removeLabel(book, Book.FAVORITE_LABEL);
book.removeLabel(Book.FAVORITE_LABEL);
myRootTree.Collection.saveBook(book, false);
if (getCurrentTree().onBookEvent(BookEvent.Updated, book)) {
getListAdapter().replaceAll(getCurrentTree().subTrees());
getListView().invalidateViews();

View file

@ -166,17 +166,6 @@ public class BookCollectionShadow extends AbstractBookCollection implements Serv
}
}
public synchronized List<Book> booksForLabel(String label) {
if (myInterface == null) {
return Collections.emptyList();
}
try {
return SerializerUtil.deserializeBookList(myInterface.booksForLabel(label));
} catch (RemoteException e) {
return Collections.emptyList();
}
}
public synchronized Book getRecentBook(int index) {
if (myInterface == null) {
return null;
@ -335,34 +324,6 @@ public class BookCollectionShadow extends AbstractBookCollection implements Serv
return Collections.emptyList();
}
public synchronized List<String> labels(Book book) {
if (myInterface != null) {
try {
return myInterface.labelsForBook(SerializerUtil.serialize(book));
} catch (RemoteException e) {
}
}
return Collections.emptyList();
}
public synchronized void setLabel(Book book, String label) {
if (myInterface != null) {
try {
myInterface.setLabel(SerializerUtil.serialize(book), label);
} catch (RemoteException e) {
}
}
}
public synchronized void removeLabel(Book book, String label) {
if (myInterface != null) {
try {
myInterface.removeLabel(SerializerUtil.serialize(book), label);
} catch (RemoteException e) {
}
}
}
public synchronized ZLTextPosition getStoredPosition(long bookId) {
if (myInterface == null) {
return null;

View file

@ -15,7 +15,7 @@ interface LibraryInterface {
int size();
List<String> books(in String query);
boolean hasBooks(in String query);
List<String> booksForLabel(in String label);
List<String> recentBooks();
String getBookByFile(in String file);
@ -27,14 +27,10 @@ interface LibraryInterface {
boolean hasSeries();
List<String> series();
List<String> tags();
List<String> labels();
List<String> titles(in String query);
List<String> firstTitleLetters();
List<String> labels();
List<String> labelsForBook(in String book);
void setLabel(in String book, in String label);
void removeLabel(in String book, in String label);
boolean saveBook(in String book, in boolean force);
void removeBook(in String book, in boolean deleteFromDisk);
void addBookToRecentList(in String book);

View file

@ -150,10 +150,6 @@ public class LibraryService extends Service {
return SerializerUtil.serializeBookList(myCollection.recentBooks());
}
public List<String> booksForLabel(String label) {
return SerializerUtil.serializeBookList(myCollection.booksForLabel(label));
}
public String getRecentBook(int index) {
return SerializerUtil.serialize(myCollection.getRecentBook(index));
}
@ -220,18 +216,6 @@ public class LibraryService extends Service {
return myCollection.labels();
}
public List<String> labelsForBook(String book) {
return myCollection.labels(SerializerUtil.deserializeBook(book));
}
public void setLabel(String book, String label) {
myCollection.setLabel(SerializerUtil.deserializeBook(book), label);
}
public void removeLabel(String book, String label) {
myCollection.removeLabel(SerializerUtil.deserializeBook(book), label);
}
public TextPosition getStoredPosition(long bookId) {
final ZLTextPosition position = myCollection.getStoredPosition(bookId);
if (position == null) {

View file

@ -468,6 +468,22 @@ final class SQLiteBooksDatabase extends BooksDatabase {
return list;
}
@Override
protected List<String> listLabels(long bookId) {
final Cursor cursor = myDatabase.rawQuery(
"SELECT Labels.name FROM Labels" +
" INNER JOIN BookLabel ON BookLabel.label_id=Labels.label_id" +
" WHERE BookLabel.book_id=?",
new String[] { String.valueOf(bookId) }
);
final LinkedList<String> names = new LinkedList<String>();
while (cursor.moveToNext()) {
names.add(cursor.getString(0));
}
cursor.close();
return names;
}
private SQLiteStatement myDeleteBookUidsStatement;
protected void deleteAllBookUids(long bookId) {
if (myDeleteBookUidsStatement == null) {
@ -736,38 +752,6 @@ final class SQLiteBooksDatabase extends BooksDatabase {
return ids;
}
@Override
protected List<String> labels() {
final Cursor cursor = myDatabase.rawQuery(
"SELECT Labels.name FROM Labels" +
" INNER JOIN BookLabel ON BookLabel.label_id=Labels.label_id" +
" GROUP BY Labels.name",
null
);
final LinkedList<String> names = new LinkedList<String>();
while (cursor.moveToNext()) {
names.add(cursor.getString(0));
}
cursor.close();
return names;
}
@Override
protected List<String> labels(long bookId) {
final Cursor cursor = myDatabase.rawQuery(
"SELECT Labels.name FROM Labels" +
" INNER JOIN BookLabel ON BookLabel.label_id=Labels.label_id" +
" WHERE BookLabel.book_id=?",
new String[] { String.valueOf(bookId) }
);
final LinkedList<String> names = new LinkedList<String>();
while (cursor.moveToNext()) {
names.add(cursor.getString(0));
}
cursor.close();
return names;
}
private SQLiteStatement mySetLabelStatement;
@Override
protected void setLabel(long bookId, String label) {
@ -797,21 +781,6 @@ final class SQLiteBooksDatabase extends BooksDatabase {
myRemoveLabelStatement.execute();
}
@Override
protected List<Long> loadBooksForLabelIds(String label) {
final Cursor cursor = myDatabase.rawQuery(
"SELECT BookLabel.book_id FROM BookLabel" +
" INNER JOIN Labels ON BookLabel.label_id=Labels.label_id" +
" WHERE Labels.name=?", new String[] { label }
);
final LinkedList<Long> ids = new LinkedList<Long>();
while (cursor.moveToNext()) {
ids.add(cursor.getLong(0));
}
cursor.close();
return ids;
}
@Override
protected List<Bookmark> loadInvisibleBookmarks(long bookId) {
LinkedList<Bookmark> list = new LinkedList<Bookmark>();

View file

@ -46,6 +46,7 @@ public class Book extends TitledEntity {
private volatile String myLanguage;
private volatile List<Author> myAuthors;
private volatile List<Tag> myTags;
private volatile List<String> myLabels;
private volatile SeriesInfo mySeriesInfo;
private volatile List<UID> myUids;
@ -81,6 +82,7 @@ public class Book extends TitledEntity {
myLanguage = book.myLanguage;
myAuthors = book.myAuthors != null ? new ArrayList<Author>(book.myAuthors) : null;
myTags = book.myTags != null ? new ArrayList<Tag>(book.myTags) : null;
myLabels = book.myLabels != null ? new ArrayList<String>(book.myLabels) : null;
mySeriesInfo = book.mySeriesInfo;
}
@ -114,6 +116,7 @@ public class Book extends TitledEntity {
setTitle(null);
myAuthors = null;
myTags = null;
myLabels = null;
mySeriesInfo = null;
myUids = null;
@ -140,6 +143,7 @@ public class Book extends TitledEntity {
void loadLists(BooksDatabase database) {
myAuthors = database.listAuthors(myId);
myTags = database.listTags(myId);
myLabels = database.listLabels(myId);
mySeriesInfo = database.getSeriesInfo(myId);
myUids = database.listUids(myId);
myIsSaved = true;
@ -324,6 +328,33 @@ public class Book extends TitledEntity {
addTag(Tag.getTag(null, tagName));
}
public List<String> labels() {
return myLabels != null ? Collections.unmodifiableList(myLabels) : Collections.<String>emptyList();
}
void addLabelWithNoCheck(String label) {
if (myLabels == null) {
myLabels = new ArrayList<String>();
}
myLabels.add(label);
}
public void addLabel(String label) {
if (myLabels == null) {
myLabels = new ArrayList<String>();
}
if (!myLabels.contains(label)) {
myLabels.add(label);
myIsSaved = false;
}
}
public void removeLabel(String label) {
if (myLabels != null && myLabels.remove(label)) {
myIsSaved = false;
}
}
public List<UID> uids() {
return myUids != null ? Collections.unmodifiableList(myUids) : Collections.<UID>emptyList();
}
@ -414,6 +445,17 @@ public class Book extends TitledEntity {
for (Tag tag : tags()) {
database.saveBookTagInfo(myId, tag);
}
final List<String> labelsInDb = database.listLabels(myId);
for (String label : labelsInDb) {
if (myLabels == null || !myLabels.contains(label)) {
database.removeLabel(myId, label);
}
}
if (myLabels != null) {
for (String label : myLabels) {
database.setLabel(myId, label);
}
}
database.saveBookSeriesInfo(myId, mySeriesInfo);
database.deleteAllBookUids(myId);
for (UID uid : uids()) {

View file

@ -264,10 +264,6 @@ public class BookCollection extends AbstractBookCollection {
return books(myDatabase.loadRecentBookIds());
}
public List<Book> booksForLabel(String label) {
return books(myDatabase.loadBooksForLabelIds(label));
}
private List<Book> books(List<Long> ids) {
final List<Book> bookList = new ArrayList<Book>(ids.size());
for (long id : ids) {
@ -313,6 +309,16 @@ public class BookCollection extends AbstractBookCollection {
return new ArrayList<Tag>(tags);
}
public List<String> labels() {
final Set<String> labels = new HashSet<String>();
synchronized (myBooksByFile) {
for (Book book : myBooksByFile.values()) {
labels.addAll(book.labels());
}
}
return new ArrayList<String>(labels);
}
public boolean hasSeries() {
synchronized (myBooksByFile) {
for (Book book : myBooksByFile.values()) {
@ -366,27 +372,6 @@ public class BookCollection extends AbstractBookCollection {
myDatabase.saveRecentBookIds(ids);
}
public List<String> labels() {
return myDatabase.labels();
}
public List<String> labels(Book book) {
if (book == null) {
return Collections.<String>emptyList();
}
return myDatabase.labels(book.getId());
}
public void setLabel(Book book, String label) {
myDatabase.setLabel(book.getId(), label);
fireBookEvent(BookEvent.Updated, book);
}
public void removeLabel(Book book, String label) {
myDatabase.removeLabel(book.getId(), label);
fireBookEvent(BookEvent.Updated, book);
}
private void setStatus(Status status) {
myStatus = status;
fireBuildEvent(status);

View file

@ -53,6 +53,7 @@ public abstract class BooksDatabase {
protected abstract List<Author> listAuthors(long bookId);
protected abstract List<Tag> listTags(long bookId);
protected abstract List<String> listLabels(long bookId);
protected abstract SeriesInfo getSeriesInfo(long bookId);
protected abstract List<UID> listUids(long bookId);
@ -81,9 +82,6 @@ public abstract class BooksDatabase {
protected abstract List<Long> loadRecentBookIds();
protected abstract void saveRecentBookIds(final List<Long> ids);
protected abstract List<Long> loadBooksForLabelIds(String label);
protected abstract List<String> labels();
protected abstract List<String> labels(long bookId);
protected abstract void setLabel(long bookId, String label);
protected abstract void removeLabel(long bookId, String label);

View file

@ -58,6 +58,18 @@ public abstract class Filter {
}
}
public final static class ByLabel extends Filter {
public final String Label;
public ByLabel(String label) {
Label = label;
}
public boolean matches(Book book) {
return book.labels().contains(Label);
}
}
public final static class ByPattern extends Filter {
public final String Pattern;

View file

@ -55,13 +55,6 @@ public interface IBookCollection {
boolean hasBooks(Query query);
List<String> titles(Query query);
List<Book> booksForLabel(String label);
List<String> labels();
List<String> labels(Book book);
void setLabel(Book book, String label);
void removeLabel(Book book, String label);
List<Book> recentBooks();
Book getRecentBook(int index);
void addBookToRecentList(Book book);
@ -70,6 +63,7 @@ public interface IBookCollection {
Book getBookById(long id);
Book getBookByUid(UID uid);
List<String> labels();
List<Author> authors();
boolean hasSeries();
List<String> series();

View file

@ -81,6 +81,11 @@ class XMLSerializer extends AbstractSerializer {
params[index++] = name;
}
appendTag(buffer, "filter", true, params);
} else if (filter instanceof Filter.ByLabel) {
appendTag(buffer, "filter", true,
"type", "label",
"name", ((Filter.ByLabel)filter).Label
);
} else if (filter instanceof Filter.BySeries) {
appendTag(buffer, "filter", true,
"type", "series",
@ -156,6 +161,13 @@ class XMLSerializer extends AbstractSerializer {
);
}
for (String label : book.labels()) {
appendTag(
buffer, "label", true,
"name", label
);
}
final SeriesInfo seriesInfo = book.getSeriesInfo();
if (seriesInfo != null) {
appendTagWithContent(buffer, "calibre:series", seriesInfo.Series.getTitle());
@ -333,6 +345,7 @@ class XMLSerializer extends AbstractSerializer {
private final ArrayList<UID> myUidList = new ArrayList<UID>();
private final ArrayList<Author> myAuthors = new ArrayList<Author>();
private final ArrayList<Tag> myTags = new ArrayList<Tag>();
private final ArrayList<String> myLabels = new ArrayList<String>();
private final StringBuilder myAuthorSortKey = new StringBuilder();
private final StringBuilder myAuthorName = new StringBuilder();
private final StringBuilder mySeriesTitle = new StringBuilder();
@ -359,6 +372,7 @@ class XMLSerializer extends AbstractSerializer {
myUidList.clear();
myAuthors.clear();
myTags.clear();
myLabels.clear();
myState = State.READ_NOTHING;
}
@ -381,6 +395,9 @@ class XMLSerializer extends AbstractSerializer {
for (Tag tag : myTags) {
myBook.addTagWithNoCheck(tag);
}
for (String label : myLabels) {
myBook.addLabelWithNoCheck(label);
}
for (UID uid : myUidList) {
myBook.addUid(uid);
}
@ -417,6 +434,11 @@ class XMLSerializer extends AbstractSerializer {
if (term != null) {
myTags.add(Tag.getTag(term.split("/")));
}
} else if ("label".equals(localName)) {
final String name = attributes.getValue("name");
if (name != null) {
myLabels.add(name);
}
} else if ("series".equals(localName) && XMLNamespaces.CalibreMetadata.equals(uri)) {
myState = State.READ_SERIES_TITLE;
} else if ("series_index".equals(localName) && XMLNamespaces.CalibreMetadata.equals(uri)) {
@ -573,6 +595,8 @@ class XMLSerializer extends AbstractSerializer {
names.add(n);
}
myFilter = new Filter.ByTag(Tag.getTag(names.toArray(new String[names.size()])));
} else if ("label".equals(type)) {
myFilter = new Filter.ByLabel(attributes.getValue("name"));
} else if ("series".equals(type)) {
myFilter = new Filter.BySeries(new Series(
attributes.getValue("title")

View file

@ -19,11 +19,41 @@
package org.geometerplus.fbreader.library;
import org.geometerplus.zlibrary.core.resources.ZLResource;
import org.geometerplus.fbreader.book.*;
public class FavoritesTree extends FirstLevelTree {
public class FavoritesTree extends FilteredTree {
private final ZLResource myResource;
FavoritesTree(RootTree root) {
super(root, ROOT_FAVORITES);
super(root, new Filter.ByLabel(Book.FAVORITE_LABEL), -1);
myResource = resource().getResource(ROOT_FAVORITES);
}
@Override
public String getName() {
return myResource.getValue();
}
@Override
public String getTreeTitle() {
return getSummary();
}
@Override
public String getSummary() {
return myResource.getResource("summary").getValue();
}
@Override
protected String getStringId() {
return ROOT_FAVORITES;
}
@Override
public boolean isSelectable() {
return false;
}
@Override
@ -41,26 +71,7 @@ public class FavoritesTree extends FirstLevelTree {
}
@Override
public void waitForOpening() {
clear();
for (Book book : Collection.booksForLabel(Book.FAVORITE_LABEL)) {
createBookWithAuthorsSubTree(book);
}
}
public boolean onBookEvent(BookEvent event, Book book) {
switch (event) {
case Added:
return Collection.labels(book).contains(Book.FAVORITE_LABEL) && createBookWithAuthorsSubTree(book);
case Updated:
{
boolean changed = removeBook(book);
changed |= Collection.labels(book).contains(Book.FAVORITE_LABEL) && createBookWithAuthorsSubTree(book);
return changed;
}
case Removed:
default:
return super.onBookEvent(event, book);
}
protected boolean createSubTree(Book book) {
return createBookWithAuthorsSubTree(book);
}
}

View file

@ -49,7 +49,7 @@ abstract class FilteredTree extends LibraryTree {
}
@Override
public final Status getOpeningStatus() {
public Status getOpeningStatus() {
return Status.ALWAYS_RELOAD_BEFORE_OPENING;
}