1 /***************************************************************************
2 * This file is part of KWorship. *
3 * Copyright 2008 James Hogan <james@albanarts.com> *
5 * KWorship is free software: you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation, either version 2 of the License, or *
8 * (at your option) any later version. *
10 * KWorship is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with KWorship. If not, write to the Free Software Foundation, *
17 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
18 ***************************************************************************/
21 * @file KwBibleModule.cpp
22 * @brief An abstract bible module (analagous to a SWORD module).
23 * @author James Hogan <james@albanarts.com>
26 #include "KwBibleModule.h"
27 #include "KwBiblePassage.h"
32 * Constructors + destructor
35 /// Default constructor.
36 KwBibleModule::KwBibleModule()
38 , m_rightToLeft(false)
43 KwBibleModule::~KwBibleModule()
51 /// Create a key from a string.
52 KwBibleModule::Key
KwBibleModule::createKey(const QString
& text
, bool* valid
)
54 // Find the key relative to the first chapter of the first book.
55 return createKey(createKey(0, 0), text
, valid
);
58 /// Create a key from a string relative to another key.
59 KwBibleModule::Key
KwBibleModule::createKey(const Key
& other
, const QString
& text
, bool* valid
)
62 static QRegExp
re("^\\s*" // Must from beginning (ignore whitespace)
64 "(((\\S+)|\"([^\"]+)\")\\s+)?" // Optional book name followed by spaces
66 "((\\d+)[:.])?" // Optional chapter number followed by [:.]
68 "(\\d+)?" // Optional verse number
70 "(\\s*-\\s*" // Optionally start matching dash followed by end of the range
72 "((\\d+)[:.])?" // Optional chapter number followed by [:.]
74 "(\\d+)?" // Optional verse number
76 ")?" // End of matching end of range
77 "\\s*$" // Must match to end (ignore whitespace)
79 Q_ASSERT(re
.isValid());
81 if (re
.exactMatch(text
))
83 QStringList cap
= re
.capturedTexts();
86 if (!cap
[3].isEmpty())
90 else if (!cap
[4].isEmpty())
94 if (!bookName
.isEmpty())
96 int book
= bookIndex(bookName
);
99 key
.start
.book
= book
;
107 QString chapterName
= cap
[6];
108 if (!chapterName
.isEmpty())
110 int chapter
= chapterName
.toInt() - 1;
111 if (chapter
>= 0 && chapter
< numChapters(key
.start
.book
))
113 key
.start
.chapter
= chapter
;
121 QString verseName
= cap
[7];
122 if (!verseName
.isEmpty())
124 int verse
= verseName
.toInt() - 1;
125 if (verse
>= 0 && verse
< numVerses(key
.start
.book
, key
.start
.chapter
))
127 key
.start
.verse
= verse
;
135 if (!cap
[8].isEmpty())
137 key
.end
.book
= key
.start
.book
;
138 key
.end
.chapter
= key
.start
.chapter
;
141 QString chapterName
= cap
[10];
142 if (!chapterName
.isEmpty())
144 int chapter
= chapterName
.toInt() - 1;
145 if (chapter
>= 0 && chapter
< numChapters(key
.start
.book
))
147 key
.end
.chapter
= chapter
;
155 QString verseName
= cap
[11];
156 if (!verseName
.isEmpty())
158 int verse
= verseName
.toInt() - 1;
159 if (verse
>= 0 && verse
< numVerses(key
.start
.book
, key
.start
.chapter
))
161 key
.end
.verse
= verse
;
168 if (key
.end
.verse
< 0)
170 key
.end
.verse
= numVerses(key
.end
.book
, key
.end
.chapter
)-1;
178 //std::cout << "result: " << key.start.book << "." << key.start.chapter << ":" << key.start.verse << " - "
179 // << key.end.book << "." << key.end.chapter << ":" << key.end.verse << std::endl;
187 /// Create a key from individual values.
188 KwBibleModule::Key
KwBibleModule::createKey(int book
, int chapter
, int verse
)
190 Key key
= { { book
, chapter
, verse
},
195 /// Create a key from individual values.
196 KwBibleModule::Key
KwBibleModule::createKey(const QString
& book
, int chapter
, int verse
)
198 int bookId
= bookIndex(book
);
199 Key key
= { { bookId
, chapter
, verse
},
204 /// Create a range key between two verses in the same chapter.
205 KwBibleModule::Key
KwBibleModule::createKey(const QString
& book
, int chapter
, int verseStart
,
208 int bookId
= bookIndex(book
);
209 Key key
= { { bookId
, chapter
, verseStart
},
210 { bookId
, chapter
, verseEnd
} };
214 /// Create a range key between two verses in different chapters.
215 KwBibleModule::Key
KwBibleModule::createKey(const QString
& book
, int chapterStart
, int verseStart
,
216 int chapterEnd
, int verseEnd
)
218 int bookId
= bookIndex(book
);
219 Key key
= { { bookId
, chapterStart
, verseStart
},
220 { bookId
, chapterEnd
, verseEnd
} };
224 /// Create a range key between two verses in different books.
225 KwBibleModule::Key
KwBibleModule::createKey(const QString
& bookStart
, int chapterStart
, int verseStart
,
226 const QString
& bookEnd
, int chapterEnd
, int verseEnd
)
228 int bookIdStart
= bookIndex(bookStart
);
229 int bookIdEnd
= bookIndex(bookEnd
);
230 Key key
= { { bookIdStart
, chapterStart
, verseStart
},
231 { bookIdEnd
, chapterEnd
, verseEnd
} };
235 /// Is the text right to left?
236 bool KwBibleModule::isRightToLeft() const
238 return m_rightToLeft
;
241 /// List the books in this module.
242 const QStringList
& KwBibleModule::books()
244 if (m_books
.isEmpty())
251 /// Get the index of a book from it's name.
252 int KwBibleModule::bookIndex(const QString
& name
)
254 if (m_books
.isEmpty())
258 return m_books
.indexOf(name
);
261 /// Get the name of a book from it's index.
262 QString
KwBibleModule::bookName(int book
)
264 if (m_books
.isEmpty())
268 if (book
>= 0 && book
< m_books
.size())
270 return m_books
[book
];
278 bool KwBibleModule::fillPassage(const Key
& key
, KwBiblePassage
* outPassage
)
282 // Complete the range
283 if (range
.start
.book
< 0)
285 // Start book must be specified
288 else if (range
.end
.book
< 0)
290 range
.end
.book
= range
.start
.book
;
293 if (range
.start
.chapter
< 0)
295 range
.start
.chapter
= 0;
296 range
.end
.chapter
= numChapters(range
.end
.book
)-1;
298 else if (range
.end
.chapter
< 0)
300 range
.end
.chapter
= range
.start
.chapter
;
303 if (range
.start
.verse
< 0)
305 range
.start
.verse
= 0;
306 range
.end
.verse
= numVerses(range
.end
.book
, range
.end
.chapter
)-1;
308 else if (range
.end
.verse
< 0)
310 range
.end
.verse
= range
.start
.verse
;
313 outPassage
->setSource(managerId(), name(), m_rightToLeft
);
314 outPassage
->initBooks(range
.start
.book
, 1+range
.end
.book
-range
.start
.book
);
315 for (int book
= range
.start
.book
; book
<= range
.end
.book
; ++book
)
317 bool isFirstBook
= (book
== range
.start
.book
);
318 bool isLastBook
= (book
== range
.end
.book
);
319 int maxChapters
= numChapters(book
);
320 int firstChapter
= (isFirstBook
? range
.start
.chapter
: 0);
321 int lastChapter
= (isLastBook
? range
.end
.chapter
: maxChapters
-1);
322 Q_ASSERT(lastChapter
>= firstChapter
&& lastChapter
< maxChapters
);
323 outPassage
->initBook(book
, bookName(book
), 1+firstChapter
, 1+lastChapter
-firstChapter
);
324 for (int chapter
= firstChapter
; chapter
<= lastChapter
; ++chapter
)
326 bool isFirstChapter
= isFirstBook
&& (chapter
== firstChapter
);
327 bool isLastChapter
= isLastBook
&& (chapter
== lastChapter
);
328 int maxVerses
= numVerses(book
, chapter
);
329 int firstVerse
= (isFirstChapter
? range
.start
.verse
: 0);
330 int lastVerse
= (isLastChapter
? range
.end
.verse
: maxVerses
-1);
331 Q_ASSERT(lastVerse
>= firstVerse
&& lastVerse
< maxVerses
);
332 outPassage
->initChapter(book
, 1+chapter
, 1+firstVerse
, 1+lastVerse
-firstVerse
);
333 for (int verse
= firstVerse
; verse
<= lastVerse
; ++verse
)
335 fillPassageVerse(book
, chapter
, verse
, outPassage
);
343 * Protected virtual interface
346 /// Ensure that the book list is up to date.
347 void KwBibleModule::obtainBooks()
352 * Protected interface
355 /// Update the list of books.
356 void KwBibleModule::setBooks(const QStringList
& books
)
361 /// Set whether the module has text right-to-left.
362 void KwBibleModule::setRightToLeft(bool rightToLeft
)
364 m_rightToLeft
= rightToLeft
;