summaryrefslogtreecommitdiffstats
path: root/src/kio_sword.cpp
diff options
context:
space:
mode:
authorSlávek Banko <slavek.banko@axis.cz>2013-08-21 19:16:24 +0200
committerSlávek Banko <slavek.banko@axis.cz>2013-08-21 19:16:24 +0200
commit44c23c4159d9195718a7e80e005cc5c12c7001ce (patch)
tree65ab21fde66beb0aeee124631e0f65b0fb8c18bd /src/kio_sword.cpp
downloadtdeio-sword-44c23c4159d9195718a7e80e005cc5c12c7001ce.tar.gz
tdeio-sword-44c23c4159d9195718a7e80e005cc5c12c7001ce.zip
Initial import of kio-sword 0.3
Diffstat (limited to 'src/kio_sword.cpp')
-rw-r--r--src/kio_sword.cpp676
1 files changed, 676 insertions, 0 deletions
diff --git a/src/kio_sword.cpp b/src/kio_sword.cpp
new file mode 100644
index 0000000..b0db5bc
--- /dev/null
+++ b/src/kio_sword.cpp
@@ -0,0 +1,676 @@
+/***************************************************************************
+ File: kio_sword.cpp
+ Project: Kio-Sword -- An ioslave for SWORD and KDE
+ Copyright: Copyright (C) 2004-2005 Luke Plant
+
+ File info:
+ ***************************************************************************/
+
+/***************************************************************************
+ * 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., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+// Mine
+#include "renderer.h"
+#include "kio_sword.h"
+#include "utils.h"
+#include "template.h"
+#include "option.h"
+
+// KDE
+#include <kdebug.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kurl.h>
+#include <kstandarddirs.h>
+
+// Qt
+#include <qcstring.h>
+#include <qmap.h>
+
+// Standard C++ /C
+#include <list>
+#include <stdlib.h>
+
+using namespace KIO;
+using std::list;
+using std::vector;
+
+
+// main --------------------------------------------------------------------------------------------------------
+extern "C" {
+ int kdemain(int argc, char **argv) {
+ KInstance instance("kio_sword");
+
+ kdDebug(7101) << "*** Starting kio_sword " << endl;
+
+ if (argc != 4) {
+ kdDebug(7101) <<
+ "Usage: kio_sword protocol domain-socket1 domain-socket2"
+ << endl;
+ exit(-1);
+ }
+
+ KioSword::SwordProtocol slave(argv[2], argv[3]);
+ slave.dispatchLoop();
+
+ kdDebug(7101) << "*** kio_sword Done" << endl;
+ return 0;
+ }
+}
+
+namespace KioSword
+{
+ class SwordOptions;
+
+ // HTML fragments that will be initialised at run time -------------------------------------------------------------------------
+ static QString search_form;
+ static QString help_page;
+
+
+
+ SwordProtocol::SwordProtocol(const QCString & pool_socket,
+ const QCString & app_socket)
+ : SlaveBase("kio_sword", pool_socket, app_socket)
+ {
+ kdDebug() << "SwordProtocol::SwordProtocol()" << endl;
+ m_config = KGlobal::config();
+ }
+
+
+ SwordProtocol::~SwordProtocol()
+ {
+ kdDebug() << "SwordProtocol::~SwordProtocol()" << endl;
+ }
+
+ void SwordProtocol::get(const KURL & url)
+ {
+ QString modname;
+ QString query;
+ QString error;
+
+ kdDebug() << "SwordProtocol::get(const KURL& url)" << endl;
+
+ /* kdDebug() << "Seconds: " << url.query() << endl;
+ QString remoteServer = url.host();
+ int remotePort = url.port();
+ kdDebug() << "myURL: " << url.prettyURL() << endl; */
+
+ // Send the mimeType as soon as it is known
+ mimeType("text/html");
+
+ // Set user defaults from user config file
+ // (with internal defaults supplied if any options
+ // are missing from users config file)
+ readUserConfig();
+
+ // Get options/actions from URL
+ parseURL(url);
+
+ if (!m_path.isEmpty() && m_path != "/") {
+ if (!m_path.startsWith("/")) {
+ // sword:xxx is a shortcut for bible verses
+ modname = m_options.defaultBible();
+ if (modname.isEmpty())
+ {
+ error = i18n("No default Bible has been specified.");
+ }
+ else
+ {
+ // do redirection
+ query = m_path;
+ KURL newurl(url);
+ newurl.setPath('/' + modname + '/' + query);
+ redirection(newurl);
+ finished();
+ return;
+ }
+ }
+ else
+ {
+ modname = m_path.section('/', 0, 0, QString::SectionSkipEmpty);
+ query = m_path.section('/', 1, -1, QString::SectionSkipEmpty);
+ }
+ }
+
+ // handle redirections first
+ if (m_action == REDIRECT_QUERY) {
+ if (!m_redirect.module.isEmpty())
+ modname = m_redirect.module;
+ if (!m_redirect.query.isEmpty())
+ query = m_redirect.query;
+
+ if (modname.isEmpty()) {
+ switch (m_moduletype) {
+ case DEFBIBLE:
+ modname = m_options.defaultBible();
+ error = i18n("No default Bible has been specified.");
+ break;
+ case GREEKSTRONGS:
+ modname = m_options.defaultGreekStrongs();
+ error = i18n("No default Greek Strongs module has been specified.");
+ break;
+ case HEBREWSTRONGS:
+ modname = m_options.defaultHebrewStrongs();
+ error = i18n("No default Hebrew Strongs module has been specified.");
+ break;
+ case GREEKMORPH:
+ modname = m_options.defaultGreekMorph();
+ error = i18n("No default Greek morphological module has been specified.");
+ break;
+ case HEBREWMORPH:
+ modname = m_options.defaultHebrewMorph();
+ error = i18n("No default Hebrew morphological module has been specified.");
+ break;
+ case DEFMODULETYPE_NONE:
+ error = i18n("No module specified.");
+ }
+ }
+
+ if (modname.isEmpty()) {
+ error = "<p class='usererror'>" + error + "</p><hr />";
+ m_action = QUERY; // revert back to displaying list of modules
+ } else {
+ KURL newurl(url);
+ // Remove anything that will trigger a redirection
+ newurl.removeQueryItem("module");
+ newurl.removeQueryItem("query");
+ newurl.removeQueryItem("testsettings");
+ newurl.removeQueryItem("modtype");
+ newurl.setPath('/' + modname + '/' + query);
+ redirection(newurl);
+ finished();
+ return;
+ }
+ }
+
+ // Send the data
+ Template* tmplt = new Template();
+ tmplt->setCurrentPath(m_path);
+
+ switch (m_action) {
+ case QUERY:
+ if (!modname.isEmpty()) {
+ m_renderer.moduleQuery(modname, query, m_options, tmplt);
+ } else {
+ QString body;
+ tmplt->setTitle(i18n("Modules - Kio-Sword"));
+ if (!error.isEmpty()) {
+ body = error;
+ }
+ body += m_renderer.listModules(m_options);
+ tmplt->setContent(body);
+ }
+ break;
+
+ case SEARCH_FORM:
+ tmplt->setTitle(i18n("Search - Kio-Sword"));
+ tmplt->setContent(searchForm(m_options));
+ break;
+
+ case SEARCH_QUERY:
+ tmplt->setTitle(i18n("Search Results - Kio-Sword"));
+ tmplt->setContent(m_renderer.search(m_redirect.module, m_redirect.query, m_stype, m_options));
+ break;
+
+ case SETTINGS_FORM:
+ tmplt->setTitle(i18n("Settings - Kio-Sword"));
+ tmplt->setContent(settingsForm());
+ break;
+
+ case SETTINGS_SAVE:
+ tmplt->setTitle(i18n("Settings saved - Kio-Sword"));
+ tmplt->setContent(saveUserConfig());
+ break;
+
+ case HELP:
+ tmplt->setTitle(i18n("Kio-Sword Help"));
+ tmplt->setContent(helpPage());
+ break;
+
+ default:
+ break;
+ }
+ sendPage(tmplt);
+ delete tmplt;
+
+ }
+
+
+ void SwordProtocol::mimetype(const KURL& url) {
+ mimeType("text/html");
+ finished();
+ }
+
+ /* redefine data for QCStrings so we don't send the trailing
+ null */
+ void SwordProtocol::data(const QCString& text) {
+ QByteArray nonull;
+ nonull.setRawData(text.data(), text.size()-1);
+ SlaveBase::data(nonull);
+ nonull.resetRawData(text.data(), text.size()-1);
+ }
+
+ void SwordProtocol::data(const QByteArray& array) {
+ SlaveBase::data(array);
+ }
+
+ void SwordProtocol::readUserConfig()
+ {
+ m_options.readFromConfig(m_config);
+ }
+
+ QString SwordProtocol::saveUserConfig()
+ {
+ QString message;
+ m_options.saveToConfig(m_config);
+ m_config->sync();
+ // search form depends on settings, so force it to be recreated
+ search_form.truncate(0);
+ message = "<p>" + i18n("Settings saved.") + "</p>";
+ return message;
+ }
+
+
+ #define ENUM_OPTION(option, tag, v) \
+ if (!strcasecmp(key, tag)) { \
+ option = v; \
+ }
+
+ void SwordProtocol::parseURL(const KURL& url)
+ {
+ // Reset data members that should always be
+ // retrieved from URL
+ m_action = QUERY;
+ m_path = QString::null;
+ m_redirect.module = QString::null;
+ m_redirect.query = QString::null;
+ m_previous.module = QString::null;
+ m_previous.query = QString::null;
+ m_moduletype = DEFMODULETYPE_NONE;
+
+ if (url.hasPath())
+ m_path = url.path();
+
+ m_options.readFromQueryString(url.queryItems(KURL::CaseInsensitiveKeys));
+
+ // URLs will be encoded in UTF-8 since they are sometimes
+ // generated from the search form, and the browser will
+ // encode in UTF-8 since the whole page has UTF-8 charset
+ QMap<QString, QString> items = url.queryItems(KURL::CaseInsensitiveKeys, 106);
+ QMap<QString, QString>::const_iterator it;
+ QMap<QString, QString>::const_iterator it_end = items.end();
+ QString val;
+
+ const char *key;
+ for(it = items.begin(); it != it_end; it++) {
+ key = it.key().latin1();
+ val = it.data();
+
+ if (!strcasecmp(key, "query")) {
+ m_redirect.query = val;
+ }
+ else if (!strcasecmp(key, "module")) {
+ m_redirect.module = val;
+ }
+ else if (!strcasecmp(key, "modtype")) {
+ if (!strcasecmp(val, "bible")) {
+ m_moduletype = DEFBIBLE;
+ m_action = REDIRECT_QUERY;
+ } else if (!strcasecmp(val, "greekstrongs")) {
+ m_moduletype = GREEKSTRONGS;
+ m_action = REDIRECT_QUERY;
+ } else if (!strcasecmp(val, "hebrewstrongs")) {
+ m_moduletype = HEBREWSTRONGS;
+ m_action = REDIRECT_QUERY;
+ } else if (!strcasecmp(val, "greekmorph")) {
+ m_moduletype = GREEKMORPH;
+ m_action = REDIRECT_QUERY;
+ } else if (!strcasecmp(val, "hebrewmorph")) {
+ m_moduletype = HEBREWMORPH;
+ m_action = REDIRECT_QUERY;
+ }
+ }
+ // search
+ else if (!strcasecmp(key, "stype")) {
+ if (!strcasecmp(val, "words")) {
+ m_stype = Renderer::SEARCH_WORDS;
+ } else if (!strcasecmp(val, "phrase")) {
+ m_stype = Renderer::SEARCH_PHRASE;
+ } else if (!strcasecmp(val, "regex")) {
+ m_stype = Renderer::SEARCH_REGEX;
+ } else {
+ m_stype = Renderer::SEARCH_WORDS;
+ }
+ }
+
+ // Actions
+ else ENUM_OPTION(m_action, "help", HELP)
+ else ENUM_OPTION(m_action, "search", SEARCH_FORM)
+ else ENUM_OPTION(m_action, "searchq", SEARCH_QUERY)
+ else ENUM_OPTION(m_action, "settings", SETTINGS_FORM)
+ else ENUM_OPTION(m_action, "savesettings", SETTINGS_SAVE)
+ else ENUM_OPTION(m_action, "testsettings", REDIRECT_QUERY)
+
+ else if (!strcasecmp(key, "previouspath")) {
+ m_previous.module = val.section('/', 0, 0, QString::SectionSkipEmpty);
+ m_previous.query = val.section('/', 1, -1, QString::SectionSkipEmpty);
+ }
+ }
+
+ // Once all the URL is parsed:
+ if ((m_action == QUERY) && (
+ !m_redirect.query.isEmpty() || !m_redirect.module.isEmpty()))
+ m_action = REDIRECT_QUERY;
+ }
+
+ #undef ENUM_OPTION
+
+
+ void SwordProtocol::sendPage(const Template* tplt) {
+ data(tplt->render(m_options));
+ data(QByteArray()); // empty array means we're done sending the data
+ finished();
+ }
+
+ /** Returns a string representing notes about an option for the settings page
+ */
+ template <class T>
+ QString optionNotes(const Option<T>& option)
+ {
+ QString output;
+ if (!option.m_propagate)
+ {
+ output += "<sup>1</sup>";
+ }
+ if (option.m_configName.isNull())
+ {
+ if (output.length() > 0)
+ {
+ output += "<sup>,</sup>";
+ }
+ output += "<sup>2</sup>";
+ }
+ return output;
+ }
+
+
+ /** HTML for a boolean option */
+ QString settingsBooleanOptionRow(const QString& description, const Option<bool>& option) {
+ static const QString boolean_option_row(
+ "<tr><td>%1</td><td><nobr><input type='radio' name='%2' value='1' %3>%4 &nbsp;&nbsp;<input type='radio' name='%2' value='0' %5>%6</nobr></td><td>%2, %7</td></tr>");
+ return boolean_option_row
+ .arg(description + optionNotes(option))
+ .arg(option.m_qsShortName)
+ .arg(option.m_qsShortName)
+ .arg(option.m_qsShortName)
+ .arg(option() ? "checked" : "")
+ .arg(i18n("On"))
+ .arg(option() ? "" : "checked")
+ .arg(i18n("Off"))
+ .arg(option.m_qsLongName);
+ }
+ /** */
+
+ /** HTML for a general option row
+ *
+ * @param description User visible description of option
+ * @param option option metadata
+ * @param optionList HTML containing the <option>s
+ * @return
+ */
+ QString settingsGeneralOptionRow(const QString& description, const Option<QString>& option,
+ const QString& optionList)
+ {
+ static const QString general_option_row(
+ "<tr><td>%1</td><td><select name='%2'>%3</select></td><td>%4, %5</td></tr>");
+ return general_option_row
+ .arg(description + optionNotes(option))
+ .arg(option.m_qsLongName)
+ .arg(optionList)
+ .arg(option.m_qsShortName)
+ .arg(option.m_qsLongName);
+ }
+
+ QString SwordProtocol::settingsForm() {
+ QString output;
+ QStringList modules;
+ QStringList::Iterator it;
+ QString temp;
+
+ static const QString separator_row(
+ "<tr><td class='settingscategory' colspan='3'>%1</td></tr>");
+
+
+ // Start output
+ output += i18n("<h1>Settings</h1>"
+ "<p>Select the settings using the form below. Use the 'Save settings' button to "
+ " save these settings to your own configuration file. 'Test settings' will return "
+ " you to the previous page with the options you have specified. <br>");
+
+ output += QString(
+ "<form action='sword:/' method='GET'>"
+ "<table class='settings' border=0 cellspacing=0>"
+ " <tr><th>%1</th><th>%2</th><th>%4</th></tr>")
+ .arg(i18n("Description"))
+ .arg(i18n("Value"))
+ .arg(i18n("URL parameter"));
+
+ output += separator_row.arg(i18n("Formatting options"));
+ output += settingsBooleanOptionRow(i18n("Display verse numbers for Bible modules"), m_options.verseNumbers);
+ output += settingsBooleanOptionRow(i18n("Insert line breaks between Bible verses"), m_options.verseLineBreaks);
+ output += settingsBooleanOptionRow(i18n("Include footnotes."), m_options.footnotes);
+ output += settingsBooleanOptionRow(i18n("Words of Christ in red."), m_options.redWords);
+ output += settingsBooleanOptionRow(i18n("Display strongs numbers (for Bibles that include them)."), m_options.strongs);
+ output += settingsBooleanOptionRow(i18n("Display morphological tags (for Bibles that include them)."), m_options.morph);
+
+ output += separator_row.arg(i18n("Language"));
+
+ // Locale
+ QStringList locales = m_renderer.availableLocales();
+ temp = "";
+ for (int i = 0; i < locales.size(); i++)
+ {
+ temp += QString("<option value='%1' %3>%2</option>")
+ .arg(locales[i])
+ .arg(locales[i])
+ .arg((m_options.locale() == locales[i]) ? "selected" : "");
+ }
+ output += settingsGeneralOptionRow(i18n("Locale"), m_options.locale, temp);
+
+ // Formatting options
+ output += settingsBooleanOptionRow(i18n("Use Hebrew cantillation."), m_options.cantillation);
+ output += settingsBooleanOptionRow(i18n("Show Hebrew vowel points."), m_options.hebrewVowelPoints);
+ output += settingsBooleanOptionRow(i18n("Show Greek accents."), m_options.greekAccents);
+
+ output += separator_row.arg(i18n("Navigation options"));
+ output += settingsBooleanOptionRow(i18n("Display the whole book when a Bible book is selected, instead of an index of the chapters"),
+ m_options.wholeBook);
+ output += settingsBooleanOptionRow(i18n("Display the booklist for bibles if no book is requested"),
+ m_options.doBibleIndex);
+ output += settingsBooleanOptionRow(i18n("Display an index for dictionaries if no entry is requested"),
+ m_options.doDictIndex);
+ output += settingsBooleanOptionRow(i18n("Display an index for other books if no entry is request"),
+ m_options.doOtherIndex);
+ output += settingsBooleanOptionRow(i18n("Display a full index for books that have a multiple level index, instead of just the first level"),
+ m_options.doFullTreeIndex);
+
+
+ // Default modules
+ output += separator_row.arg(i18n("Default modules"));
+ modules = m_renderer.moduleList();
+
+ vector<QString> dm_desc;
+ vector<Option<QString> > dm_options;
+ vector<QString>::size_type i;
+ dm_desc.push_back(i18n("Default Bible"));
+ dm_options.push_back(m_options.defaultBible);
+
+ dm_desc.push_back(i18n("Default Greek Strong's Lexicon"));
+ dm_options.push_back(m_options.defaultGreekStrongs);
+
+ dm_desc.push_back(i18n("Default Hebrew Strong's Lexicon"));
+ dm_options.push_back(m_options.defaultHebrewStrongs);
+
+ dm_desc.push_back(i18n("Default Greek Morphological Lexicon"));
+ dm_options.push_back(m_options.defaultGreekMorph);
+
+ dm_desc.push_back(i18n("Default Hebrew Morphological Lexicon"));
+ dm_options.push_back(m_options.defaultHebrewMorph);
+
+ for (i = 0; i < dm_options.size(); i++) {
+ temp = QString("<option value='' %1> </option>")
+ .arg(dm_options[i]().stripWhiteSpace().isEmpty() ? "selected" : "");
+
+ for (it = modules.begin(); it != modules.end(); ++it ) {
+ temp += QString("<option value='%1' %3>%2</option>")
+ .arg(*it)
+ .arg(*it)
+ .arg(((*it) == dm_options[i]() ? "selected" : ""));
+ }
+ output += settingsGeneralOptionRow(dm_desc[i], dm_options[i], temp);
+ }
+
+ // Misc options
+ output += separator_row.arg(i18n("Other options"));
+ output += settingsBooleanOptionRow(i18n("Make formatting options propagate. This makes Kio-Sword remember formatting settings that you have set, by propagating them in the links. (Some navigation options are always excluded from this behaviour)."),
+ m_options.propagate);
+
+ output += QString("</table>");
+
+ output += i18n("<p>Notes:<br/>"
+ "1) These options never propagate<br/>"
+ "2) These options are never saved<br/></p>");
+
+ output += QString(
+ "<br><input type='hidden' name='module' value='%1'>" // redirection path
+ "<input type='hidden' name='query' value='%2'>" // redirection path
+ "<input type='submit' name='testsettings' value='%3'>&nbsp;" // "Test settings"
+ "<input type='submit' name='savesettings' value='%4''>" // "Save settings"
+ "</form>")
+ .arg(m_previous.module)
+ .arg(m_previous.query)
+ .arg(i18n("Test settings"))
+ .arg(i18n("Save settings"));
+
+ output += i18n("<hr><h1>Stylesheet</h1>"
+ "<p>To further customise the appearance of the Kio-Sword page, you can make your own modified "
+ "version of the style sheet. "
+ "Simply copy the file '%1kio_sword/kio_sword.css' to $HOME/.kde/share/apps/kio_sword/ and modify it as desired. You may want to use the 'simplepage' option above to make the most of this.</p>")
+ .arg(KGlobal::dirs()->findResourceDir("data", "kio_sword/kio_sword.css")); // FIXME - this must always return the system dir, not users dir.
+
+
+ return output;
+ }
+
+ QString SwordProtocol::helpPage() {
+ if (help_page.isEmpty()) {
+ help_page += i18n("<h1>Help</h1>"
+ "<p>For full documentation, see <a href=\"help:/kio_sword\">installed help files</a>.</p>"
+ "<p>Kio-Sword allows you to view SWORD modules (such as Bibles and commentaries) from Konqueror.\n"
+ " These modules must already be installed - you can download them from <a href=\"http://www.crosswire.org/\">"
+ "crosswire.org</a> or you can use a program such as <a href=\"http:/www.bibletime.info\">BibleTime</a> to help"
+ " install them."
+ "<h3>Quick help</h3>\n"
+ "<ul>\n"
+ " <li>To start, simply type <b><a href=\"sword:/\">sword:/</a></b> in the location bar, and follow the links like any normal web page<br /><br />\n"
+ " <li>You can type the exact reference in the Location bar, instead of browsing to it, e.g.<br />\n"
+ " <b>sword:/KJV/Hebrews 1:3-5</b> will look up Hebrews chapter 1 verses 3 to 5 in the King James Bible.<br /><br /></li>\n"
+ " <li>You can specify various formatting options in the URL - see <a href=\"sword:/?settings\">Settings</a> for more info.<br /><br /></li>\n"
+ " <li>To use your default Bible, just omit the first forward slash: <b>sword:Hebs 1:3-5</b> <br /><br /></li>\n"
+ " <li>You can bookmark Kio-Sword pages just like any other web page.<br /><br /></li>\n"
+ " <li>You can use keyboards shortcuts - press 'Ctrl' to activate 'Acess Keys' in Konqueror, \n"
+ " and the following shortcuts are then available:"
+ " <ul><li>'u' to go up</li>\n"
+ " <li>'n' for next section/chapter</li>\n"
+ " <li>'p' for previous section/chapter</li>\n"
+ " <li>'t' for the module list</li>\n"
+ " <li>'v' to toggle verse numbers</li>\n"
+ " <li>'l' to toggle line breaks between verses</li>\n"
+ " <li>'s' to toggle Strongs numbers</li>\n"
+ " <li>'m' to toggle morphological tags</li>\n"
+ " </ul>\n"
+ " (Depending on the context, some of these will either not be available or won't be much use).<br/><br/>"
+ " Also, remember the following Konqueror shortcuts to make keyboard navigation even better:<br/>"
+ " <b>/</b> starts find-as-you-type<br/>"
+ " <b>'</b> starts find-as-you-type for link text<br/>"
+ " </li>\n"
+ "</ul>\n"
+ "<p>Problems, comments, feature requests? Email the author. "
+ "<p>Author: <a href=\"mailto:L.Plant.98@cantab.net\">L.Plant.98@cantab.net</a>"
+ "<p>Website: <a href=\"http://lukeplant.me.uk/kio-sword/\">http://lukeplant.me.uk/kio-sword/</a>.");
+ }
+ return help_page;
+ }
+
+ QString SwordProtocol::searchForm(const SwordOptions& options) {
+ static const QString search_form_tmpl(
+ "<h1 class='searchform'>%1</h1>" // title
+ "<div class='searchform'>"
+ "<form action='sword:/' method='GET'>"
+ " <table class='searchform'>"
+ " <tr>"
+ " <td><label for='query'>%2</label></td>" // Search terms
+ " <td><input type='text' name='query'></td>"
+ " </tr>"
+ " <tr>"
+ " <td><label for='module'>%3</label></td>" // Module
+ " <td><select name='module'>"
+ " %4</select></td>" // (list of modules)
+ " </tr>"
+ " <tr>"
+ " <td valign='top'><label for='stype'>%5</label></td>" // Search type
+ " <td><input type='radio' name='stype' value='words' checked>%6<br>" // words
+ " <input type='radio' name='stype' value='phrase'>%7<br>" // phrase
+ " <input type='radio' name='stype' value='regex'>%8" // regex
+ " </td>"
+ " </tr>"
+ " <tr>"
+ " <td colspan='2' align='center'><input type='submit' name='searchq' value='%9'></td>" // Search
+ " </tr>"
+ " </table>"
+ "</form>"
+ "</div>");
+
+ if (search_form.isEmpty()) { // avoid calculating this twice
+ QStringList modules = m_renderer.moduleList();
+ QString temp;
+ QStringList::Iterator it;
+
+ temp = "<option value=''></option>";
+ for (it = modules.begin(); it != modules.end(); ++it ) {
+ temp += QString("<option value='%1' %3>%2</option>")
+ .arg(*it)
+ .arg(*it)
+ .arg((*it == m_options.defaultBible()) ? "selected='selected'" : "");
+ }
+ search_form = search_form_tmpl
+ .arg(i18n("Search"))
+ .arg(i18n("Search terms"))
+ .arg(i18n("Module"))
+ .arg(temp)
+ .arg(i18n("Search type"))
+ .arg(i18n("Words"))
+ .arg(i18n("Phrase"))
+ .arg(i18n("Regular expression"))
+ .arg(i18n("Search"));
+ }
+ // search_form is generated once, but we need to modify
+ // form each time to include propagated values
+ QString output(search_form);
+ return output.replace("</form>", optionsAsHiddenFields(options) + "</form>");
+ }
+}