plugin code
[lbook_fbreader.git] / fbreader / src / description / BookDescription.cpp
blob7f479f000bdcba3c0bcb806a22255b6f47078042
1 /*
2 * Copyright (C) 2004-2008 Geometer Plus <contact@geometerplus.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
20 #include <ZLOptions.h>
21 #include <ZLFile.h>
22 #include <ZLUnicodeUtil.h>
23 #include <ZLStringUtil.h>
25 #include "BookDescription.h"
26 #include "BookDescriptionUtil.h"
27 #include "Author.h"
29 #include "../formats/FormatPlugin.h"
30 #include "../options/FBOptions.h"
32 std::map<std::string,BookDescriptionPtr> BookDescription::ourDescriptions;
34 static const std::string EMPTY = "";
36 BookInfo::BookInfo(const std::string &fileName) :
37 AuthorDisplayNameOption(FBCategoryKey::BOOKS, fileName, "AuthorDisplayName", EMPTY),
38 AuthorSortKeyOption(FBCategoryKey::BOOKS, fileName, "AuthorSortKey", EMPTY),
39 TitleOption(FBCategoryKey::BOOKS, fileName, "Title", EMPTY),
40 SequenceNameOption(FBCategoryKey::BOOKS, fileName, "Sequence", EMPTY),
41 NumberInSequenceOption(FBCategoryKey::BOOKS, fileName, "Number in seq", 0, 100, 0),
42 LanguageOption(FBCategoryKey::BOOKS, fileName, "Language", PluginCollection::instance().DefaultLanguageOption.value()),
43 EncodingOption(FBCategoryKey::BOOKS, fileName, "Encoding", EMPTY),
44 IsSequenceDefinedOption(FBCategoryKey::BOOKS, fileName, "SequenceDefined", ZLFile(fileName).extension() != "fb2") {
45 // this is just hack for compatibility with versions < 0.8.8
46 std::string language = LanguageOption.value();
47 if (language == "") {
48 LanguageOption.setValue(PluginCollection::instance().DefaultLanguageOption.value());
49 } else if (language == "cz") {
50 LanguageOption.setValue("cs");
51 } else if (language == "none") {
52 LanguageOption.setValue("other");
53 } else if ((language == "chinese") || (language == "anycharacter")) {
54 LanguageOption.setValue("zh");
58 void BookInfo::reset() {
59 AuthorDisplayNameOption.setValue(EMPTY);
60 AuthorSortKeyOption.setValue(EMPTY);
61 TitleOption.setValue(EMPTY);
62 SequenceNameOption.setValue(EMPTY);
63 NumberInSequenceOption.setValue(0);
64 LanguageOption.setValue(PluginCollection::instance().DefaultLanguageOption.value());
65 EncodingOption.setValue(EMPTY);
68 bool BookInfo::isFull() const {
69 return
70 !AuthorDisplayNameOption.value().empty() &&
71 !AuthorSortKeyOption.value().empty() &&
72 !TitleOption.value().empty() &&
73 !EncodingOption.value().empty() &&
74 IsSequenceDefinedOption.value();
77 BookDescriptionPtr BookDescription::getDescription(const std::string &fileName, bool checkFile) {
78 const std::string physicalFileName = ZLFile(fileName).physicalFilePath();
79 ZLFile file(physicalFileName);
80 if (checkFile && !file.exists()) {
81 return 0;
84 BookDescriptionPtr description = ourDescriptions[fileName];
85 if (description.isNull()) {
86 description = new BookDescription(fileName);
87 ourDescriptions[fileName] = description;
90 if (!checkFile || BookDescriptionUtil::checkInfo(file)) {
91 BookInfo info(fileName);
92 description->myAuthor = SingleAuthor::create(info.AuthorDisplayNameOption.value(), info.AuthorSortKeyOption.value());
93 description->myTitle = info.TitleOption.value();
94 description->mySequenceName = info.SequenceNameOption.value();
95 description->myNumberInSequence = info.NumberInSequenceOption.value();
96 description->myLanguage = info.LanguageOption.value();
97 description->myEncoding = info.EncodingOption.value();
98 if (info.isFull()) {
99 return description;
101 } else {
102 if (physicalFileName != fileName) {
103 BookDescriptionUtil::resetZipInfo(file);
105 BookDescriptionUtil::saveInfo(file);
108 ZLFile bookFile(fileName);
109 FormatPlugin *plugin = PluginCollection::instance().plugin(bookFile, false);
110 if ((plugin == 0) || !plugin->readDescription(fileName, *description)) {
111 return 0;
114 if (description->myTitle.empty()) {
115 description->myTitle = ZLFile::fileNameToUtf8(bookFile.name(true));
117 AuthorPtr author = description->myAuthor;
118 if (author.isNull() || author->displayName().empty()) {
119 description->myAuthor = SingleAuthor::create();
121 if (description->myEncoding.empty()) {
122 description->myEncoding = "auto";
124 if (description->myLanguage.empty()) {
125 description->myLanguage = PluginCollection::instance().DefaultLanguageOption.value();
128 BookInfo info(fileName);
129 info.AuthorDisplayNameOption.setValue(description->myAuthor->displayName());
130 info.AuthorSortKeyOption.setValue(description->myAuthor->sortKey());
131 info.TitleOption.setValue(description->myTitle);
132 info.SequenceNameOption.setValue(description->mySequenceName);
133 info.NumberInSequenceOption.setValue(description->myNumberInSequence);
134 info.LanguageOption.setValue(description->myLanguage);
135 info.EncodingOption.setValue(description->myEncoding);
136 info.IsSequenceDefinedOption.setValue(true);
138 return description;
141 BookDescription::BookDescription(const std::string &fileName) {
142 myFileName = fileName;
143 myAuthor = 0;
144 myNumberInSequence = 0;
147 void WritableBookDescription::clearAuthor() {
148 myDescription.myAuthor = 0;
151 void WritableBookDescription::addAuthor(const std::string &name, const std::string &sortKey) {
152 std::string strippedName = name;
153 ZLStringUtil::stripWhiteSpaces(strippedName);
154 if (strippedName.empty()) {
155 return;
158 std::string strippedKey = sortKey;
159 ZLStringUtil::stripWhiteSpaces(strippedKey);
160 if (strippedKey.empty()) {
161 int index = strippedName.rfind(' ');
162 if (index == -1) {
163 strippedKey = strippedName;
164 } else {
165 strippedKey = strippedName.substr(index + 1);
166 while ((index >= 0) && (strippedName[index] == ' ')) {
167 --index;
169 strippedName = strippedName.substr(0, index + 1) + ' ' + strippedKey;
172 AuthorPtr author = SingleAuthor::create(strippedName, ZLUnicodeUtil::toLower(strippedKey));
173 if (myDescription.myAuthor.isNull()) {
174 myDescription.myAuthor = author;
175 } else {
176 if (myDescription.myAuthor->isSingle()) {
177 myDescription.myAuthor = MultiAuthor::create(myDescription.myAuthor);
179 ((MultiAuthor&)*myDescription.myAuthor).addAuthor(author);