diff options
author | Michele Calgaro <[email protected]> | 2024-05-11 21:28:48 +0900 |
---|---|---|
committer | Michele Calgaro <[email protected]> | 2024-05-11 21:28:48 +0900 |
commit | 2462d03f322261bd616721c2b2065c4004b36c9c (patch) | |
tree | 239947a0737bb8386703a1497f12c09aebd3080a /fbreader/src/migration | |
download | tde-ebook-reader-2462d03f322261bd616721c2b2065c4004b36c9c.tar.gz tde-ebook-reader-2462d03f322261bd616721c2b2065c4004b36c9c.zip |
Initial import (as is) from Debian Snapshot's 'fbreader' source code (https://snapshot.debian.org/package/fbreader/0.99.4%2Bdfsg-6).
The Debian code is provided under GPL2 license.
Signed-off-by: Michele Calgaro <[email protected]>
Diffstat (limited to 'fbreader/src/migration')
19 files changed, 1758 insertions, 0 deletions
diff --git a/fbreader/src/migration/BookInfo.cpp b/fbreader/src/migration/BookInfo.cpp new file mode 100644 index 0000000..5a13647 --- /dev/null +++ b/fbreader/src/migration/BookInfo.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus <[email protected]> + * + * 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. + */ + +#include "BookInfo.h" + +#include "../options/FBCategoryKey.h" + +static const std::string EMPTY = ""; + +BookInfo::BookInfo(const std::string &fileName) : + AuthorDisplayNameOption(FBCategoryKey::BOOKS, fileName, "AuthorDisplayName", EMPTY), + AuthorSortKeyOption(FBCategoryKey::BOOKS, fileName, "AuthorSortKey", EMPTY), + TitleOption(FBCategoryKey::BOOKS, fileName, "Title", EMPTY), + SeriesTitleOption(FBCategoryKey::BOOKS, fileName, "Sequence", EMPTY), + IndexInSeriesOption(FBCategoryKey::BOOKS, fileName, "Series Number in Sequence", EMPTY), + LanguageOption(FBCategoryKey::BOOKS, fileName, "Language", EMPTY), + EncodingOption(FBCategoryKey::BOOKS, fileName, "Encoding", EMPTY), + TagsOption(FBCategoryKey::BOOKS, fileName, "TagList", EMPTY) { +} + +void BookInfo::reset() { + AuthorDisplayNameOption.setValue(EMPTY); + AuthorSortKeyOption.setValue(EMPTY); + TitleOption.setValue(EMPTY); + SeriesTitleOption.setValue(EMPTY); + IndexInSeriesOption.setValue(EMPTY); + LanguageOption.setValue(EMPTY); + EncodingOption.setValue(EMPTY); + TagsOption.setValue(EMPTY); +} + +bool BookInfo::isFull() const { + return + !AuthorDisplayNameOption.value().empty() && + !AuthorSortKeyOption.value().empty() && + !TitleOption.value().empty() && + !EncodingOption.value().empty(); +} + +const BookInfo &BookInfo::operator = (const BookInfo &bi) { + AuthorDisplayNameOption.setValue(bi.AuthorDisplayNameOption.value()); + AuthorSortKeyOption.setValue(bi.AuthorSortKeyOption.value()); + TitleOption.setValue(bi.TitleOption.value()); + SeriesTitleOption.setValue(bi.SeriesTitleOption.value()); + IndexInSeriesOption.setValue(bi.IndexInSeriesOption.value()); + LanguageOption.setValue(bi.LanguageOption.value()); + EncodingOption.setValue(bi.EncodingOption.value()); + TagsOption.setValue(bi.TagsOption.value()); + return bi; +} diff --git a/fbreader/src/migration/BookInfo.h b/fbreader/src/migration/BookInfo.h new file mode 100644 index 0000000..997e9ea --- /dev/null +++ b/fbreader/src/migration/BookInfo.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus <[email protected]> + * + * 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. + */ + +#ifndef __BOOKINFO_H__ +#define __BOOKINFO_H__ + +#include <string> + +#include <ZLOptions.h> + + +struct BookInfo { + BookInfo(const std::string &fileName); + ~BookInfo(); + + bool isFull() const; + void reset(); + + ZLStringOption AuthorDisplayNameOption; + ZLStringOption AuthorSortKeyOption; + ZLStringOption TitleOption; + ZLStringOption SeriesTitleOption; + ZLStringOption IndexInSeriesOption; + ZLStringOption LanguageOption; + ZLStringOption EncodingOption; + ZLStringOption TagsOption; + + const BookInfo &operator = (const BookInfo &bi); +}; + +inline BookInfo::~BookInfo() {} + +#endif /* __BOOKINFO_H__ */ diff --git a/fbreader/src/migration/FB2MigrationReader.cpp b/fbreader/src/migration/FB2MigrationReader.cpp new file mode 100644 index 0000000..875c0a5 --- /dev/null +++ b/fbreader/src/migration/FB2MigrationReader.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus <[email protected]> + * + * 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. + */ + +#include <cstdlib> + +#include <ZLInputStream.h> +#include <ZLUnicodeUtil.h> + +#include "FB2MigrationReader.h" +#include "../formats/fb2/FB2TagManager.h" + +FB2MigrationReader::FB2MigrationReader(BookInfo &info, bool updateSeries) : myInfo(info), myUpdateSeries(updateSeries), myUpdateTags(info.TagsOption.value().empty()) { +} + +void FB2MigrationReader::characterDataHandler(const char *text, std::size_t len) { + if (myReadState == READ_GENRE) { + myGenreBuffer.append(text, len); + } +} + +void FB2MigrationReader::startElementHandler(int tag, const char **attributes) { + switch (tag) { + case _BODY: + interrupt(); + break; + case _TITLE_INFO: + myReadState = READ_SOMETHING; + break; + case _GENRE: + if ((myReadState == READ_SOMETHING) && myUpdateTags) { + myReadState = READ_GENRE; + } + break; + case _SEQUENCE: + if ((myReadState == READ_SOMETHING) && myUpdateSeries) { + const char *name = attributeValue(attributes, "name"); + if (name != 0) { + std::string seriesTitle = name; + ZLUnicodeUtil::utf8Trim(seriesTitle); + myInfo.SeriesTitleOption.setValue(seriesTitle); + const char *number = attributeValue(attributes, "number"); + myInfo.IndexInSeriesOption.setValue((number != 0) ? std::string(number) : std::string()); + } + } + break; + default: + break; + } +} + +void FB2MigrationReader::endElementHandler(int tag) { + switch (tag) { + case _TITLE_INFO: + myReadState = READ_NOTHING; + break; + case _GENRE: + if (myReadState == READ_GENRE) { + ZLUnicodeUtil::utf8Trim(myGenreBuffer); + if (!myGenreBuffer.empty()) { + const std::vector<std::string> &tags = + FB2TagManager::Instance().humanReadableTags(myGenreBuffer); + if (!tags.empty()) { + myTags.insert(tags.begin(), tags.end()); + } else { + myTags.insert(myGenreBuffer); + } + myGenreBuffer.erase(); + } + myReadState = READ_SOMETHING; + } + break; + default: + break; + } +} + +void FB2MigrationReader::doRead(const ZLFile &file) { + myReadState = READ_NOTHING; + readDocument(file); + if (myUpdateTags) { + std::string tagList; + for (std::set<std::string>::const_iterator it = myTags.begin(); it != myTags.end(); ++it) { + if (it != myTags.begin()) { + tagList += ","; + } + tagList += *it; + } + myInfo.TagsOption.setValue(tagList); + } +} diff --git a/fbreader/src/migration/FB2MigrationReader.h b/fbreader/src/migration/FB2MigrationReader.h new file mode 100644 index 0000000..d8e7dd2 --- /dev/null +++ b/fbreader/src/migration/FB2MigrationReader.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus <[email protected]> + * + * 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. + */ + +#ifndef __FB2MIGRATIONREADER_H__ +#define __FB2MIGRATIONREADER_H__ + +#include <set> +#include <string> + +#include "../formats/fb2/FB2Reader.h" + +#include "BookInfo.h" + +class FB2MigrationReader : public FB2Reader { + +public: + FB2MigrationReader(BookInfo &info, bool updateSeries); + + void doRead(const ZLFile &file); + + void startElementHandler(int tag, const char **attributes); + void endElementHandler(int tag); + void characterDataHandler(const char *text, std::size_t len); + +private: + BookInfo &myInfo; + + enum { + READ_NOTHING, + READ_SOMETHING, + READ_GENRE + } myReadState; + + bool myUpdateSeries; + bool myUpdateTags; + + std::string myGenreBuffer; + std::set<std::string> myTags; +}; + +#endif /* __FB2MIGRATIONREADER_H__ */ diff --git a/fbreader/src/migration/HtmlDCTagsReader.cpp b/fbreader/src/migration/HtmlDCTagsReader.cpp new file mode 100644 index 0000000..4929686 --- /dev/null +++ b/fbreader/src/migration/HtmlDCTagsReader.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus <[email protected]> + * + * 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. + */ + +#include <ZLStringUtil.h> + +#include "HtmlDCTagsReader.h" + +HtmlDCTagsReader::HtmlDCTagsReader(BookInfo &info) : HtmlReader(info.EncodingOption.value()), myInfo(info) { +} + +bool HtmlDCTagsReader::tagHandler(const HtmlReader::HtmlTag &tag) { + if (tag.Name == "BODY") { + return false; + } else if (tag.Name == "DC:SUBJECT") { + myReadTag = tag.Start; + ZLStringUtil::stripWhiteSpaces(myBuffer); + if (!tag.Start && !myBuffer.empty()) { + if (!myTagList.empty()) { + myTagList += ","; + } + myTagList += myBuffer; + myBuffer.erase(); + } + } + return true; +} + +void HtmlDCTagsReader::startDocumentHandler() { + myReadTag = false; +} + +void HtmlDCTagsReader::endDocumentHandler() { + myInfo.TagsOption.setValue(myTagList); +} + +bool HtmlDCTagsReader::characterDataHandler(const char *text, std::size_t len, bool convert) { + if (myReadTag) { + if (convert) { + myConverter->convert(myBuffer, text, text + len); + } else { + myBuffer.append(text, len); + } + } + return true; +} diff --git a/fbreader/src/migration/HtmlDCTagsReader.h b/fbreader/src/migration/HtmlDCTagsReader.h new file mode 100644 index 0000000..5cd7f9a --- /dev/null +++ b/fbreader/src/migration/HtmlDCTagsReader.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus <[email protected]> + * + * 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. + */ + +#ifndef __HTMLDCTAGSREADER_H__ +#define __HTMLDCTAGSREADER_H__ + +#include "../formats/html/HtmlReader.h" +#include "BookInfo.h" + +class HtmlDCTagsReader : public HtmlReader { + +public: + HtmlDCTagsReader(BookInfo &info); + +private: + void startDocumentHandler(); + void endDocumentHandler(); + + bool tagHandler(const HtmlTag &tag); + bool characterDataHandler(const char *text, std::size_t len, bool convert); + +private: + BookInfo &myInfo; + + bool myReadTag; + + std::string myBuffer; + std::string myTagList; +}; + +#endif /* __HTMLDCTAGSREADER_H__ */ diff --git a/fbreader/src/migration/Migration.cpp b/fbreader/src/migration/Migration.cpp new file mode 100644 index 0000000..172209d --- /dev/null +++ b/fbreader/src/migration/Migration.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2008-2012 Geometer Plus <[email protected]> + * + * 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. + */ + +#include <cstdlib> + +#include <ZLStringUtil.h> + +#include "../options/FBCategoryKey.h" + +#include "Migration.h" + +void Migration::moveOption( + const ZLCategoryKey &oldCategory, const std::string &oldGroup, const std::string &oldName, + const ZLCategoryKey &newCategory, const std::string &newGroup, const std::string &newName, + const std::string &defaultValue +) { + ZLStringOption newOption(newCategory, newGroup, newName, defaultValue); + const std::string newValue = newOption.value(); + ZLStringOption oldOption(oldCategory, oldGroup, oldName, newValue); + const std::string oldValue = oldOption.value(); + if (newValue != oldValue) { + newOption.setValue(oldValue); + oldOption.setValue(newValue); + } +} + +bool Migration::isLikeToFileName(const std::string &str) { + return + ZLStringUtil::stringStartsWith(str, "/") || + ZLStringUtil::stringStartsWith(str, "\\\\") || + ((str.length() > 2) && (str.substr(1, 2) == ":\\")); +} + +Migration::Migration(const std::string &version) : myVersion(version) { +} + +Migration::~Migration() { +} + +int Migration::extractVersionInformation(const std::string &name) { + int major = std::atoi(name.c_str()); + int minor = 0; + int point = 0; + int index = name.find('.'); + if (index > 0) { + minor = std::atoi(name.c_str() + index + 1); + index = name.find('.', index + 1); + if (index > 0) { + point = std::atoi(name.c_str() + index + 1); + } + } + return 10000 * major + 100 * minor + point; +} + +void Migration::doMigration() { + ZLStringOption versionOption(FBCategoryKey::SYSTEM, "Version", "FBReaderVersion", "0"); + if (extractVersionInformation(versionOption.value()) < + extractVersionInformation(myVersion)) { + doMigrationInternal(); + } +} diff --git a/fbreader/src/migration/Migration.h b/fbreader/src/migration/Migration.h new file mode 100644 index 0000000..507da79 --- /dev/null +++ b/fbreader/src/migration/Migration.h @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2008-2012 Geometer Plus <[email protected]> + * + * 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. + */ + +#ifndef __MIGRATION_H__ +#define __MIGRATION_H__ + +#include <string> +#include <map> + +#include <shared_ptr.h> +#include <ZLOptions.h> + +class Migration { + +public: + static int extractVersionInformation(const std::string &name); + +protected: + static void moveOption( + const ZLCategoryKey &oldCategory, const std::string &oldGroup, const std::string &oldName, + const ZLCategoryKey &newCategory, const std::string &newGroup, const std::string &newName, + const std::string &defaultValue + ); + static bool isLikeToFileName(const std::string &str); + +public: + Migration(const std::string &version); + virtual ~Migration(); + void doMigration(); + +protected: + virtual void doMigrationInternal() = 0; + +private: + const std::string myVersion; + +friend class Migration_0_11_0_Runnable; +}; + +class Migration_0_8_11 : public Migration { + +public: + Migration_0_8_11(); + +protected: + void doMigrationInternal(); +}; + +class Migration_0_8_13 : public Migration { + +public: + Migration_0_8_13(); + +protected: + void doMigrationInternal(); +}; + +class Migration_0_8_16 : public Migration { + +public: + Migration_0_8_16(); + +protected: + void doMigrationInternal(); +}; + +class Migration_0_10_4 : public Migration { + +public: + Migration_0_10_4(); + +protected: + void doMigrationInternal(); +}; + +class Migration_0_11_0 : public Migration { + +public: + Migration_0_11_0(); + +protected: + void doMigrationInternal(); +}; + +class Migration_0_99_0 : public Migration { + +public: + Migration_0_99_0(); + +protected: + void doMigrationInternal(); +}; + +class Migration_0_99_1 : public Migration { + +public: + Migration_0_99_1(); + +protected: + void doMigrationInternal(); +}; + +#endif /* __MIGRATION_H__ */ diff --git a/fbreader/src/migration/Migration_0_10_4.cpp b/fbreader/src/migration/Migration_0_10_4.cpp new file mode 100644 index 0000000..b4cedbf --- /dev/null +++ b/fbreader/src/migration/Migration_0_10_4.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2009-2012 Geometer Plus <[email protected]> + * + * 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. + */ + +#include <vector> + +#include <ZLStringUtil.h> +#include <ZLUnicodeUtil.h> + +#include "Migration.h" +#include "../options/FBCategoryKey.h" + +Migration_0_10_4::Migration_0_10_4() : Migration("0.10.4") { +} + +void Migration_0_10_4::doMigrationInternal() { + std::vector<std::string> groups; + ZLOption::listOptionGroups(groups); + for (std::vector<std::string>::const_iterator it = groups.begin(); it != groups.end(); ++it) { + static const std::string zipPostfix = ".zip"; + static const std::string sizeName = "Size"; + if (ZLStringUtil::stringEndsWith(ZLUnicodeUtil::toLower(*it), zipPostfix)) { + ZLIntegerOption option(FBCategoryKey::BOOKS, *it, sizeName, -1); + option.setValue(-1); + } + } +} diff --git a/fbreader/src/migration/Migration_0_11_0.cpp b/fbreader/src/migration/Migration_0_11_0.cpp new file mode 100644 index 0000000..144245e --- /dev/null +++ b/fbreader/src/migration/Migration_0_11_0.cpp @@ -0,0 +1,544 @@ +/* + * Copyright (C) 2009-2012 Geometer Plus <[email protected]> + * + * 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. + */ + +#include <iostream> +#include <iomanip> +#include <ZLTime.h> + +#include <vector> +#include <algorithm> + +#include <ZLFile.h> +#include <ZLStringUtil.h> +#include <ZLUnicodeUtil.h> + +#include "BookInfo.h" +#include "Migration.h" +#include "../options/FBCategoryKey.h" + +#include "../formats/FormatPlugin.h" + +#include "../database/booksdb/BooksDBUtil.h" +#include "../database/booksdb/BooksDB.h" +#include "../library/Book.h" +#include "../library/Tag.h" + +static const std::string BOOK_LIST_GROUP = "BookList"; +static const std::string BOOK_LIST_SIZE = "Size"; +static const std::string BOOK_LIST_PREFIX = "Book"; + +static const std::string CURRENT_STATE_GROUP = "State"; + +static const std::string RECENT_BOOKS_GROUP = "LastOpenedBooks"; +static const std::string BOOK = "Book"; +static const std::size_t MaxXmlListSize = 10; + +static const std::string PARAGRAPH_OPTION_NAME = "Paragraph"; +static const std::string WORD_OPTION_NAME = "Word"; +static const std::string CHAR_OPTION_NAME = "Char"; +static const std::string POSITION_IN_BUFFER = "PositionInBuffer"; +static const std::string BUFFER_SIZE = "UndoBufferSize"; +static const char * const BUFFER_PARAGRAPH_PREFIX = "Paragraph_"; +static const char * const BUFFER_WORD_PREFIX = "Word_"; +static const int MaxXmlStackSize = 20; + +static const std::string SIZE = "Size"; +static const std::string ENTRIES_NUMBER = "EntriesNumber"; +static const std::string PALM_TYPE = "PalmType"; + +static const std::string NET_FILES_GROUP = "Files"; + +class Migration_0_11_0_Runnable : public DBRunnable { + +public: + bool run(); + +private: + bool migrateBooks(); + bool migrateBookList(); + bool migrateState(); + bool migrateNetwork(); + + bool migrateBook(const ZLFile &file); + + std::string tags2string(const TagList &tags); + + bool stringEquals(const std::string &tags1, const std::string &tags2); + + bool migrateRecentBooks(); + + bool migrateBooksState(); + + bool migrateBookStateStack(const std::string &fileName, const Book &book); + bool migrateBookLastState(const std::string &fileName, const Book &book); + + bool shouldReadDisk(const std::string &fileName); + + bool clearBooksOptions(); + + static void moveOption(const ZLCategoryKey &category, const std::string &oldGroup, const std::string &newGroup, const std::string &name, const std::string &defaultValue); + static void moveOption(const ZLCategoryKey &category, const std::string &oldGroup, const std::string &newGroup, const std::string &name, int defaultValue); + static void movePercentGroups(std::vector<std::string> &optionGroups); + static void moveBookGroup(const std::string &oldgroup, const std::string &newgroup); + +private: + std::map<std::string, shared_ptr<Book> > myBooks; +}; + + +inline bool Migration_0_11_0_Runnable::shouldReadDisk(const std::string &fileName) { + const std::string ext = ZLFile(fileName).extension(); + return ext == "fb2" || ext == "epub" || ext == "mobi" || ext == "oebzip" || ext == "opf"; + //return ext == "fb2"; + //return true; +} + + +void Migration_0_11_0_Runnable::moveOption(const ZLCategoryKey &category, const std::string &oldGroup, const std::string &newGroup, const std::string &name, const std::string &defaultValue) { + ZLStringOption newOption(category, newGroup, name, defaultValue); + ZLStringOption oldOption(category, oldGroup, name, defaultValue); + newOption.setValue(oldOption.value()); + oldOption.setValue(defaultValue); +} + +void Migration_0_11_0_Runnable::moveOption(const ZLCategoryKey &category, const std::string &oldGroup, const std::string &newGroup, const std::string &name, int defaultValue) { + ZLIntegerOption newOption(category, newGroup, name, defaultValue); + ZLIntegerOption oldOption(category, oldGroup, name, defaultValue); + newOption.setValue(oldOption.value()); + oldOption.setValue(defaultValue); +} + +static bool percentPathPredicate(const std::string &path) { + static const std::string _start = "%APPLICATION_PATH%"; + return ZLStringUtil::stringStartsWith(path, _start); +} + +void Migration_0_11_0_Runnable::movePercentGroups(std::vector<std::string> &optionGroups) { + std::vector<std::string>::iterator it = optionGroups.begin(); + while ((it = std::find_if(it, optionGroups.end(), percentPathPredicate)) != optionGroups.end()) { + const std::string oldgroup = *it; + const std::string newgroup = ZLFile(oldgroup).resolvedPath(); + if (std::find(optionGroups.begin(), optionGroups.end(), newgroup) == optionGroups.end()) { + moveBookGroup(oldgroup, newgroup); + *it++ = newgroup; + } else { + if (BookInfo(newgroup).TitleOption.value().empty()) { + moveBookGroup(oldgroup, newgroup); + } + it = optionGroups.erase(it); + } + ZLOption::clearGroup(oldgroup); + } +} + +void Migration_0_11_0_Runnable::moveBookGroup(const std::string &oldgroup, const std::string &newgroup) { + BookInfo oldbi(oldgroup); + BookInfo newbi(newgroup); + newbi = oldbi; + oldbi.reset(); + + moveOption(ZLCategoryKey::STATE, oldgroup, newgroup, PARAGRAPH_OPTION_NAME, 0); + moveOption(ZLCategoryKey::STATE, oldgroup, newgroup, WORD_OPTION_NAME, 0); + moveOption(ZLCategoryKey::STATE, oldgroup, newgroup, CHAR_OPTION_NAME, 0); + moveOption(ZLCategoryKey::STATE, oldgroup, newgroup, POSITION_IN_BUFFER, 0); + + int stackSize = ZLIntegerOption(ZLCategoryKey::STATE, oldgroup, BUFFER_SIZE, 0).value(); + for (int i = 0; i < stackSize; ++i) { + std::string bufferParagraph = BUFFER_PARAGRAPH_PREFIX; + std::string bufferWord = BUFFER_WORD_PREFIX; + ZLStringUtil::appendNumber(bufferParagraph, i); + ZLStringUtil::appendNumber(bufferWord, i); + moveOption(ZLCategoryKey::STATE, oldgroup, newgroup, bufferParagraph, -1); + moveOption(ZLCategoryKey::STATE, oldgroup, newgroup, bufferWord, -1); + } + moveOption(ZLCategoryKey::STATE, oldgroup, newgroup, BUFFER_SIZE, 0); +} + + + +Migration_0_11_0::Migration_0_11_0() : Migration("0.11.0") { +} + +void Migration_0_11_0::doMigrationInternal() { + Migration_0_11_0_Runnable r; + BooksDB::Instance().executeAsTransaction(r); + //r.run(); +} + +bool Migration_0_11_0_Runnable::run() { +const ZLTime start; + if (!migrateBooks()) { + std::cerr << std::endl << "VERDICT: migrateBooks failed" << std::endl << std::endl; + } +std::cerr << "migration total 0: " << ZLTime().millisecondsFrom(start) << "ms" << std::endl; + if (!migrateBookList()) { + std::cerr << std::endl << "VERDICT: migrateBookList failed" << std::endl << std::endl; + } +std::cerr << "migration total 1: " << ZLTime().millisecondsFrom(start) << "ms" << std::endl; + if (!migrateState()) { + std::cerr << std::endl << "VERDICT: migrateState failed" << std::endl << std::endl; + } +std::cerr << "migration total 2: " << ZLTime().millisecondsFrom(start) << "ms" << std::endl; + if (!migrateNetwork()) { + std::cerr << std::endl << "VERDICT: migrateNetwork failed" << std::endl << std::endl; + } +std::cerr << "migration total 3: " << ZLTime().millisecondsFrom(start) << "ms" << std::endl; + if (!clearBooksOptions()) { + std::cerr << std::endl << "VERDICT: clearBooksOptions failed" << std::endl << std::endl; + } +std::cerr << "migration total 4: " << ZLTime().millisecondsFrom(start) << "ms" << std::endl; + return true; +} + + + +bool Migration_0_11_0_Runnable::migrateBooks() { + /*std::map<std::string, unsigned long> ext2time; + std::map<std::string, unsigned long> ext2num; + unsigned long totalTime = 0, totalNum = 0;*/ + + PluginCollection &collection = PluginCollection::Instance(); + std::vector<std::string> optionGroups; + ZLOption::listOptionGroups(optionGroups); + + movePercentGroups(optionGroups); + + bool res = true; + for (std::vector<std::string>::const_iterator it = optionGroups.begin(); it != optionGroups.end(); ++it) { + const std::string &name = *it; + if (Migration::isLikeToFileName(name)) { + /* TODO: check correctness of migration order: + * 1) palmType + * 2) size + * 3) book (depends on palmType and size) + */ + const std::string palmType = ZLStringOption(FBCategoryKey::BOOKS, name, PALM_TYPE, "").value(); + if (!palmType.empty()) { + BooksDB::Instance().setPalmType(name, palmType); + } + ZLStringOption(FBCategoryKey::BOOKS, name, PALM_TYPE, "").setValue(""); // clean books.xml + ZLFile file(name); + if (file.physicalFilePath() == name) { + int size = ZLIntegerOption(FBCategoryKey::BOOKS, name, SIZE, -1).value(); + if (size != -1) { + BooksDB::Instance().setFileSize(name, size); + } + } + if (collection.plugin(file, false) != 0) { + if (!BookInfo(name).TitleOption.value().empty()) { + //ZLTime start; + if (!migrateBook(ZLFile(name))) { + std::cerr << "ERROR(2): migrateBook failed" << std::endl; + res = false; + } + /*ZLTime end; + { + unsigned time = end.millisecondsFrom(start); + std::string ext = ZLFile(name).extension(); + totalTime += time; + totalNum += 1; + ext2time[ext] += time; + ext2num[ext] += 1; + }*/ + } + BookInfo(name).reset(); // clean books.xml + } else { + ZLOption::clearGroup(name); // clean books.xml + } + ZLIntegerOption(FBCategoryKey::BOOKS, name, SIZE, -1).setValue(-1); // clean books.xml + if (!ZLStringOption(FBCategoryKey::BOOKS, name, ENTRIES_NUMBER, "").value().empty()) { + ZLOption::clearGroup(name); // clean books.xml + } + } + } + + /*std::cerr << " ext" << " time,ms" << " time/total,%" << " number of books" << " time for 1 book,ms" << std::endl; + std::cerr << "---------------------------------------------------------------------------" << std::endl; + for (std::map<std::string, unsigned long>::const_iterator it = ext2time.begin(); it != ext2time.end(); ++it) { + const std::string &ext = it->first; + unsigned long time = it->second; + unsigned long num = ext2num[ext]; + std::cerr << std::setw(8) << ext << std::setw(10) << time << std::setw(15) << ((float) time) / totalTime * 100.0 + << std::setw(18) << num << std::setw(22) << ((float) time) / num << std::endl; + } + std::cerr << "---------------------------------------------------------------------------" << std::endl; + std::cerr << "total:" << std::endl; + std::cerr << std::setw(8) << "" << std::setw(10) << totalTime << std::setw(15) << "" + << std::setw(20) << totalNum << std::setw(20) << "" << std::endl;*/ + + return res; +} + + +bool Migration_0_11_0_Runnable::migrateBook(const ZLFile &file) { + shared_ptr<Book> infoBook = Book::loadFromBookInfo(file); + if (infoBook.isNull()) { + std::cerr << "ERROR: loading book from BookInfo failed: " << file.path() << std::endl; + return false; + } + if (shouldReadDisk(file.path()) && BooksDBUtil::isBookFull(*infoBook)) { + shared_ptr<Book> fileBook = Book::loadFromFile(file); + //shared_ptr<Book> fileBook = infoBook; + //shared_ptr<Book> fileBook; + if (!fileBook.isNull()) { + std::string tagList1 = tags2string(infoBook->tags()); + std::string tagList2 = tags2string(fileBook->tags()); + if (stringEquals(tagList1, tagList2)) { + infoBook->removeAllTags(); + const TagList &tList = fileBook->tags(); + for (TagList::const_iterator it = tList.begin(); it != tList.end(); ++it) { + infoBook->addTag(*it); + } + } + } + } + myBooks.insert(std::make_pair(file.path(), infoBook)); + const bool code = BooksDB::Instance().saveBook(infoBook); + if (!code) { + std::cerr << "ERROR: saving book to database failed: " << file.path() << std::endl; + } + return code; +} + +std::string Migration_0_11_0_Runnable::tags2string(const TagList &tags) { + std::string tagList; + TagList::const_iterator it = tags.begin(); + if (it != tags.end()) { + tagList += (*it++)->fullName(); + while (it != tags.end()) { + tagList += ','; + tagList += (*it++)->fullName(); + } + } + return tagList; +} + +bool Migration_0_11_0_Runnable::stringEquals(const std::string &tags1, const std::string &tags2) { + std::size_t i1 = 0; + std::size_t i2 = 0; + while (i1 < tags1.size() && i2 < tags2.size()) { + if (std::isspace(tags1[i1])) { + ++i1; + continue; + } + if (std::isspace(tags2[i2])) { + ++i2; + continue; + } + if (tags1[i1++] != tags2[i2++]) { + return false; + } + } + if (i1 == tags1.size() && i2 < tags2.size()) { + while (i2 < tags2.size()) { + if (!std::isspace(tags2[i2++])) { + return false; + } + } + return true; + } + if (i1 < tags1.size() && i2 == tags2.size()) { + while (i1 < tags1.size()) { + if (!std::isspace(tags1[i1++])) { + return false; + } + } + return true; + } + return true; +} + +bool Migration_0_11_0_Runnable::migrateBookList() { + bool res = true; + int size = ZLIntegerOption(ZLCategoryKey::STATE, BOOK_LIST_GROUP, BOOK_LIST_SIZE, 0).value(); + for (int i = 0; i < size; ++i) { + std::string optionName = BOOK_LIST_PREFIX; + ZLStringUtil::appendNumber(optionName, i); + const std::string &fileName = ZLStringOption(ZLCategoryKey::STATE, BOOK_LIST_GROUP, optionName, "").value(); + if (!fileName.empty()) { + std::map<std::string, shared_ptr<Book> >::iterator it = myBooks.find(fileName); + if (it != myBooks.end()) { + shared_ptr<Book> book = it->second; + if (!book.isNull() && book->bookId() != 0) { + if (!BooksDB::Instance().insertIntoBookList(*book)) { + std::cerr << "ERROR: insert into BookList failed: " << fileName << std::endl; + res = false; + } + } + } + } + } + ZLOption::clearGroup(BOOK_LIST_GROUP); // clean state.xml + return res; +} + +bool Migration_0_11_0_Runnable::migrateState() { + bool res = true; + if (!migrateRecentBooks()) { + std::cerr << "ERROR(2): migrateRecentBooks failed" << std::endl; + res = false; + } + if (!migrateBooksState()) { + std::cerr << "ERROR(2): migrateBooksState failed" << std::endl; + res = false; + } + ZLOption::clearGroup(RECENT_BOOKS_GROUP); // clean state.xml + ZLOption::clearGroup(CURRENT_STATE_GROUP); // clean state.xml + return res; +} + +bool Migration_0_11_0_Runnable::migrateRecentBooks() { + BookList books; + for (std::size_t i = 0; i < MaxXmlListSize; ++i) { + std::string num = BOOK; + ZLStringUtil::appendNumber(num, i); + std::string name = ZLStringOption(ZLCategoryKey::STATE, RECENT_BOOKS_GROUP, num, "").value(); + if (!name.empty()) { + //shared_ptr<Book> book = BooksDBUtil::getBook(name, false); + std::map<std::string, shared_ptr<Book> >::const_iterator it = myBooks.find(name); + if (it == myBooks.end()) { + if ((it = myBooks.find(ZLFile(name).resolvedPath())) == myBooks.end()) { + continue; + } + } + shared_ptr<Book> book = it->second; + if (!book.isNull() && book->bookId() != 0 && std::find(books.begin(), books.end(), book) == books.end()) { + books.push_back(book); + } + } + } + bool res = BooksDB::Instance().saveRecentBooks(books); + if (!res) { + std::cerr << "ERROR: saving recent books list failed (" << books.size() << " item[s])" << std::endl; + } + return res; +} + +bool Migration_0_11_0_Runnable::migrateBooksState() { + bool res = true; + + for (std::map<std::string, shared_ptr<Book> >::const_iterator it = myBooks.begin(); it != myBooks.end(); ++it) { + const std::string &fileName = it->first; + if (it->second.isNull()) { + std::cerr << "ERROR: book in map is null: " << fileName << std::endl; + res = false; + continue; + } + const Book &book = *it->second; + if (!migrateBookStateStack(fileName, book)) { + res = false; + } + if (!migrateBookLastState(fileName, book)) { + res = false; + } + } + return res; +} + + +bool Migration_0_11_0_Runnable::migrateBookStateStack(const std::string &fileName, const Book &book) { + std::deque<ReadingState> stack; + bool res = true; + int stackSize = ZLIntegerOption(ZLCategoryKey::STATE, fileName, BUFFER_SIZE, 0).value(); + if (stackSize > 0) { + if (stackSize > MaxXmlStackSize) { + stackSize = MaxXmlStackSize; + } + for (int i = 0; i < stackSize; ++i) { + std::string bufferParagraph = BUFFER_PARAGRAPH_PREFIX; + std::string bufferWord = BUFFER_WORD_PREFIX; + ZLStringUtil::appendNumber(bufferParagraph, i); + ZLStringUtil::appendNumber(bufferWord, i); + ReadingState pos( + ZLIntegerOption(ZLCategoryKey::STATE, fileName, bufferParagraph, -1).value(), + ZLIntegerOption(ZLCategoryKey::STATE, fileName, bufferWord, -1).value(), + 0 + ); + stack.push_back(pos); + ZLIntegerOption(ZLCategoryKey::STATE, fileName, bufferParagraph, -1).setValue(-1); // clean state.xml + ZLIntegerOption(ZLCategoryKey::STATE, fileName, bufferWord, -1).setValue(-1); // clean state.xml + } + if (!BooksDB::Instance().saveBookStateStack(book, stack)) { + std::cerr << "ERROR: saving book state stack failed: " << fileName << std::endl; + res = false; + } + stack.clear(); + } + ZLIntegerOption(ZLCategoryKey::STATE, fileName, BUFFER_SIZE, 0).setValue(0); // clean state.xml + return res; +} + +bool Migration_0_11_0_Runnable::migrateBookLastState(const std::string &fileName, const Book &book) { + const ReadingState state( + ZLIntegerOption(ZLCategoryKey::STATE, fileName, PARAGRAPH_OPTION_NAME, 0).value(), + ZLIntegerOption(ZLCategoryKey::STATE, fileName, WORD_OPTION_NAME, 0).value(), + ZLIntegerOption(ZLCategoryKey::STATE, fileName, CHAR_OPTION_NAME, 0).value() + ); + const int stackPos = ZLIntegerOption(ZLCategoryKey::STATE, fileName, POSITION_IN_BUFFER, 0).value(); + if (state.Paragraph == 0 && state.Word == 0 && state.Character == 0 && stackPos == 0) { + return true; + } + ZLIntegerOption(ZLCategoryKey::STATE, fileName, PARAGRAPH_OPTION_NAME, 0).setValue(0); + ZLIntegerOption(ZLCategoryKey::STATE, fileName, WORD_OPTION_NAME, 0).setValue(0); + ZLIntegerOption(ZLCategoryKey::STATE, fileName, CHAR_OPTION_NAME, 0).setValue(0); + ZLIntegerOption(ZLCategoryKey::STATE, fileName, POSITION_IN_BUFFER, 0).setValue(0); + bool res1 = BooksDB::Instance().setBookState(book, state); + bool res2 = BooksDB::Instance().setStackPos(book, stackPos); + if (!res1) { + std::cerr << "ERROR: saving book last state failed: " << fileName << std::endl; + } + if (!res2) { + std::cerr << "ERROR: saving book state stack position failed: " << fileName << std::endl; + } + return res1 && res2; +} + +bool Migration_0_11_0_Runnable::migrateNetwork() { + bool res = true; +// FBReader desktop 0.99.1 deprecates NetFiles table, so don't fill it +// std::vector<std::string> urls; +// ZLOption::listOptionNames(NET_FILES_GROUP, urls); +// for (std::vector<std::string>::const_iterator it = urls.begin(); it != urls.end(); ++it) { +// const std::string &url = *it; +// const std::string fileName = ZLStringOption(ZLCategoryKey::NETWORK, NET_FILES_GROUP, url, "").value(); +// if (!BooksDB::Instance().setNetFile(url, fileName)) { +// std::cerr << "ERROR: saving file's URL failed: " << std::endl +// << "\tURL = " << url << std::endl +// << "\tfileName = " << fileName << std::endl; +// res = false; +// } +// } + ZLOption::clearGroup(NET_FILES_GROUP); // clean state.xml + return res; +} + +bool Migration_0_11_0_Runnable::clearBooksOptions() { + bool res = true; + for (std::map<std::string, shared_ptr<Book> >::const_iterator it = myBooks.begin(); it != myBooks.end(); ++it) { + const std::string &fileName = it->first; + if (it->second.isNull()) { + std::cerr << "ERROR: book in map is null in clearBooksOptions: " << fileName << std::endl; + res = false; + continue; + } + ZLOption::clearGroup(fileName); // clear books.xml & state.xml + } + return res; +} + diff --git a/fbreader/src/migration/Migration_0_8_11.cpp b/fbreader/src/migration/Migration_0_8_11.cpp new file mode 100644 index 0000000..d4fd2f3 --- /dev/null +++ b/fbreader/src/migration/Migration_0_8_11.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2008-2012 Geometer Plus <[email protected]> + * + * 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. + */ + +#include <map> + +#include <ZLStringUtil.h> + +#include "Migration.h" +#include "../fbreader/FBReaderActions.h" + +static void changeActionNames(const std::map<std::string,std::string> map, const std::string &group) { + const int length = ZLIntegerOption(ZLCategoryKey::CONFIG, group, "Number", 0).value(); + for (int i = 0; i < length; ++i) { + std::string optionName = "Action"; + ZLStringUtil::appendNumber(optionName, i); + ZLStringOption option(ZLCategoryKey::CONFIG, group, optionName, ""); + std::string value = option.value(); + std::map<std::string,std::string>::const_iterator it = map.find(value); + if (it != map.end()) { + option.setValue(it->second); + } + } +} + +static void changeActionNames() { + std::map<std::string,std::string> oldToNewNames; + oldToNewNames["0"] = "none"; + oldToNewNames["1"] = ActionCode::SHOW_LIBRARY; + oldToNewNames["30"] = ActionCode::OPEN_PREVIOUS_BOOK; + oldToNewNames["5"] = ActionCode::SHOW_TOC; + oldToNewNames["15"] = ActionCode::SCROLL_TO_HOME; + oldToNewNames["16"] = ActionCode::SCROLL_TO_START_OF_TEXT; + oldToNewNames["17"] = ActionCode::SCROLL_TO_END_OF_TEXT; + oldToNewNames["33"] = ActionCode::GOTO_NEXT_TOC_SECTION; + oldToNewNames["34"] = ActionCode::GOTO_PREVIOUS_TOC_SECTION; + oldToNewNames["9"] = ActionCode::PAGE_SCROLL_FORWARD; + oldToNewNames["10"] = ActionCode::PAGE_SCROLL_BACKWARD; + oldToNewNames["11"] = ActionCode::LINE_SCROLL_FORWARD; + oldToNewNames["12"] = ActionCode::LINE_SCROLL_BACKWARD; + oldToNewNames["3"] = ActionCode::UNDO; + oldToNewNames["4"] = ActionCode::REDO; + oldToNewNames["35"] = ActionCode::COPY_SELECTED_TEXT_TO_CLIPBOARD; + oldToNewNames["37"] = ActionCode::OPEN_SELECTED_TEXT_IN_DICTIONARY; + oldToNewNames["36"] = ActionCode::CLEAR_SELECTION; + oldToNewNames["6"] = ActionCode::SEARCH; + oldToNewNames["7"] = ActionCode::FIND_PREVIOUS; + oldToNewNames["8"] = ActionCode::FIND_NEXT; + oldToNewNames["19"] = ActionCode::INCREASE_FONT; + oldToNewNames["20"] = ActionCode::DECREASE_FONT; + oldToNewNames["21"] = ActionCode::SHOW_HIDE_POSITION_INDICATOR; + oldToNewNames["22"] = ActionCode::TOGGLE_FULLSCREEN; + oldToNewNames["23"] = ActionCode::FULLSCREEN_ON; + oldToNewNames["27"] = ActionCode::ROTATE_SCREEN; + oldToNewNames["2"] = ActionCode::SHOW_OPTIONS_DIALOG; + oldToNewNames["25"] = ActionCode::SHOW_BOOK_INFO_DIALOG; + oldToNewNames["24"] = ActionCode::ADD_BOOK; + oldToNewNames["18"] = ActionCode::CANCEL; + oldToNewNames["29"] = ActionCode::QUIT; + + changeActionNames(oldToNewNames, "Keys"); + changeActionNames(oldToNewNames, "Keys90"); + changeActionNames(oldToNewNames, "Keys180"); + changeActionNames(oldToNewNames, "Keys270"); +} + +Migration_0_8_11::Migration_0_8_11() : Migration("0.8.11") { +} + +void Migration_0_8_11::doMigrationInternal() { + moveOption( + ZLCategoryKey::CONFIG, "FingerTapScrolling", "ScrollingDelay", + ZLCategoryKey::CONFIG, "TapScrolling", "ScrollingDelay", + "0" + ); + moveOption( + ZLCategoryKey::CONFIG, "FingerTapScrolling", "Mode", + ZLCategoryKey::CONFIG, "TapScrolling", "Mode", + "0" + ); + moveOption( + ZLCategoryKey::CONFIG, "FingerTapScrolling", "LinesToKeep", + ZLCategoryKey::CONFIG, "TapScrolling", "LinesToKeep", + "1" + ); + moveOption( + ZLCategoryKey::CONFIG, "FingerTapScrolling", "LinesToScroll", + ZLCategoryKey::CONFIG, "TapScrolling", "LinesToScroll", + "1" + ); + moveOption( + ZLCategoryKey::CONFIG, "FingerTapScrolling", "PercentToScroll", + ZLCategoryKey::CONFIG, "TapScrolling", "PercentToScroll", + "50" + ); + moveOption( + ZLCategoryKey::CONFIG, "FingerTapScrolling", "Enabled", + ZLCategoryKey::CONFIG, "TapScrolling", "Enabled", + "true" + ); + moveOption( + ZLCategoryKey::CONFIG, "Options", "ScrollingDelay", + ZLCategoryKey::CONFIG, "LargeScrolling", "ScrollingDelay", + "250" + ); + changeActionNames(); +} diff --git a/fbreader/src/migration/Migration_0_8_13.cpp b/fbreader/src/migration/Migration_0_8_13.cpp new file mode 100644 index 0000000..ff86fed --- /dev/null +++ b/fbreader/src/migration/Migration_0_8_13.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2008-2012 Geometer Plus <[email protected]> + * + * 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. + */ + +#include <vector> + +#include <ZLStringUtil.h> + +#include "Migration.h" + +Migration_0_8_13::Migration_0_8_13() : Migration("0.8.13") { +} + +void Migration_0_8_13::doMigrationInternal() { + std::vector<std::string> optionNames; + ZLOption::listOptionNames("Style", optionNames); + for (std::vector<std::string>::const_iterator it = optionNames.begin(); it != optionNames.end(); ++it) { + if (ZLStringUtil::stringEndsWith(*it, ":lineSpacing") || + ZLStringUtil::stringEndsWith(*it, ":lineSpace")) { + ZLDoubleOption doubleOption(ZLCategoryKey::LOOK_AND_FEEL, "Style", *it, 0.0); + ZLIntegerOption intOption(ZLCategoryKey::LOOK_AND_FEEL, "Style", *it + "Percent", -1); + const double doubleValue = doubleOption.value(); + const int intValue = intOption.value(); + doubleOption.setValue((intValue == -1) ? 0.0 : (intValue / 100.0)); + intOption.setValue((int)(doubleValue * 100)); + } + } +} diff --git a/fbreader/src/migration/Migration_0_8_16.cpp b/fbreader/src/migration/Migration_0_8_16.cpp new file mode 100644 index 0000000..d08fc49 --- /dev/null +++ b/fbreader/src/migration/Migration_0_8_16.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2008-2012 Geometer Plus <[email protected]> + * + * 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. + */ + +#include <ZLFile.h> +#include <ZLLanguageUtil.h> + +#include "Migration.h" +#include "FB2MigrationReader.h" +#include "OEBMigrationReader.h" +#include "HtmlDCTagsReader.h" +#include "BookInfo.h" + +#include "../options/FBCategoryKey.h" +#include "../formats/oeb/OEBPlugin.h" +#include "../formats/pdb/PdbPlugin.h" +#include "../formats/pdb/PalmDocStream.h" + +Migration_0_8_16::Migration_0_8_16() : Migration("0.8.16") { +} + +void Migration_0_8_16::doMigrationInternal() { + PluginCollection &collection = PluginCollection::Instance(); + + std::vector<std::string> optionGroups; + ZLOption::listOptionGroups(optionGroups); + + for (std::vector<std::string>::const_iterator it = optionGroups.begin(); it != optionGroups.end(); ++it) { + if (isLikeToFileName(*it)) { + ZLFile file(*it); + if (collection.plugin(file, false) != 0) { + BookInfo info(*it); + ZLStringOption &languageOption = info.LanguageOption; + const std::string &language = languageOption.value(); + if (language == "") { + languageOption.setValue(collection.DefaultLanguageOption.value()); + } else if (language == "cz") { + languageOption.setValue("cs"); + } else if (language == "none") { + languageOption.setValue(ZLLanguageUtil::OtherLanguageCode); + } else if ((language == "chinese") || (language == "anycharacter")) { + languageOption.setValue("zh"); + } + + const std::string extension = file.extension(); + if (extension == "fb2") { + ZLBooleanOption seriesOption(FBCategoryKey::BOOKS, *it, "SequenceDefined", false); + if (!seriesOption.value() || info.TagsOption.value().empty()) { + FB2MigrationReader(info, !seriesOption.value()).doRead(ZLFile(*it)); + } + seriesOption.setValue(true); + } else if ((extension == "opf") || (extension == "oebzip") || (extension == "epub")) { + if (info.TagsOption.value().empty()) { + OEBMigrationReader(info).doRead(OEBPlugin::opfFile(ZLFile(*it))); + } + } else if ((extension == "prc") || (extension == "pdb") || (extension == "mobi")) { + const std::string fileType = PdbPlugin::fileType(file); + if (info.TagsOption.value().empty() && ((fileType == "BOOKMOBI") || (fileType == "TEXtREAd"))) { + shared_ptr<ZLInputStream> stream = new PalmDocStream(file); + if (!stream.isNull()) { + HtmlDCTagsReader(info).readDocument(*stream); + } + } + } + } + } + } +} diff --git a/fbreader/src/migration/Migration_0_99_0.cpp b/fbreader/src/migration/Migration_0_99_0.cpp new file mode 100644 index 0000000..6a1d253 --- /dev/null +++ b/fbreader/src/migration/Migration_0_99_0.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2009-2012 Geometer Plus <[email protected]> + * + * 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. + */ + +#include <string> + +#include <ZLLogger.h> + +#include "../database/booksdb/BooksDB.h" +#include "../library/Number.h" + +#include "Migration.h" + +static const std::string RENAME_TABLE_TO_OBSOLETE = "ALTER TABLE BookSeries RENAME TO BookSeries_Obsolete"; +static const std::string CREATE_NEW_TABLE = \ + "CREATE TABLE IF NOT EXISTS BookSeries ( " \ + " book_id INTEGER UNIQUE NOT NULL REFERENCES Books (book_id), " \ + " series_id INTEGER NOT NULL REFERENCES Series (series_id), " \ + " book_index TEXT " \ + "); "; +static const std::string DROP_OBSOLETE_TABLE = "DROP TABLE BookSeries_Obsolete"; +static const std::string LOAD_OBSOLETE_SERIES_QUERY = + "SELECT book_id, series_id, book_index" \ + " FROM BookSeries_Obsolete;"; + +class Migration_0_99_0_Runnable : public DBRunnable { +public: + bool run(); + +}; + +bool Migration_0_99_0_Runnable::run() { + DBConnection &connection = BooksDB::Instance().connection(); + + shared_ptr<DBCommand> renameTable = SQLiteFactory::createCommand(RENAME_TABLE_TO_OBSOLETE, connection); + shared_ptr<DBCommand> createNewTable = SQLiteFactory::createCommand(CREATE_NEW_TABLE, connection); + shared_ptr<DBCommand> dropObsoleteTable = SQLiteFactory::createCommand(DROP_OBSOLETE_TABLE, connection); + shared_ptr<DBCommand> loadObsoleteSeries = SQLiteFactory::createCommand(LOAD_OBSOLETE_SERIES_QUERY, connection); + shared_ptr<DBCommand> insertBookSeries = SQLiteFactory::createCommand(BooksDBQuery::SET_BOOKSERIES, connection, "@book_id", DBValue::DBINT, "@series_id", DBValue::DBINT, "@book_index", DBValue::DBTEXT); + + if (!renameTable->execute()) { + return false; + } + if (!createNewTable->execute()) { + return false; + } + + shared_ptr<DBDataReader> reader = loadObsoleteSeries->executeReader(); + while (reader->next()) { + ((DBIntValue &) *insertBookSeries->parameter("@book_id").value()) = reader->intValue(0); + ((DBIntValue &) *insertBookSeries->parameter("@series_id").value()) = reader->intValue(1); + Number seriesIndex; + if (reader->type(2) == DBValue::DBREAL){ + seriesIndex = Number((int)reader->realValue(2)); + } else { + seriesIndex = Number(reader->intValue(2)); + } + ((DBTextValue &) *insertBookSeries->parameter("@book_index").value()) = seriesIndex.value(); + if (!insertBookSeries->execute()) { + ZLLogger::Instance().println("Migration", "problems with inserting series & book index"); + } + } + dropObsoleteTable->execute(); + return true; +} + + +Migration_0_99_0::Migration_0_99_0() : Migration("0.99.0") { + +} + +void Migration_0_99_0::doMigrationInternal() { + Migration_0_99_0_Runnable r; + BooksDB::Instance().executeAsTransaction(r); +} + diff --git a/fbreader/src/migration/Migration_0_99_1.cpp b/fbreader/src/migration/Migration_0_99_1.cpp new file mode 100644 index 0000000..970f4fc --- /dev/null +++ b/fbreader/src/migration/Migration_0_99_1.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2008-2012 Geometer Plus <[email protected]> + * + * 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. + */ + +#include <map> + +#include <ZLStringUtil.h> + +#include "Migration.h" +#include "../fbreader/FBReaderActions.h" +#include "../database/networkdb/NetworkDB.h" + +Migration_0_99_1::Migration_0_99_1() : Migration("0.99.1") { +} + +void Migration_0_99_1::doMigrationInternal() { + shared_ptr<DBCommand> cmd = SQLiteFactory::createCommand("DROP TABLE IF EXISTS NetFiles", NetworkDB::Instance().connection()); + cmd->execute(); +} diff --git a/fbreader/src/migration/OEBMigrationReader.cpp b/fbreader/src/migration/OEBMigrationReader.cpp new file mode 100644 index 0000000..735e0df --- /dev/null +++ b/fbreader/src/migration/OEBMigrationReader.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus <[email protected]> + * + * 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. + */ + +#include <ZLUnicodeUtil.h> +#include <ZLXMLNamespace.h> + +#include "OEBMigrationReader.h" + +OEBMigrationReader::OEBMigrationReader(BookInfo &info) : myInfo(info) { +} + +static const std::string METADATA = "metadata"; +static const std::string DC_METADATA = "dc-metadata"; + +void OEBMigrationReader::characterDataHandler(const char *text, std::size_t len) { + if (myReadSubject) { + myBuffer.append(text, len); + } +} + +bool OEBMigrationReader::testDCTag(const std::string &name, const std::string &tag) const { + return + testTag(ZLXMLNamespace::DublinCore, name, tag) || + testTag(ZLXMLNamespace::DublinCoreLegacy, name, tag); +} + +void OEBMigrationReader::startElementHandler(const char *tag, const char**) { + const std::string tagString = ZLUnicodeUtil::toLower(tag); + if ((METADATA == tagString) || (DC_METADATA == tagString)) { + myDCMetadataTag = tagString; + myReadMetaData = true; + } else if (myReadMetaData) { + if (testDCTag("subject", tagString)) { + myReadSubject = true; + } + } +} + +void OEBMigrationReader::endElementHandler(const char *tag) { + const std::string tagString = ZLUnicodeUtil::toLower(tag); + if (myDCMetadataTag == tagString) { + interrupt(); + } else if (myReadSubject) { + ZLUnicodeUtil::utf8Trim(myBuffer); + if (!myBuffer.empty()) { + if (!myTagList.empty()) { + myTagList += ','; + } + myTagList += myBuffer; + myBuffer.erase(); + } + myReadSubject = false; + } +} + +bool OEBMigrationReader::processNamespaces() const { + return true; +} + +void OEBMigrationReader::doRead(const ZLFile &file) { + myReadMetaData = false; + myReadSubject = false; + readDocument(file); + myInfo.TagsOption.setValue(myTagList); +} diff --git a/fbreader/src/migration/OEBMigrationReader.h b/fbreader/src/migration/OEBMigrationReader.h new file mode 100644 index 0000000..2ce6690 --- /dev/null +++ b/fbreader/src/migration/OEBMigrationReader.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus <[email protected]> + * + * 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. + */ + +#ifndef __OEBMIGRATIONREADER_H__ +#define __OEBMIGRATIONREADER_H__ + +#include <vector> + +#include <ZLXMLReader.h> + +#include "BookInfo.h" + +class OEBMigrationReader : public ZLXMLReader { + +public: + OEBMigrationReader(BookInfo &info); + void doRead(const ZLFile &file); + + void startElementHandler(const char *tag, const char **attributes); + void endElementHandler(const char *tag); + void characterDataHandler(const char *text, std::size_t len); + bool processNamespaces() const; + +private: + bool testDCTag(const std::string &name, const std::string &tag) const; + +private: + BookInfo &myInfo; + + bool myReadMetaData; + bool myReadSubject; + + std::string myDCMetadataTag; + std::string myBuffer; + std::string myTagList; +}; + +#endif /* __OEBMIGRATIONREADER_H__ */ diff --git a/fbreader/src/migration/migrate.cpp b/fbreader/src/migration/migrate.cpp new file mode 100644 index 0000000..4fefbf7 --- /dev/null +++ b/fbreader/src/migration/migrate.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2008-2012 Geometer Plus <[email protected]> + * + * 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. + */ + +#include "../options/FBCategoryKey.h" + +#include "Migration.h" +#include "migrate.h" + +MigrationRunnable::MigrationRunnable() : + myVersionOption(FBCategoryKey::SYSTEM, "Version", "FBReaderVersion", "0") { +} + +bool MigrationRunnable::shouldMigrate() const { + return + Migration::extractVersionInformation(myVersionOption.value()) < + Migration::extractVersionInformation(VERSION); +} + +void MigrationRunnable::run() { + Migration_0_8_11().doMigration(); + Migration_0_8_13().doMigration(); + Migration_0_8_16().doMigration(); + Migration_0_10_4().doMigration(); + Migration_0_11_0().doMigration(); + Migration_0_99_0().doMigration(); + Migration_0_99_1().doMigration(); + + myVersionOption.setValue(VERSION); +} diff --git a/fbreader/src/migration/migrate.h b/fbreader/src/migration/migrate.h new file mode 100644 index 0000000..e833d28 --- /dev/null +++ b/fbreader/src/migration/migrate.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2008-2012 Geometer Plus <[email protected]> + * + * 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. + */ + +#ifndef __MIGRATE_H__ +#define __MIGRATE_H__ + +#include <ZLOptions.h> +#include <ZLRunnable.h> + +class MigrationRunnable : public ZLRunnable { + +public: + MigrationRunnable(); + bool shouldMigrate() const; + void run(); + +private: + ZLStringOption myVersionOption; +}; + +#endif /* __MIGRATE_H__ */ |