diff --git a/assets/resources/application/en.xml b/assets/resources/application/en.xml
index ffd99dd8a..b7d224981 100644
--- a/assets/resources/application/en.xml
+++ b/assets/resources/application/en.xml
@@ -801,6 +801,7 @@
+
diff --git a/src/org/geometerplus/android/fbreader/libraryService/BookCollectionShadow.java b/src/org/geometerplus/android/fbreader/libraryService/BookCollectionShadow.java
index f0d72f68a..12138e91c 100644
--- a/src/org/geometerplus/android/fbreader/libraryService/BookCollectionShadow.java
+++ b/src/org/geometerplus/android/fbreader/libraryService/BookCollectionShadow.java
@@ -147,7 +147,29 @@ public class BookCollectionShadow extends AbstractBookCollection implements Serv
}
}
- public synchronized List books(String pattern) {
+ public synchronized List booksForSeries(String series) {
+ if (myInterface == null) {
+ return Collections.emptyList();
+ }
+ try {
+ return SerializerUtil.deserializeBookList(myInterface.booksForSeries(series));
+ } catch (RemoteException e) {
+ return Collections.emptyList();
+ }
+ }
+
+ public synchronized List booksForTitlePrefix(String prefix) {
+ if (myInterface == null) {
+ return Collections.emptyList();
+ }
+ try {
+ return SerializerUtil.deserializeBookList(myInterface.booksForTitlePrefix(prefix));
+ } catch (RemoteException e) {
+ return Collections.emptyList();
+ }
+ }
+
+ public synchronized List booksForPattern(String pattern) {
if (myInterface == null) {
return Collections.emptyList();
}
@@ -245,16 +267,25 @@ public class BookCollectionShadow extends AbstractBookCollection implements Serv
}
}
+ public synchronized boolean hasSeries() {
+ if (myInterface != null) {
+ try {
+ return myInterface.hasSeries();
+ } catch (RemoteException e) {
+ }
+ }
+ return false;
+ }
+
public synchronized List series() {
if (myInterface == null) {
return Collections.emptyList();
}
- //try {
- // TODO: implement
+ try {
+ return myInterface.series();
+ } catch (RemoteException e) {
return Collections.emptyList();
- //} catch (RemoteException e) {
- // return Collections.emptyList();
- //}
+ }
}
public synchronized boolean saveBook(Book book, boolean force) {
diff --git a/src/org/geometerplus/android/fbreader/libraryService/LibraryInterface.aidl b/src/org/geometerplus/android/fbreader/libraryService/LibraryInterface.aidl
index 01510d32f..a3977d494 100644
--- a/src/org/geometerplus/android/fbreader/libraryService/LibraryInterface.aidl
+++ b/src/org/geometerplus/android/fbreader/libraryService/LibraryInterface.aidl
@@ -12,6 +12,8 @@ interface LibraryInterface {
List books();
List booksForAuthor(in String author);
List booksForTag(in String tag);
+ List booksForSeries(in String series);
+ List booksForTitlePrefix(in String prefix);
List booksForPattern(in String pattern);
List recentBooks();
List favorites();
@@ -20,6 +22,7 @@ interface LibraryInterface {
String getRecentBook(in int index);
List authors();
+ boolean hasSeries();
List series();
List tags();
diff --git a/src/org/geometerplus/android/fbreader/libraryService/LibraryService.java b/src/org/geometerplus/android/fbreader/libraryService/LibraryService.java
index a95be3551..fed6ddb24 100644
--- a/src/org/geometerplus/android/fbreader/libraryService/LibraryService.java
+++ b/src/org/geometerplus/android/fbreader/libraryService/LibraryService.java
@@ -132,8 +132,16 @@ public class LibraryService extends Service {
return SerializerUtil.serializeBookList(myCollection.books(Util.stringToTag(tag)));
}
+ public List booksForSeries(String series) {
+ return SerializerUtil.serializeBookList(myCollection.booksForSeries(series));
+ }
+
+ public List booksForTitlePrefix(String prefix) {
+ return SerializerUtil.serializeBookList(myCollection.booksForTitlePrefix(prefix));
+ }
+
public List booksForPattern(String pattern) {
- return SerializerUtil.serializeBookList(myCollection.books(pattern));
+ return SerializerUtil.serializeBookList(myCollection.booksForPattern(pattern));
}
public List recentBooks() {
@@ -165,6 +173,10 @@ public class LibraryService extends Service {
return strings;
}
+ public boolean hasSeries() {
+ return myCollection.hasSeries();
+ }
+
public List series() {
return myCollection.series();
}
diff --git a/src/org/geometerplus/fbreader/book/BookCollection.java b/src/org/geometerplus/fbreader/book/BookCollection.java
index 3d9e507fa..78ff0e2e8 100644
--- a/src/org/geometerplus/fbreader/book/BookCollection.java
+++ b/src/org/geometerplus/fbreader/book/BookCollection.java
@@ -222,7 +222,26 @@ public class BookCollection extends AbstractBookCollection {
return filtered;
}
- public List books(String pattern) {
+ public List booksForSeries(String series) {
+ final LinkedList filtered = new LinkedList();
+ for (Book b : books()) {
+ final SeriesInfo info = b.getSeriesInfo();
+ if (info != null && series.equals(info.Title)) {
+ filtered.add(b);
+ }
+ }
+ return filtered;
+ }
+
+ public List booksForTitlePrefix(String prefix) {
+ final LinkedList filtered = new LinkedList();
+ for (Book b : books()) {
+ // TODO: implement
+ }
+ return filtered;
+ }
+
+ public List booksForPattern(String pattern) {
if (pattern == null || pattern.length() == 0) {
return Collections.emptyList();
}
@@ -289,6 +308,17 @@ public class BookCollection extends AbstractBookCollection {
return new ArrayList(tags);
}
+ public boolean hasSeries() {
+ synchronized (myBooksByFile) {
+ for (Book book : myBooksByFile.values()) {
+ if (book.getSeriesInfo() != null) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
public List series() {
final Set series = new TreeSet();
synchronized (myBooksByFile) {
diff --git a/src/org/geometerplus/fbreader/book/IBookCollection.java b/src/org/geometerplus/fbreader/book/IBookCollection.java
index 782040f7a..b4b57479d 100644
--- a/src/org/geometerplus/fbreader/book/IBookCollection.java
+++ b/src/org/geometerplus/fbreader/book/IBookCollection.java
@@ -46,26 +46,30 @@ public interface IBookCollection {
List books();
List books(Author author);
List books(Tag tag);
- List books(String pattern);
- List recentBooks();
+ List booksForSeries(String series);
+ List booksForTitlePrefix(String prefix);
+ List booksForPattern(String pattern);
+
List favorites();
+ boolean hasFavorites();
+ boolean isFavorite(Book book);
+ void setBookFavorite(Book book, boolean favorite);
+
+ List recentBooks();
+ Book getRecentBook(int index);
+ void addBookToRecentList(Book book);
+
Book getBookByFile(ZLFile file);
Book getBookById(long id);
- Book getRecentBook(int index);
List authors();
List tags();
+ boolean hasSeries();
List series();
boolean saveBook(Book book, boolean force);
void removeBook(Book book, boolean deleteFromDisk);
- void addBookToRecentList(Book book);
-
- boolean hasFavorites();
- boolean isFavorite(Book book);
- void setBookFavorite(Book book, boolean favorite);
-
ZLTextPosition getStoredPosition(long bookId);
void storePosition(long bookId, ZLTextPosition position);
diff --git a/src/org/geometerplus/fbreader/library/AuthorTree.java b/src/org/geometerplus/fbreader/library/AuthorTree.java
index ae3787b72..7cfffba6c 100644
--- a/src/org/geometerplus/fbreader/library/AuthorTree.java
+++ b/src/org/geometerplus/fbreader/library/AuthorTree.java
@@ -97,6 +97,16 @@ public class AuthorTree extends LibraryTree {
}
}
+ private SeriesTree getSeriesSubTree(String series) {
+ final SeriesTree temp = new SeriesTree(Collection, series);
+ int position = Collections.binarySearch(subTrees(), temp);
+ if (position >= 0) {
+ return (SeriesTree)subTrees().get(position);
+ } else {
+ return new SeriesTree(this, series, - position - 1);
+ }
+ }
+
private boolean createBookSubTree(Book book) {
final SeriesInfo seriesInfo = book.getSeriesInfo();
if (seriesInfo != null) {
diff --git a/src/org/geometerplus/fbreader/library/Library.java b/src/org/geometerplus/fbreader/library/Library.java
index c1809ac4f..8a83a9deb 100644
--- a/src/org/geometerplus/fbreader/library/Library.java
+++ b/src/org/geometerplus/fbreader/library/Library.java
@@ -96,6 +96,7 @@ public final class Library {
new RecentBooksTree(myRootTree);
new AuthorListTree(myRootTree);
new FirstLevelTree(myRootTree, LibraryTree.ROOT_BY_TITLE);
+ new SeriesListTree(myRootTree);
new TagListTree(myRootTree);
new FileFirstLevelTree(myRootTree);
}
@@ -176,20 +177,6 @@ public final class Library {
myBooks.put(book.getId(), book);
}
- final SeriesInfo seriesInfo = book.getSeriesInfo();
-
- if (seriesInfo != null) {
- FirstLevelTree seriesRoot = getFirstLevelTree(LibraryTree.ROOT_BY_SERIES);
- if (seriesRoot == null) {
- seriesRoot = new FirstLevelTree(
- myRootTree,
- myRootTree.indexOf(getFirstLevelTree(LibraryTree.ROOT_BY_TITLE)) + 1,
- LibraryTree.ROOT_BY_SERIES
- );
- }
- seriesRoot.getSeriesSubTree(seriesInfo.Title).createBookInSeriesSubTree(book);
- }
-
if (myDoGroupTitlesByFirstLetter) {
final String letter = TitleTree.firstTitleLetter(book);
if (letter != null) {
@@ -225,7 +212,6 @@ public final class Library {
myBooks.remove(book.getId());
removeFromTree(LibraryTree.ROOT_FOUND, book);
removeFromTree(LibraryTree.ROOT_BY_TITLE, book);
- removeFromTree(LibraryTree.ROOT_BY_SERIES, book);
addBookToLibrary(book);
fireModelChangedEvent(ChangeListener.Code.BookAdded);
}
@@ -265,7 +251,7 @@ public final class Library {
FirstLevelTree newSearchResults = null;
synchronized (this) {
- for (Book book : Collection.books(pattern)) {
+ for (Book book : Collection.booksForPattern(pattern)) {
if (newSearchResults == null) {
if (oldSearchResults != null) {
oldSearchResults.removeSelf();
diff --git a/src/org/geometerplus/fbreader/library/LibraryTree.java b/src/org/geometerplus/fbreader/library/LibraryTree.java
index 4108348a3..ceb60fbaf 100644
--- a/src/org/geometerplus/fbreader/library/LibraryTree.java
+++ b/src/org/geometerplus/fbreader/library/LibraryTree.java
@@ -95,16 +95,6 @@ public abstract class LibraryTree extends FBTree {
}
}
- SeriesTree getSeriesSubTree(String series) {
- final SeriesTree temp = new SeriesTree(Collection, series);
- int position = Collections.binarySearch(subTrees(), temp);
- if (position >= 0) {
- return (SeriesTree)subTrees().get(position);
- } else {
- return new SeriesTree(this, series, - position - 1);
- }
- }
-
public boolean removeBook(Book book) {
final LinkedList toRemove = new LinkedList();
for (FBTree tree : this) {
diff --git a/src/org/geometerplus/fbreader/library/SeriesListTree.java b/src/org/geometerplus/fbreader/library/SeriesListTree.java
new file mode 100644
index 000000000..cc267f8bc
--- /dev/null
+++ b/src/org/geometerplus/fbreader/library/SeriesListTree.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2009-2013 Geometer Plus
+ *
+ * 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.library;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.geometerplus.fbreader.book.*;
+
+public class SeriesListTree extends FirstLevelTree {
+ SeriesListTree(RootTree root) {
+ super(root, ROOT_BY_SERIES);
+ }
+
+ @Override
+ public Status getOpeningStatus() {
+ if (!Collection.hasSeries()) {
+ return Status.CANNOT_OPEN;
+ }
+ return Status.ALWAYS_RELOAD_BEFORE_OPENING;
+ }
+
+ @Override
+ public String getOpeningStatusMessage() {
+ return getOpeningStatus() == Status.CANNOT_OPEN
+ ? "noSeries" : super.getOpeningStatusMessage();
+ }
+
+ @Override
+ public void waitForOpening() {
+ clear();
+ for (String s : Collection.series()) {
+ createSeriesSubTree(s);
+ }
+ }
+
+ @Override
+ public boolean onBookEvent(BookEvent event, Book book) {
+ switch (event) {
+ case Added:
+ {
+ final SeriesInfo info = book.getSeriesInfo();
+ return info != null && createSeriesSubTree(info.Title);
+ }
+ case Removed:
+ // TODO: implement
+ return false;
+ default:
+ case Updated:
+ // TODO: implement
+ return false;
+ }
+ }
+
+ private boolean createSeriesSubTree(String series) {
+ final SeriesTree temp = new SeriesTree(Collection, series);
+ int position = Collections.binarySearch(subTrees(), temp);
+ if (position >= 0) {
+ return false;
+ } else {
+ new SeriesTree(this, series, - position - 1);
+ return true;
+ }
+ }
+}
diff --git a/src/org/geometerplus/fbreader/library/SeriesTree.java b/src/org/geometerplus/fbreader/library/SeriesTree.java
index 3b7bf3995..f19b02e84 100644
--- a/src/org/geometerplus/fbreader/library/SeriesTree.java
+++ b/src/org/geometerplus/fbreader/library/SeriesTree.java
@@ -46,17 +46,6 @@ public final class SeriesTree extends LibraryTree {
return "@SeriesTree " + getName();
}
- boolean createBookInSeriesSubTree(Book book) {
- final BookInSeriesTree temp = new BookInSeriesTree(Collection, book);
- int position = Collections.binarySearch(subTrees(), temp);
- if (position >= 0) {
- return false;
- } else {
- new BookInSeriesTree(this, book, - position - 1);
- return true;
- }
- }
-
@Override
public boolean containsBook(Book book) {
if (book == null) {
@@ -70,4 +59,42 @@ public final class SeriesTree extends LibraryTree {
protected String getSortKey() {
return " Series:" + super.getSortKey();
}
+
+ @Override
+ public Status getOpeningStatus() {
+ return Status.ALWAYS_RELOAD_BEFORE_OPENING;
+ }
+
+ @Override
+ public void waitForOpening() {
+ clear();
+ for (Book book : Collection.booksForSeries(Series)) {
+ createBookInSeriesSubTree(book);
+ }
+ }
+
+ @Override
+ public boolean onBookEvent(BookEvent event, Book book) {
+ switch (event) {
+ case Added:
+ return containsBook(book) && createBookInSeriesSubTree(book);
+ case Removed:
+ // TODO: implement
+ case Updated:
+ // TODO: implement
+ default:
+ return super.onBookEvent(event, book);
+ }
+ }
+
+ boolean createBookInSeriesSubTree(Book book) {
+ final BookInSeriesTree temp = new BookInSeriesTree(Collection, book);
+ int position = Collections.binarySearch(subTrees(), temp);
+ if (position >= 0) {
+ return false;
+ } else {
+ new BookInSeriesTree(this, book, - position - 1);
+ return true;
+ }
+ }
}