1 /*********
2 *
3 * In the name of the Father, and of the Son, and of the Holy Spirit.
4 *
5 * This file is part of BibleTime's source code, http://www.bibletime.info/.
6 *
7 * Copyright 1999-2016 by the BibleTime developers.
8 * The BibleTime source code is licensed under the GNU General Public License version 2.0.
9 *
10 **********/
11 
12 #ifndef CSWORDMODULEINFO_H
13 #define CSWORDMODULEINFO_H
14 
15 #include <QObject>
16 #include "btdisplayholder.h"
17 
18 #include "../managers/clanguagemgr.h"
19 
20 #include <atomic>
21 #include <QIcon>
22 #include <QList>
23 #include <QMetaType>
24 #include <QString>
25 
26 // Sword includes:
27 #include <listkey.h>
28 #include <swmodule.h>
29 #include <swsearchable.h>
30 #include <swversion.h>
31 
32 
33 #ifdef CLUCENE2
34 // CLucene no longer lists the following functions in its headers
35 extern size_t lucene_utf8towcs(wchar_t *, const char *,  size_t maxslen);
36 extern size_t lucene_wcstoutf8 (char *,  const wchar_t *, size_t maxslen);
37 #endif
38 
39 class CSwordBackend;
40 class CSwordKey;
41 
42 
43 /**
44  * Base class for Sword modules.
45  * This is the base class for all Sword modules. Every class handling a special Sword module type
46  * does inherit from this class.
47  *
48  * @author The BibleTime team
49  * @version $Id: cswordmoduleinfo.h,v 1.83 2007/02/04 23:12:32 joachim Exp $
50  */
51 
52 class CSwordModuleInfo
53     : public QObject
54     , public BtDisplayHolder<CSwordModuleInfo>
55 {
56 
57     Q_OBJECT
58 
59 public: /* Types: */
60 
61     /**
62      * These are the options which could be supported by modules and by this backend.
63      * It's used in @ref CSwordBackend::setOption.
64      */
65     enum FilterTypes {
66         footnotes, /**< Footnotes embedded in the module's text */
67         strongNumbers, /**< strong numbers, usually in the text for the info display */
68         headings, /**< additional section headings */
69         morphTags, /**< morphology */
70         lemmas, /**< lemma tags */
71         hebrewPoints,/**< Hebrew vowel points */
72         hebrewCantillation, /**<Hewbrew caantillation points */
73         greekAccents, /**< Greek accents may be switched on and off */
74         scriptureReferences, /**< scripture references may be switched on and off, just makes sense in Bibles */
75         redLetterWords, /**< Jesus words in red, color is template specific */
76         textualVariants, /**< variants */
77         morphSegmentation, /**< morph word segmentation, supported by OSIS */
78         filterTypesMIN = footnotes, /**< first entry of this enum */
79         filterTypesMAX = morphSegmentation /**< last item in this enum */
80         //     transliteration /* The following are handled in a special way */
81     };
82 
83     /** The text direction of a module */
84     enum TextDirection { /* The text direction of the modules's text */
85         LeftToRight, /**< Left to right text direction, the default setting */
86         RightToLeft /**< Right to left text directin, e.g. for hebrew */
87     };
88 
89     /** The module type. */
90     enum ModuleType {
91         Bible, /**< Bible module */
92         Commentary, /**< Commentary module */
93         Lexicon, /**< Lexicon module */
94         GenericBook, /**< Generic book module */
95         Unknown /**< Fall back type for unknown modules */
96     };
97 
98     /**
99      * This enum is used to give
100      * back an error code after unlocking the module
101      * BibleTime stores the unlock key not in the module's config file but in BibleTime's
102      * configuration file.
103      */
104     enum UnlockErrorCode {
105         noError, /**< No error occured, everything worked ok. The key was written to the BibleTime config */
106         wrongUnlockKey, /**< The wrong key was used. Module is not unlocked */
107         notLocked, /**< The module was not locked so it can't be unlocked */
108         noPermission /**< The key was not written to config because we have no permissions */
109     };
110 
111     enum ConfigEntry {
112         AboutInformation, /**< The about information of a module which is stored in the config file*/
113         AbsoluteDataPath, /**< The absolute data path stored in the config object */
114         CipherKey, /**< The cipher key which was used to unlock the module. Not necessarily set.*/
115         DataPath, /**< The relative path. See AbsoluteDataPath*/
116         Description, /**< The module description stored in the config file */
117         ModuleVersion, /**< The module's version.*/
118         MinimumSwordVersion, /**< The required Sword Version of this module. Otherwise some things may not work (compression etc.).*/
119         TextDir, /**< The text direction */
120         DisplayLevel, /**< Mostly used for books. Gives the level which should contain the connected entries.*/
121         GlossaryFrom, /**< lamguage from which the Glosaary tramslates */
122         GlossaryTo, /**< lamguages to which the glossary maps to */
123         DistributionLicense,
124         DistributionSource,
125         DistributionNotes,
126         TextSource,
127         CopyrightNotes,
128         CopyrightHolder,
129         CopyrightDate,
130         CopyrightContactName,
131         CopyrightContactAddress,
132         CopyrightContactEmail,
133         Markup  /**< The markup of this module */
134     };
135 
136     enum Feature {
137         //StrongsNumbers, /**< Use for Bibles which have embedded strong numbers */ BT does not use this as a user option
138         GreekDef,
139         HebrewDef,
140         GreekParse,
141         HebrewParse,
142         featureMin = GreekDef,
143         featureMax = HebrewParse
144     };
145 
146     enum Category {
147         UnknownCategory = 0x0,  /**< Unknown or unset category. */
148         NoCategory      = 0x0,
149         Bibles          = 0x01,
150         Commentaries    = 0x02,
151         Books           = 0x04,
152         Lexicons        = 0x08,
153         Glossary        = 0x10,
154         DailyDevotional = 0x20,
155         Images          = 0x40,
156         Cult            = 0x80, /**< Cult / sect / questionable module. */
157         AllCategories   = 0xff
158     };
159     Q_DECLARE_FLAGS(Categories, Category)
160 
161 public: /* Methods: */
162 
163     CSwordModuleInfo(CSwordModuleInfo &&) = delete;
164     CSwordModuleInfo(CSwordModuleInfo const &) = delete;
165     CSwordModuleInfo & operator=(CSwordModuleInfo &&) = delete;
166     CSwordModuleInfo & operator=(CSwordModuleInfo const &) = delete;
167 
168     /**
169     * Returns the base directory for search indices
170     */
171     static QString getGlobalBaseIndexLocation();
172 
173     /**
174       Removes the search index for this module (rm -rf).
175     */
176     void deleteIndex();
177 
178     /**
179       Removes search index for a module, even if the module is not there any more.
180       \param[in] name name of the module.
181     */
182     static void deleteIndexForModule(const QString & name);
183 
184     /**
185     * Returns the config entry which is pecified by the parameter.
186     */
187     QString config(const CSwordModuleInfo::ConfigEntry entry) const;
188 
189     /**
190     * Returns the module object so all objects can access the original Sword module.
191     */
module()192     inline sword::SWModule & module() const {
193         return m_module;
194     }
195 
196     /**
197     * Sets the unlock key of the modules and writes the key into the config file.
198     * @return True if the unlock process was succesful, if the key was
199 wrong, or if the config file was write protected return false.
200     */
201     bool unlock(const QString & unlockKey);
202 
203     /**
204     * This function does return true if the data files of the module are encrypted by the module author
205     * (the on who made the module) no matter if it's locked or not.
206     * @return True if this module is encryped
207     */
208     bool isEncrypted() const;
209 
210     /**
211     * This function returns true if this module is locked (encrypted + correct cipher key),
212     * otherwise return false.
213     * @return True if this module is locked, i.e. encrypted but without a key set
214     */
215     bool isLocked() const;
216 
217     /**
218       This function makes an estimate if a module was properly unlocked. It
219       returns true if the first entry of the module is not empty and
220       contains only printable characters (for the first 100 chars or so). If
221       that is the case, we can safely assume that a) the module was properly
222       unlocked and b) no buffer overflows will occur, which can happen when
223       Sword filters process garbage text which was not properly decrypted.
224     */
225     bool unlockKeyIsValid() const;
226 
227     /**
228       \retval true if this module has a version number
229       \retval false if it doesn't have a version number
230     */
hasVersion()231     inline bool hasVersion() const {
232         return m_cachedHasVersion;
233     }
234 
235     /**
236       \returns true if the module's index has been built.
237     */
238     bool hasIndex() const;
239 
240     /**
241       \returns the path to this module's index base dir
242     */
243     QString getModuleBaseIndexLocation() const;
244 
245     /**
246       \returns the path to this module's standard index
247     */
248     QString getModuleStandardIndexLocation() const;
249 
250     /**
251       Builds a search index for this module
252       \throws when unsuccessful
253     */
254     void buildIndex();
255 
256     /**
257       \returns index size
258     */
259     size_t indexSize() const;
260 
261     /**
262       This function uses CLucene to perform and index based search. It also
263       overwrites the variable containing the last search result.
264       \returns the number of results found
265       \throws on error
266     */
267     size_t searchIndexed(const QString & searchedText,
268                          const sword::ListKey & scope,
269                          sword::ListKey & results) const;
270 
271     /**
272       \returns the type of the module.
273     */
type()274     inline ModuleType type() const {
275         return m_type;
276     }
277 
278     /**
279     * Returns the required Sword version for this module.
280     * Returns -1 if no special Sword version is required.
281     */
282     sword::SWVersion minimumSwordVersion() const;
283 
284     /**
285       \note The Sword library takes care of the duplicate names: _n is added
286             after each duplicate.
287       \returns The name of this module.
288     */
name()289     inline const QString & name() const {
290         return m_cachedName;
291     }
292 
293     /**
294     * Snaps to the closest entry in the module if the current key is
295     * not present in the data files.
296     */
snap()297     virtual inline bool snap() const {
298         return false;
299     }
300 
301     /**
302       \returns whether the module supports the feature given as parameter.
303     */
304     bool has(const CSwordModuleInfo::Feature) const;
305 
306     bool has(const CSwordModuleInfo::FilterTypes ) const;
307 
308     /** \returns the text direction of the module's text. */
309     CSwordModuleInfo::TextDirection textDirection() const;
310 
311     /** \returns the text direction of the module's text as an HTML value. */
312     char const * textDirectionAsHtml() const;
313 
314     /**
315       Writes the new text at the given position into the module. This does
316       only work for writabe modules.
317     */
318     void write(CSwordKey * key, const QString & newText);
319 
320     /**
321       Deletes the current entry and removes it from the module.
322     */
323     void deleteEntry(CSwordKey * const key);
324 
325     /**
326       \returns the language of the module.
327     */
language()328     inline const CLanguageMgr::Language * language() const {
329         return m_cachedLanguage;
330     }
331 
332     /**
333       \returns whether this module may be written to.
334     */
isWritable()335     inline virtual bool isWritable() const {
336         return false;
337     }
338 
339     /**
340     * Returns true if this module is hidden (not to be shown with other modules in certain views).
341     */
isHidden()342     inline bool isHidden() const {
343         return m_hidden;
344     }
345 
346     /**
347       Shows or hides the module.
348       \param hide Whether the module should be hidden.
349       \returns whether the hidden state was changed.
350     */
351     bool setHidden(bool hide);
352 
353     /**
354       \returns the category of this module.
355     */
category()356     inline CSwordModuleInfo::Category category() const {
357         return m_cachedCategory;
358     }
359 
360     /**
361     * The about text which belongs to this module.
362     */
363     QString aboutText() const;
364 
365     /**
366     * Returns true if this module is Unicode encoded. False if the charset is iso8859-1.
367     * Protected because it should not be used outside of the CSword*ModuleInfo classes.
368     */
isUnicode()369     inline bool isUnicode() const {
370         return m_module.isUnicode();
371     }
372 
373     /**
374       Returns an icon for this module.
375     */
moduleIcon()376     inline QIcon moduleIcon() const {
377         return CSwordModuleInfo::moduleIcon(*this);
378     }
379 
380     /**
381       Returns an icon for the given module.
382       \param[in] module The module whose icon to return.
383     */
384     static QIcon const & moduleIcon(CSwordModuleInfo const & module);
385 
386     /**
387       Returns an icon for the category of given module.
388       \param[in] module The module whose category icon to return.
389     */
390     static QIcon const & categoryIcon(CSwordModuleInfo::Category category);
391 
392     /**
393       Returns a translated name for the given category.
394       \param[in] module The category whose translated name to return.
395     */
396     static QString categoryName(const CSwordModuleInfo::Category & category);
397 
398     /**
399       Returns a english name for the given category.
400       \param[in] module The category whose english name to return.
401     */
402     static QString englishCategoryName(const CSwordModuleInfo::Category & category);
403 
404 public slots:
405 
406     inline void cancelIndexing(std::memory_order const memoryOrder =
407                                         std::memory_order_relaxed) noexcept
408     { m_cancelIndexing.store(true, memoryOrder); }
409 
410 protected: /* Methods: */
411 
412     CSwordModuleInfo(sword::SWModule & module,
413                      CSwordBackend & backend,
414                      ModuleType type);
415 
backend()416     inline CSwordBackend & backend() const {
417         return m_backend;
418     }
419 
420     QString getSimpleConfigEntry(const QString & name) const;
421     QString getFormattedConfigEntry(const QString & name) const;
422 
423 signals:
424 
425     void hasIndexChanged(bool hasIndex);
426     void hiddenChanged(bool hidden);
427     void unlockedChanged(bool unlocked);
428     void indexingFinished();
429     void indexingProgress(int);
430 
431 private: /* Fields: */
432 
433     sword::SWModule & m_module;
434     CSwordBackend & m_backend;
435     ModuleType const m_type;
436     bool m_hidden;
437     std::atomic<bool> m_cancelIndexing;
438 
439     // Cached data:
440     QString const m_cachedName;
441     CSwordModuleInfo::Category const m_cachedCategory;
442     const CLanguageMgr::Language * const m_cachedLanguage;
443     bool const m_cachedHasVersion;
444 
445 };
446 
447 Q_DECLARE_METATYPE(CSwordModuleInfo::Category);
448 Q_DECLARE_OPERATORS_FOR_FLAGS(CSwordModuleInfo::Categories)
449 
450 #endif
451