diff options
Diffstat (limited to 'src/frontend/keychooser')
24 files changed, 2923 insertions, 0 deletions
diff --git a/src/frontend/keychooser/bthistory.cpp b/src/frontend/keychooser/bthistory.cpp new file mode 100644 index 0000000..7eae47f --- /dev/null +++ b/src/frontend/keychooser/bthistory.cpp @@ -0,0 +1,130 @@ +// +// C++ Implementation: BTHistory +// +// Description: +// +// +// Author: The BibleTime team <info@bibletime.info>, (C) 2007 +// +// Copyright: See COPYING file that comes with this distribution +// +// + +#include "bthistory.h" + +#include "backend/keys/cswordkey.h" + + +#include <QAction> +#include <QList> + +#include <QDebug> + + +BTHistory::BTHistory(QWidget* parent) + : m_historyList(), + m_index(-1), + m_inHistoryFunction(false) +{ + setParent(parent); + Q_ASSERT(class_invariant()); +} + +void BTHistory::add(CSwordKey* newKey) { + qDebug("BTHistory::add"); + Q_ASSERT(newKey); + // Add new key Action after current index if we were not using the history functions, + // if it's not a duplicate and if it's not empty. + if (!m_inHistoryFunction && ((m_index < 0) || (newKey->key() != m_historyList.at(m_index)->text()) )) + { + if (!newKey->key().isEmpty()) { + m_historyList.insert(++m_index, new QAction(newKey->key(), this)); + } + // TODO: history limit? + sendChangedSignal(); + } + Q_ASSERT(class_invariant()); +} + +void BTHistory::move(QAction* historyItem) +{ + qDebug("BTHistory::move"); + //Q_ASSERT(historyItem); + Q_ASSERT(m_historyList.count()); + + m_inHistoryFunction = true; + //find the action in the list + m_index = m_historyList.indexOf(historyItem); + //move to the selected item in the list, it will be the current item + QString newKey = m_historyList.at(m_index)->text(); + emit historyMoved(newKey); // signal to "outsiders"; key has been changed + sendChangedSignal(); + + m_inHistoryFunction = false; + Q_ASSERT(class_invariant()); +} + +void BTHistory::back() +{ + qDebug("BTHistory::back"); + if ( m_index >= 1) { + move(m_historyList.at(m_index-1)); + } + Q_ASSERT(class_invariant()); +} + +void BTHistory::fw() +{ + qDebug("BTHistory::fw"); + if (m_index < (m_historyList.size()-1)) { + move(m_historyList.at(m_index+1)); + } + Q_ASSERT(class_invariant()); +} + +QList<QAction*> BTHistory::getBackList() +{ + qDebug("BTHistory::getBackList"); + + QList<QAction*> list; + for (int i = m_index-1; i >= 0; --i) { + list.append(m_historyList.at(i)); + } + + qDebug() << "return:" << list; + Q_ASSERT(class_invariant()); + return list; +} + +QList<QAction*> BTHistory::getFwList() +{ + qDebug("BTHistory::getFwList"); + + QList<QAction*> list; + //qDebug() << "historyList.size:" << m_historyList.size(); + for (int i = m_index+1; i < m_historyList.size(); ++i) { + //qDebug() << "i:" << i; + list.append(m_historyList.at(i)); + } + qDebug() << "return:" << list; + + Q_ASSERT(class_invariant()); + return list; +} + +void BTHistory::sendChangedSignal() +{ + bool backEnabled = m_index > 0; //there are items in the back list + bool fwEnabled = m_historyList.size() > m_index+1; //there are items in the fw list + emit historyChanged(backEnabled, fwEnabled); + Q_ASSERT(class_invariant()); +} + +bool BTHistory::class_invariant() +{ + for (int i = 0; i < m_historyList.size(); ++i) { + if (!m_historyList.at(i) || m_historyList.at(i)->text().isEmpty()) return false; + } + if (!(m_index >= -1 && m_index < m_historyList.size())) return false; + return true; +} diff --git a/src/frontend/keychooser/bthistory.h b/src/frontend/keychooser/bthistory.h new file mode 100644 index 0000000..34e5fdb --- /dev/null +++ b/src/frontend/keychooser/bthistory.h @@ -0,0 +1,80 @@ +// +// C++ Interface: BTHistory +// +// Description: +// +// +// Author: The BibleTime team <info@bibletime.info>, (C) 2007 +// +// Copyright: See COPYING file that comes with this distribution +// +// + +#ifndef BTHISTORY_H +#define BTHISTORY_H + +#include <QList> +#include <QObject> + + +class CSwordKey; +class QAction; +class QWidget; + +class BTHistory: public QObject +{ + Q_OBJECT + +public: + BTHistory(QWidget* parent); + ~BTHistory() {}; + + /** + * Return a list of Actions behind the current point, the first of the history list will be the + * last in the returned list and vice versa. + */ + QList<QAction*> getBackList(); + /** + * Return a list of Actions after the current point. + */ + QList<QAction*> getFwList(); + +public slots: + /** + * Add a new key to the history. + */ + void add(CSwordKey* newKey); + /** + * Move the current point in history list. + */ + void move(QAction*); + /** + * Go back one step in history. + */ + void back(); + /** + * Go forward one step in history. + */ + void fw(); + +signals: + /** + * Signal will be sent when the history has been changed (added, moved) + */ + void historyChanged(bool backEnabled, bool fwEnabled); + /** + * Signal will be sent when the current point in history has moved + */ + void historyMoved(QString& newKey); + +private: + + void sendChangedSignal(); + bool class_invariant(); + + QList<QAction*> m_historyList; + int m_index; //pointer to the current item; -1==empty, 0==first etc. + bool m_inHistoryFunction; //to prevent recursive behaviour +}; + +#endif diff --git a/src/frontend/keychooser/cbookkeychooser.cpp b/src/frontend/keychooser/cbookkeychooser.cpp new file mode 100644 index 0000000..411bf26 --- /dev/null +++ b/src/frontend/keychooser/cbookkeychooser.cpp @@ -0,0 +1,278 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ +#include "cbookkeychooser.h" + +#include "bthistory.h" + +#include "backend/keys/cswordtreekey.h" +#include "backend/drivers/cswordbookmoduleinfo.h" +#include "backend/config/cbtconfig.h" + +//Qt includes +#include <QWidget> +#include <QHBoxLayout> +#include <QList> +#include <QDebug> + +QMap<QObject*, int> boxes; + +CBookKeyChooser::CBookKeyChooser(QList<CSwordModuleInfo*> modules, CSwordKey *key, QWidget *parent) + : CKeyChooser(modules, key, parent), m_layout(0) +{ + + setModules(modules, false); + m_key = dynamic_cast<CSwordTreeKey*>(key); + if (!m_modules.count()) { + m_key = 0; + } + + setModules(modules, true); + setKey(key); + + adjustFont(); + connect(this, SIGNAL(keyChanged(CSwordKey*)), history(), SLOT(add(CSwordKey*)) ); +} + +CBookKeyChooser::~CBookKeyChooser() {} + +void CBookKeyChooser::setKey(CSwordKey* newKey) +{ + setKey(newKey, true); +} + +/** Sets a new key to this keychooser */ +void CBookKeyChooser::setKey(CSwordKey* newKey, const bool emitSignal) +{ + if (m_key != newKey) { //set the internal key to the new one + m_key = dynamic_cast<CSwordTreeKey*>(newKey); + } + + QString oldKey = m_key->key(); //string backup of key + + if (oldKey.isEmpty()) { //don't set keys equal to "/", always use a key which may have content + m_key->firstChild(); + oldKey = m_key->key(); + } + + const int oldOffset = m_key->getOffset(); //backup key position + + QStringList siblings; //split up key + if (m_key && !oldKey.isEmpty()) { + siblings = oldKey.split('/', QString::SkipEmptyParts); + } + + int depth = 0; + int index = 0; + + m_key->root(); //start iteration at root node + + while( m_key->firstChild() && (depth < siblings.count()) ) { + QString key = m_key->key(); + index = (depth == 0) ? -1 : 0; + + bool found = false; + + do { //look for matching sibling + ++index; + found = (m_key->getLocalNameUnicode() == siblings[depth]); + } + while (!found && m_key->nextSibling()); + + if (found) + key = m_key->key(); //found: change key to this level + else + m_key->key(key); //not found: restore old key + + setupCombo(key, depth, index); + + //last iteration: check to see if another box can be filled with child entries + if (depth == siblings.count()-1 && m_key->hasChildren()) + { + m_key->firstChild(); + setupCombo(m_key->key(), ++depth, 0); + } + + depth++; + } + + //clear the combos which were not filled + for (; depth < m_modules.first()->depth(); ++depth) { + CKeyChooserWidget* chooser = m_chooserWidgets.at(depth); + if (chooser) chooser->reset(0,0,false); + } + + if (oldKey.isEmpty()) { + m_key->root(); + } + else { + //m_key->key(oldKey); + m_key->setOffset(oldOffset); + } + + if (emitSignal) emit keyChanged(m_key); +} + +/** Returns the key of this kechooser. */ +CSwordKey* CBookKeyChooser::key() +{ + return m_key; +} + +/** Sets another module to this keychooser */ +void CBookKeyChooser::setModules(const QList<CSwordModuleInfo*>& modules, const bool refresh) +{ + m_modules.clear(); + + // for (modules.first(); modules.current(); modules.next()) { + QList<CSwordModuleInfo*>::const_iterator end_it = modules.end(); + for (QList<CSwordModuleInfo*>::const_iterator it(modules.begin()); it != end_it; ++it) { + if ( (*it)->type() == CSwordModuleInfo::GenericBook ) { + if (CSwordBookModuleInfo* book = dynamic_cast<CSwordBookModuleInfo*>(*it)) { + m_modules.append(book); + } + } + } + + //refresh the number of combos + if (refresh && m_modules.count() && m_key) { + if (!m_layout) { + m_layout = new QHBoxLayout(this); + m_layout->setSpacing(0); + m_layout->setContentsMargins(0,0,0,0); + } + + qDeleteAll(m_chooserWidgets); + m_chooserWidgets.clear(); + + for (int i = 0; i < m_modules.first()->depth(); ++i) { + // Create an empty keychooser, don't handle next/prev signals + CKeyChooserWidget* w = new CKeyChooserWidget(0, false, this); + m_chooserWidgets.append( w ); + + //don't allow a too high width, try to keep as narrow as possible + //to aid users with smaller screen resolutions + int totalWidth = 200; //only 1 level + if (m_modules.first()->depth() > 1) { + if (m_modules.first()->depth() > 3) + totalWidth = 400; //4+ levels + else + totalWidth = 300; //2-3 levels + } + + int maxWidth = (int) ((float) totalWidth / (float) m_modules.first()->depth()); + + w->comboBox()->setMaximumWidth(maxWidth); + w->comboBox()->setCurrentIndex(0); + + connect(w, SIGNAL(changed(int)), SLOT(keyChooserChanged(int))); + connect(w, SIGNAL(focusOut(int)), SLOT(keyChooserChanged(int))); + + m_layout->addWidget(w); + boxes[w] = i; + + w->show(); + } + + //set the tab order of the key chooser widgets + + CKeyChooserWidget* chooser = 0; + CKeyChooserWidget* chooser_prev = 0; + const int count = m_chooserWidgets.count(); + for (int i = 0; i < count; ++i) { + chooser = m_chooserWidgets.at(i); + Q_ASSERT(chooser); + + if (chooser && chooser_prev) { + QWidget::setTabOrder(chooser_prev, chooser); + } + + chooser_prev = chooser; + } + QWidget::setTabOrder(chooser, 0); + + updateKey(m_key); + adjustFont(); // only when refresh is set. + } +} + +/** No descriptions */ +void CBookKeyChooser::adjustFont() +{ + //Make sure the entries are displayed correctly. + QListIterator<CKeyChooserWidget*> it(m_chooserWidgets); + while (it.hasNext()) { + it.next()->comboBox()->setFont( CBTConfig::get( m_modules.first()->language() ).second ); + } +} + +/** Refreshes the content. */ +void CBookKeyChooser::refreshContent() +{ + if (m_key) { + updateKey( m_key ); //refresh with current key + } +} + +void CBookKeyChooser::setupCombo(const QString key, const int depth, const int currentItem) +{ + CKeyChooserWidget* chooserWidget = m_chooserWidgets.at(depth); + + CSwordTreeKey tmpKey(*m_key); + tmpKey.key(key); + tmpKey.parent(); + tmpKey.firstChild(); + + QStringList items; + if (depth > 0) items << QString::null; //insert an empty item at the top + + do { + items << tmpKey.getLocalNameUnicode(); + } + while (tmpKey.nextSibling()); + + if (chooserWidget) chooserWidget->reset(items,currentItem,false); +} + +/** A keychooser changed. Update and emit a signal if necessary. */ +void CBookKeyChooser::keyChooserChanged(int /*newIndex*/) +{ + const int activeID = boxes[const_cast<QObject*>(sender())]; //no so good code! + + QStringList items; + CKeyChooserWidget* chooser; + + for (int i = 0; i < m_chooserWidgets.count(); ++i) { + chooser = m_chooserWidgets.at(i); + const QString currentText = (chooser && chooser->comboBox()) ? chooser->comboBox()->currentText() : QString::null; + + if (currentText.isEmpty() || i > activeID) { + break; + } + + items << currentText; + } + + QString newKey("/"); + newKey.append(items.join("/")); + + m_key->key(newKey); + setKey(m_key); +} + +/** Updates the keychoosers for the given key but emit no signal. */ +void CBookKeyChooser::updateKey(CSwordKey* key) +{ + setKey(key, false); +} + +void CBookKeyChooser::setKey(QString& newKey) +{ + m_key->key(newKey); + setKey(m_key); +} diff --git a/src/frontend/keychooser/cbookkeychooser.h b/src/frontend/keychooser/cbookkeychooser.h new file mode 100644 index 0000000..80dd03f --- /dev/null +++ b/src/frontend/keychooser/cbookkeychooser.h @@ -0,0 +1,86 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + +#ifndef CBOOKKEYCHOOSER_H +#define CBOOKKEYCHOOSER_H + +//BibleTime includes +#include "ckeychooser.h" +#include "ckeychooserwidget.h" + +#include <QList> + +class CSwordKey; +class CSwordBookModuleInfo; +class CSwordTreeKey; + +namespace sword { + class TreeKeyIdx; +} + +/** The keychooser implementation for books. + * @author The BibleTime team + */ +class CBookKeyChooser : public CKeyChooser { + Q_OBJECT +public: + CBookKeyChooser(QList<CSwordModuleInfo*> modules, CSwordKey *key=0, QWidget *parent=0); + ~CBookKeyChooser(); + /** + * Refreshes the content. + */ + virtual void refreshContent(); + /** + * Sets another module to this keychooser + */ + virtual void setModules(const QList<CSwordModuleInfo*>& modules, const bool refresh = false); + /** + * Returns the key of this keychooser + */ + virtual CSwordKey* key(); + /** + * Sets a new key to this keychooser + */ + virtual void setKey(CSwordKey*); + /** + * Sets a new key to this keychooser + */ + void setKey(CSwordKey*, const bool emitSignal); + + +public slots: // Public slots + /** + * Updates the keychoosers for the given key but emit no signal. + */ + void updateKey(CSwordKey*); + +protected: // Protected methods + /** + * Fills the combo given by depth with the items from the key having depth "depth". + * The parent sibling is given by key. + */ + void setupCombo(const QString key, const int depth, const int currentItem); + /** No descriptions */ + virtual void adjustFont(); + +protected slots: + /** + * A keychooser changed. Update and emit a signal if necessary. + */ + void keyChooserChanged(int); + virtual void setKey(QString& newKey); + +private: + QList<CKeyChooserWidget*> m_chooserWidgets; + QList<CSwordBookModuleInfo*> m_modules; + CSwordTreeKey *m_key; + QHBoxLayout* m_layout; +}; + +#endif diff --git a/src/frontend/keychooser/cbooktreechooser.cpp b/src/frontend/keychooser/cbooktreechooser.cpp new file mode 100644 index 0000000..7297d76 --- /dev/null +++ b/src/frontend/keychooser/cbooktreechooser.cpp @@ -0,0 +1,200 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ +#include "cbooktreechooser.h" + +#include "bthistory.h" + +#include "backend/keys/cswordtreekey.h" +#include "backend/drivers/cswordbookmoduleinfo.h" +#include "backend/config/cbtconfig.h" + +#include <QHBoxLayout> +#include <QTreeWidget> +#include <QTreeWidgetItem> +#include <QHeaderView> +#include <QApplication> + +#include <QDebug> + +CBookTreeChooser::CBookTreeChooser(QList<CSwordModuleInfo*> modules, CSwordKey *key, QWidget *parent) +: CKeyChooser(modules, key, parent), +m_key( dynamic_cast<CSwordTreeKey*>(key) ) { + + setModules(modules, false); + + //if there is no module there is no key either + if (!modules.count()) { + m_modules.clear(); + m_key = 0; + } + + //now setup the keychooser widgets + m_treeView = new QTreeWidget(this); + + QHBoxLayout* layout = new QHBoxLayout(this); + layout->setSpacing(0); + layout->setContentsMargins(0,0,0,0); + layout->addWidget(m_treeView); + m_treeView->header()->hide(); + + //when user selects the item whe must react + connect(m_treeView, SIGNAL(currentItemChanged ( QTreeWidgetItem*, QTreeWidgetItem*)), SLOT(itemActivated(QTreeWidgetItem*))); + + setKey(key); + adjustFont(); + connect(this, SIGNAL(keyChanged(CSwordKey*)), history(), SLOT(add(CSwordKey*)) ); +} + +CBookTreeChooser::~CBookTreeChooser() {} + +/** Sets a new key to this keychooser. Inherited from ckeychooser. */ +void CBookTreeChooser::setKey(CSwordKey* key) { + setKey(key, false); +} + +/** Sets a new key to this keychooser. Inherited from ckeychooser. */ +void CBookTreeChooser::setKey(CSwordKey* newKey, const bool emitSignal) { + qDebug("CBookTreeChooser::setKey"); + + if (m_key != newKey ) { + m_key = dynamic_cast<CSwordTreeKey*>(newKey); + } + + const QString key = m_key->key(); //key as text, path + + QTreeWidgetItem* matching_item = m_treeView->topLevelItem(0); + + QTreeWidgetItemIterator it(m_treeView); + while (*it) { + if ((*it)->text(1) == key) + { + matching_item = (*it); + break; + } + ++it; + } + + m_treeView->setCurrentItem( matching_item ); + m_treeView->scrollToItem(matching_item); + + if (emitSignal) { + emit keyChanged(m_key); + } +} + +/** Returns the key of this keychooser. Inherited from ckeychooser.*/ +CSwordKey* CBookTreeChooser::key() { + return m_key; +} + +/** Sets another module to this keychooser. Inherited from ckeychooser (therefore +the list of modules instead of one). */ +void CBookTreeChooser::setModules(const QList<CSwordModuleInfo*>& modules, const bool refresh) { + + //Add given modules into private list + m_modules.clear(); + QList<CSwordModuleInfo*>::const_iterator end_it = modules.end(); + for (QList<CSwordModuleInfo*>::const_iterator it(modules.begin()); it != end_it; ++it) { + if (CSwordBookModuleInfo* book = dynamic_cast<CSwordBookModuleInfo*>(*it)) { + m_modules.append(book); + } + } + + //if there exists a module and a key, setup the visible tree + if (refresh && m_modules.count() && m_key) { + const uint offset = m_key->getOffset(); //actually unnecessary, taken care of in setupTree + setupTree(); + m_key->setOffset( offset ); + + adjustFont(); //only when refresh is set. + } +} + +/** From ckeychooser. */ +void CBookTreeChooser::adjustFont() { + //Make sure the entries are displayed correctly. + m_treeView->setFont( CBTConfig::get(m_modules.first()->language()).second ); + +} + + +/** Refreshes the content. Inherited from ckeychooser. */ +void CBookTreeChooser::refreshContent() { + if (m_key) { + updateKey(m_key); //refresh with current key + } +} + + +//TODO: itemActivated is called too many times. As tested in GDB, the function +//is called twice with the pointer to the correct book and twice with a null +//pointer. + +/** Slot for signal when item is selected by user. */ +void CBookTreeChooser::itemActivated( QTreeWidgetItem* item ) { + qDebug("CBookTreeChooser::itemActivated"); + //Sometimes Qt calls this function with a null pointer. + if (item){ + m_key->key(item->text(1)); + //tell possible listeners about the change + emit keyChanged(m_key); + } +} + +/** Inherited from ckeychooser */ +void CBookTreeChooser::updateKey( CSwordKey* key ) { + setKey(key, false); +} + +/** Reimplementation to handle tree creation on show. */ +void CBookTreeChooser::show() { + CKeyChooser::show(); + + if (!m_treeView->topLevelItemCount()) { + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + setupTree(); //create the tree structure + m_treeView->resize(m_treeView->sizeHint()); + QApplication::restoreOverrideCursor(); + } +} + +/** Creates the tree structure in the view. */ +void CBookTreeChooser::setupTree() { + m_treeView->clear(); + + const unsigned long offset = m_key->getOffset(); + + m_key->root(); + addKeyChildren(m_key, m_treeView->invisibleRootItem()); + + m_key->setOffset( offset ); + setKey(m_key, false); //the module may have changed +} + +/** Populates tree widget with items. */ +void CBookTreeChooser::addKeyChildren(CSwordTreeKey* key, QTreeWidgetItem* item) { + if (key->hasChildren()) { + key->firstChild(); + do { + QStringList columns; + columns << key->getLocalNameUnicode() << key->key(); + QTreeWidgetItem *i = new QTreeWidgetItem(item, columns, QTreeWidgetItem::Type); + i->setData(0, Qt::ToolTipRole, key->getLocalNameUnicode()); + int offset = key->getOffset(); + addKeyChildren(key, i); + key->setOffset(offset); + } while (key->nextSibling()); + } +} + +void CBookTreeChooser::setKey(QString& newKey) +{ + m_key->key(newKey); + setKey(m_key); +} diff --git a/src/frontend/keychooser/cbooktreechooser.h b/src/frontend/keychooser/cbooktreechooser.h new file mode 100644 index 0000000..455ba01 --- /dev/null +++ b/src/frontend/keychooser/cbooktreechooser.h @@ -0,0 +1,87 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + + + +#ifndef CBOOKTREECHOOSER_H +#define CBOOKTREECHOOSER_H + + +/** The treechooser implementation for books. + * @author The BibleTime team + */ +//BibleTime includes +#include "ckeychooser.h" +#include "ckeychooserwidget.h" + + +class CSwordKey; +class CSwordBookModuleInfo; +class CSwordTreeKey; + +namespace sword { + class TreeKeyIdx; +} + +class QTreeWidget; +class QTreeWidgetItem; + +/** The keychooser implementation for books. + * @author The BibleTime team + */ +class CBookTreeChooser : public CKeyChooser { + Q_OBJECT +public: + CBookTreeChooser(QList<CSwordModuleInfo*> modules, CSwordKey *key=0, QWidget *parent=0); + ~CBookTreeChooser(); + /** + * Refreshes the content. + */ + virtual void refreshContent(); + /** + * Sets another module to this keychooser + */ + virtual void setModules(const QList<CSwordModuleInfo*>& modules, const bool refresh = true); + /** + * Returns the key of this keychooser. + */ + virtual CSwordKey* key(); + /** + * Sets a new key to this keychooser + */ + virtual void setKey(CSwordKey*); + void setKey(CSwordKey*, const bool emitSinal); + +public slots: // Public slots + virtual void updateKey( CSwordKey* ); + /** + * Reimplementation to handle tree creation on show. + */ + virtual void show(); + + +protected: // Protected methods + /** + * Creates the first level of the tree structure. + */ + void setupTree(); + virtual void adjustFont(); + void addKeyChildren(CSwordTreeKey* key, QTreeWidgetItem* item); + +protected slots: // Protected slots + void itemActivated( QTreeWidgetItem* item ); + void setKey(QString& newKey); + +private: + QList<CSwordBookModuleInfo*> m_modules; + CSwordTreeKey* m_key; + QTreeWidget* m_treeView; +}; + +#endif diff --git a/src/frontend/keychooser/ckeychooser.cpp b/src/frontend/keychooser/ckeychooser.cpp new file mode 100644 index 0000000..f0650d6 --- /dev/null +++ b/src/frontend/keychooser/ckeychooser.cpp @@ -0,0 +1,64 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + + + +#include "ckeychooser.h" + +#include "backend/drivers/cswordmoduleinfo.h" +#include "backend/drivers/cswordbiblemoduleinfo.h" +#include "backend/drivers/cswordcommentarymoduleinfo.h" +#include "backend/drivers/cswordlexiconmoduleinfo.h" + +#include "backend/keys/cswordkey.h" + +#include "bthistory.h" +#include "clexiconkeychooser.h" +#include "versekeychooser/cbiblekeychooser.h" +#include "cbookkeychooser.h" + +#include <QAction> +#include <QDebug> + +CKeyChooser::CKeyChooser(QList<CSwordModuleInfo*>, CSwordKey *, QWidget *parent) + : QWidget(parent), + m_history(0) +{ + //qDebug("CKeyChooser::CKeyChooser"); + m_history = new BTHistory(this); + QObject::connect(history(), SIGNAL(historyMoved(QString&)), this, SLOT(setKey(QString&))); +} + +CKeyChooser::~CKeyChooser() {} + +CKeyChooser* CKeyChooser::createInstance(QList<CSwordModuleInfo*> modules, CSwordKey *key, QWidget *parent) { + if (!modules.count()) { + return 0; + } + + switch ( modules.first()->type() ) { + case CSwordModuleInfo::Commentary: //Bibles and commentaries use the same key chooser + case CSwordModuleInfo::Bible: + return new CBibleKeyChooser(modules,key,parent); + break; + case CSwordModuleInfo::Lexicon: + return new CLexiconKeyChooser(modules,key,parent); + case CSwordModuleInfo::GenericBook: + return new CBookKeyChooser(modules,key,parent); + default: + return 0; + } +} + + +BTHistory* CKeyChooser::history() +{ + return m_history; +} + diff --git a/src/frontend/keychooser/ckeychooser.h b/src/frontend/keychooser/ckeychooser.h new file mode 100644 index 0000000..d10a74a --- /dev/null +++ b/src/frontend/keychooser/ckeychooser.h @@ -0,0 +1,115 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + + + +#ifndef CKEYCHOOSER_H +#define CKEYCHOOSER_H + + +class CSwordModuleInfo; + +#include <QWidget> + + +class CSwordKey; +class QAction; + +class BTHistory; + + +/** + * The base class for the KeyChooser. + * Do not use directly, create a KeyChooser with + * @ref #createInstance , this will create the proper one + * of the classes that inherit from @ref CKeyChooser + * + * @author The BibleTime team + */ + +class CKeyChooser : public QWidget { + Q_OBJECT + +public: + + /** + * Creates a proper Instance, either + * + @ref CLexiconKeyChooser or + * @ref CBibleKeyChooser + * @param info the @ref CModuleInfo to be represented by the KeyChooser + * @param key if not NULL, the @ref CKey the KeyChooser should be set to + * @param parent the parent of the widget to create + */ + static CKeyChooser* createInstance(QList<CSwordModuleInfo*> modules, CSwordKey *key, QWidget *parent); + + +public slots: + /** + * sets the @ref CKey + * @param key the key which the widget should be set to + */ + virtual void setKey(CSwordKey* key) = 0; + /** + * sets the @ref CKey + * @param key the key which the widget should be set to + */ + virtual void updateKey(CSwordKey* key) = 0; + /** + * gets the current @ref CKey + * + * @return the current @ref CKey + */ + virtual CSwordKey* key() = 0; + /** + * Sets the module of this keychooser and refreshes the comboboxes + */ + virtual void setModules( const QList<CSwordModuleInfo*>& modules, const bool refresh = true ) = 0; + /** + * Freshes the content of the different key chooser parts. + */ + virtual void refreshContent() = 0; + + /** + * Returns the history object of this keychooser. + */ + BTHistory* history(); + +signals: + + /** + * is emitted if the @ref CKey was changed by the user + */ + void keyChanged(CSwordKey* newKey); + /** + * Is emitted before the key is changed! + */ + void beforeKeyChange(const QString& key); + +protected: + + /** + * the constructor - DO NOT USE! -- use @ref #createInstance instead! + */ + CKeyChooser(QList<CSwordModuleInfo*> info, CSwordKey *key=0, QWidget *parent=0); + virtual ~CKeyChooser(); + /** + * Set the appropriate font do display the modules + */ + virtual void adjustFont() = 0; + +protected slots: + virtual void setKey(QString& newKey) = 0; + +private: + BTHistory* m_history; + +}; + +#endif diff --git a/src/frontend/keychooser/ckeychooserwidget.cpp b/src/frontend/keychooser/ckeychooserwidget.cpp new file mode 100644 index 0000000..dd8f7a5 --- /dev/null +++ b/src/frontend/keychooser/ckeychooserwidget.cpp @@ -0,0 +1,304 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + + +//BibleTime includes +#include "ckeychooserwidget.h" + +#include "cscrollerwidgetset.h" + +//Qt includes +#include <QString> +#include <QWheelEvent> +#include <QFocusEvent> +#include <QHBoxLayout> +#include <QComboBox> +#include <QLineEdit> +#include <QDebug> + +CKCComboBox::CKCComboBox() +: QComboBox() { + setFocusPolicy(Qt::WheelFocus); + if (lineEdit()) { + installEventFilter( lineEdit() ); + } +} + +/** Reimplementation. */ +bool CKCComboBox::eventFilter( QObject *o, QEvent *e ) { + if (e->type() == QEvent::FocusOut) { + QFocusEvent* f = static_cast<QFocusEvent*>(e); + + if (o == lineEdit() && f->reason() == Qt::TabFocusReason) { + int index = findText(currentText()); + if (index == -1) { + index = 0;// return 0 if not found + } + setCurrentIndex( index ); + emit focusOut( index ); + + return false; + } + else if (f->reason() == Qt::PopupFocusReason) { + return false; + } + else if (f->reason() == Qt::ActiveWindowFocusReason) { + emit activated(currentText()); + return false; + } + else if (f->reason() == Qt::MouseFocusReason) { + emit activated(currentText()); + return false; + } + else if (o == this) { + emit activated(currentText()); + return false; + } + } + + return QComboBox::eventFilter(o,e); +} + +/** Scrolls in the list if the wheel of the mouse was used. */ +void CKCComboBox::wheelEvent( QWheelEvent* e ) { + return QComboBox::wheelEvent(e); + + const signed int change = (int)((float)e->delta()/(float)120); + int current = currentIndex(); + + if ((current+change >= 0) && (current+change<count()) ) { + setCurrentIndex(current+change); + e->accept(); + emit activated( currentIndex() ); + } + else { + e->ignore(); + } +} + +//**********************************************************************************/ + +CKeyChooserWidget::CKeyChooserWidget(int count, const bool useNextPrevSignals, QWidget *parent ) : QWidget(parent) { + m_useNextPrevSignals = useNextPrevSignals; + + for (int index=1; index <= count; index++) { + m_list.append( QString::number(index) ); + } + init(); + reset(m_list,0,false); +} + +CKeyChooserWidget::CKeyChooserWidget(QStringList *list, const bool useNextPrevSignals, QWidget *parent ) : QWidget(parent) { + m_useNextPrevSignals = useNextPrevSignals; + + if (list) { + m_list = *list; //deep copy the items of list + } + else { + m_list.clear(); + } + + init(); + reset(m_list,0,false); +} + +void CKeyChooserWidget::reset(const int count, int index, bool do_emit) { + //This prevents the widget from resetting during application load, which + //produces undesirable behavior. + //if (!updatesEnabled()) + // return; + + m_list.clear(); + for (int i=1; i <= count; i++) { //TODO: CHECK + m_list.append( QString::number(i) ); + } + + reset(&m_list,index,do_emit); +} + +void CKeyChooserWidget::reset(QStringList& list, int index, bool do_emit) { + //This prevents the widget from resetting during application load, which + //produces undesirable behavior. + //if (!updatesEnabled()) + // return; + + m_list = list; + reset(&m_list,index,do_emit); +} + + +void CKeyChooserWidget::reset(QStringList *list, int index, bool do_emit) { + //if (isResetting || !updatesEnabled()) + if (isResetting) + return; + + // qWarning("starting insert"); + isResetting = true; + + oldKey = QString::null; + + // m_comboBox->setUpdatesEnabled(false); + //DON'T REMOVE THE HIDE: Otherwise QComboBox's sizeHint() function won't work properly + m_comboBox->hide(); + m_comboBox->clear(); + if (list) { + m_comboBox->insertItems(-1, *list); + } + + if (!list || (list && !list->count())) { //nothing in the combobox + setEnabled(false); + } + else if (!isEnabled()) { //was disabled + setEnabled(true); + } + + if (list->count()) { + m_comboBox->setCurrentIndex(index); + } + if (do_emit) { + emit changed(m_comboBox->currentIndex()); + } + + const QSize dummySize = m_comboBox->sizeHint(); //without this function call the combo box won't be properly sized! + //DON'T REMOVE OR MOVE THE show()! Otherwise QComboBox's sizeHint() function won't work properly! + m_comboBox->show(); + + // m_comboBox->setFont( m_comboBox->font() ); + // m_comboBox->setUpdatesEnabled(true); + + isResetting = false; + // qWarning("inserted"); +} + +/** Initializes this widget. We need this function because we have more than one constructor. */ +void CKeyChooserWidget::init() { + qDebug("CKeyChooserWidget::init"); + oldKey = QString::null; + + setFocusPolicy(Qt::WheelFocus); + + m_comboBox = new CKCComboBox(); + m_comboBox->setAutoCompletion( true ); + m_comboBox->setEditable(true); + m_comboBox->setInsertPolicy(QComboBox::NoInsert); + m_comboBox->setFocusPolicy(Qt::WheelFocus); + + m_mainLayout = new QHBoxLayout( this ); + m_mainLayout->setSpacing(0); + m_mainLayout->setContentsMargins(0,0,0,0); + m_mainLayout->addWidget(m_comboBox); + + m_scroller = new CScrollerWidgetSet(this); + + m_mainLayout->addWidget( m_scroller ); + m_mainLayout->addSpacing(0); + + setTabOrder(m_comboBox, 0); + + connect(m_scroller, SIGNAL(scroller_pressed()), SLOT(lock())); + connect(m_scroller, SIGNAL(scroller_released()), SLOT(unlock())); + connect(m_scroller, SIGNAL(change(int)), SLOT(changeCombo(int)) ); + + connect(m_comboBox, SIGNAL(activated(int)), SLOT(slotComboChanged(int))); + // connect(m_comboBox, SIGNAL(activated(const QString&)), SLOT(slotReturnPressed(const QString&))); + connect(m_comboBox->lineEdit(), SIGNAL(returnPressed()), SLOT(slotReturnPressed())); + connect(m_comboBox, SIGNAL(focusOut(int)), SIGNAL(focusOut(int))); + + updatelock = false; + isResetting = false; +} + +/** Is called when the return key was presed in the combobox. */ +void CKeyChooserWidget::slotReturnPressed( /*const QString& text*/) { + Q_ASSERT(comboBox()->lineEdit()); + qDebug("return pressed"); + + QString text = comboBox()->lineEdit()->text(); + for (int index = 0; index < comboBox()->count(); ++index) { + if (comboBox()->itemText(index) == text) { +// emit changed(index); + emit focusOut(index); // a workaround because focusOut is not checked, the slot connected to changed to check + break; + } + } +} + +/** Is called when the current item of the combo box was changed. */ +void CKeyChooserWidget::slotComboChanged(int index) { + qDebug("CKeyChooserWidget::slotComboChanged(int index)"); + if (!updatesEnabled()) { + return; + } + + setUpdatesEnabled(false); + + const QString key = comboBox()->itemText( index ); + if (oldKey.isNull() || (oldKey != key)) { + emit changed(index); + } + + oldKey = key; + + setUpdatesEnabled(true); +} + +/** Sets the tooltips for the given entries using the parameters as text. */ +void CKeyChooserWidget::setToolTips( const QString comboTip, const QString nextEntryTip, const QString scrollButtonTip, const QString previousEntryTip) { + comboBox()->setToolTip(comboTip); + m_scroller->setToolTips(nextEntryTip, scrollButtonTip, previousEntryTip); +} + +/** Sets the current item to the one with the given text */ +bool CKeyChooserWidget::setItem( const QString item ) { + bool ret = false; + const int count = comboBox()->count(); + for (int i = 0; i < count; ++i) { + if (comboBox()->itemText(i) == item) { + comboBox()->setCurrentIndex(i); + ret = true; + break; + } + } + if (!ret) + comboBox()->setCurrentIndex(-1); + return ret; +} + +/* Handlers for the various scroller widgetset. */ +void CKeyChooserWidget::lock() { + updatelock = true; + comboBox()->setEditable(false); + oldKey = comboBox()->currentText(); +} + +void CKeyChooserWidget::unlock() { + updatelock = false; + comboBox()->setEditable(true); + comboBox()->setEditText(comboBox()->itemText(comboBox()->currentIndex())); + if (comboBox()->currentText() != oldKey) { + emit changed(comboBox()->currentIndex()); + } +} + +void CKeyChooserWidget::changeCombo(int n) { + const int old_index = comboBox()->currentIndex(); + int new_index = old_index + n; + + //index of highest Item + const int max = comboBox()->count()-1; + if(new_index > max) new_index = max; + if(new_index < 0) new_index = 0; + + if(new_index != old_index) { + comboBox()->setCurrentIndex(new_index); + if(!updatelock) + emit changed(new_index); + } +} + diff --git a/src/frontend/keychooser/ckeychooserwidget.h b/src/frontend/keychooser/ckeychooserwidget.h new file mode 100644 index 0000000..05b0236 --- /dev/null +++ b/src/frontend/keychooser/ckeychooserwidget.h @@ -0,0 +1,171 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + +#ifndef CKEYCHOOSERWIDGET_H +#define CKEYCHOOSERWIDGET_H + + +#include <QString> +#include <QStringList> +#include <QComboBox> + +class QWheelEvent; +class QHBoxLayout; +class QWidget; +class QObject; +class QEvent; + +class CLexiconKeyChooser; +class CScrollerWidgetSet; +/* +* We use this class to conrtol the focus move in the combobox +* This class is used in the key chooser widgets +*/ +class CKCComboBox : public QComboBox { + Q_OBJECT + +public: + CKCComboBox(); + /** + * Returns the size this widget would like to have. + */ + // virtual QSize sizeHint() const; + +protected: + /** + * Reimplementation. + */ + virtual bool eventFilter( QObject *o, QEvent *e ); + /** + * Scrolls in the list if the wheel of the mouse was used. + */ + virtual void wheelEvent( QWheelEvent* e); + +signals: + /** + * Emitted when the user moves the focus away from the combo by pressing tab + */ + void focusOut(int itemIndex); +}; + +/** + * This class implements the KeyCooser Widget, which + * consists of a @ref QComboBox, two normal ref @QToolButton + * and a enhanced @ref CScrollButton + * + * @author The BibleTime team + */ +class CKeyChooserWidget : public QWidget { + Q_OBJECT +public: + /** + * the constructor + */ + CKeyChooserWidget(QStringList *list=0, const bool useNextPrevSignals = false, QWidget *parent=0 ); + /** + * the constructor + */ + CKeyChooserWidget(int count=0, const bool useNextPrevSignals = false, QWidget *parent=0 ); + /** + * This function does clear the combobox, then fill in + * the StringList, set the ComboBox' current item to index + * and if do_emit is true, it will emit @ref #changed + * + * @param list the stringlist to be inserted + * @param index the index that the combobox is to jump to + * @param do_emit should we emit @ref #changed(int) + */ + void reset(const int count, int index, bool do_emit); + void reset(QStringList& list, int index, bool do_emit); + void reset(QStringList *list, int index, bool do_emit); + /** + * Initializes this widget. We need this function because + * we have more than one constructor. + */ + virtual void init(); + /** + * + */ + // virtual void adjustSize(); + /** + * Sets the tooltips for the given entries using the parameters as text. + */ + void setToolTips( const QString comboTip, const QString nextEntry, const QString scrollButton, const QString previousEntry); + /** + * Sets the current item to the one with the given text + */ + bool setItem( const QString item); + /** + * Return the combobox of this key chooser widget. + */ + QComboBox* comboBox() {return m_comboBox;}; + +public slots: + /** + * is called to lock the combobox + */ + void lock() + ; + /** + * is called to unlock the combobox + */ + void unlock(); + /** + * is called to move the combobox to a certain index + * @param index the index to jump to + */ + void changeCombo(int index); + void slotComboChanged(int index); + +signals: + /** + * Is emitted if the widget changed, but + * only if it is not locked or being reset + * + * @param the current ComboBox index + */ + void changed(int index); + /** + * Is emitted if the widget was left with a focus out event. + * @param index The new index of the ComboBox + */ + void focusOut(int index); + +protected: + /** + * indicates wheter we are resetting at the moment + */ + bool isResetting; + /** + * + */ + QString oldKey; + +protected slots: // Protected slots + /** + * Is called when the return key was presed in the combobox. + */ + void slotReturnPressed( /*const QString&*/ ); + + +private: + friend class CLexiconKeyChooser; + QStringList m_list; + bool m_useNextPrevSignals; + bool updatelock; + + /** + * Members should never be public!! + */ + CKCComboBox* m_comboBox; + QHBoxLayout *m_mainLayout; + CScrollerWidgetSet * m_scroller; +}; + +#endif diff --git a/src/frontend/keychooser/clexiconkeychooser.cpp b/src/frontend/keychooser/clexiconkeychooser.cpp new file mode 100644 index 0000000..00c02ba --- /dev/null +++ b/src/frontend/keychooser/clexiconkeychooser.cpp @@ -0,0 +1,180 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + + + +#include "clexiconkeychooser.h" + +#include "bthistory.h" +#include "ckeychooserwidget.h" +#include "cscrollbutton.h" + +#include "backend/drivers/cswordlexiconmoduleinfo.h" +#include "backend/keys/cswordldkey.h" +#include "backend/config/cbtconfig.h" +#include "util/cresmgr.h" + +//STL headers +#include <algorithm> +#include <iterator> +#include <map> + +#include <QHBoxLayout> + + +CLexiconKeyChooser::CLexiconKeyChooser(QList<CSwordModuleInfo*> modules, CSwordKey *key, QWidget *parent) + : CKeyChooser(modules, key, parent), + m_key(dynamic_cast<CSwordLDKey*>(key)) +{ + setModules(modules, false); + + //we use a layout because the key chooser should be resized to full size + m_layout = new QHBoxLayout(this); + m_layout->setSpacing(0); + m_layout->setContentsMargins(0,0,0,0); + m_layout->setDirection(QBoxLayout::LeftToRight); + m_layout->setSizeConstraint(QLayout::SetNoConstraint); + + m_widget = new CKeyChooserWidget(0, false, this); + + //don't allow a too high width, try to keep as narrow as possible + //to aid users with smaller screen resolutions + m_widget->comboBox()->setMaximumWidth(200); + + m_widget->setToolTips( + tr("Entries of the current work"), + tr("Next entry"), + tr("Scroll through the entries of the list. Press the button and move the mouse to increase or decrease the item."), + tr("Previous entry") + ); + + m_layout->addWidget(m_widget,0,Qt::AlignLeft); + + connect(m_widget,SIGNAL(changed(int)),SLOT(activated(int))); + connect(m_widget,SIGNAL(focusOut(int)),SLOT(activated(int))); + + setModules(modules, true); + setKey(key); + connect(this, SIGNAL(keyChanged(CSwordKey*)), history(), SLOT(add(CSwordKey*)) ); +} + +CSwordKey* CLexiconKeyChooser::key() { + // qWarning("key"); + return m_key; +} + +void CLexiconKeyChooser::setKey(CSwordKey* key) +{ + qDebug("CLexiconKeyChooser::setKey"); + + if (!(m_key = dynamic_cast<CSwordLDKey*>(key))) { + return; + } + + QString newKey = m_key->key(); + const int index = m_widget->comboBox()->findText(newKey); + m_widget->comboBox()->setCurrentIndex(index); + + // qWarning("setKey end"); + emit keyChanged( m_key); +} + +void CLexiconKeyChooser::activated(int index) { + // qWarning("activated"); + const QString text = m_widget->comboBox()->itemText(index); + + // To prevent from eternal loop, because activated() is emitted again + if (m_key && m_key->key() != text) { + m_key->key(text); + setKey(m_key); + } + // qWarning("activated end"); +} + +inline bool my_cmpEntries(const QString& a, const QString& b) { + return a < b; +} + +/** Reimplementation. */ +void CLexiconKeyChooser::refreshContent() { + if (m_modules.count() == 1) { + m_widget->reset(m_modules.first()->entries(), 0, true); + // qWarning("resetted"); + } + else { + typedef std::multimap<unsigned int, QStringList*> EntryMap; + EntryMap entryMap; + QStringList* entries = 0; + QListIterator<CSwordLexiconModuleInfo*> mit(m_modules); + while (mit.hasNext()) { + entries = mit.next()->entries(); + entryMap.insert( std::make_pair(entries->count(), entries) ); + } + + QStringList goodEntries; //The string list which contains the entries which are available in all modules + + EntryMap::iterator it = entryMap.begin(); //iterator to go thoigh all selected modules + QStringList refEntries = *(it->second); //copy the items for the first time + QStringList* cmpEntries = ( ++it )->second; //list for comparision, starts with the second module in the map + + while(it != entryMap.end()) { + std::set_intersection( + refEntries.begin(), --(refEntries.end()), //--end() is the last valid entry + cmpEntries->begin(), --(cmpEntries->end()), + std::back_inserter(goodEntries), //append valid entries to the end of goodEntries + my_cmpEntries //ci_cmpEntries is the comparision function + ); + + cmpEntries = ( ++it )->second; //this is a pointer to the string list of a new module + + /* + * use the good entries for next comparision, + * because the final list can only have the entries of goodEntries as maxiumum + */ + refEntries = goodEntries; + }; + + m_widget->reset(goodEntries, 0, true); //write down the entries + } //end of ELSE + +} + +/** No descriptions */ +void CLexiconKeyChooser::adjustFont() { + +} + +/** Sets the module and refreshes the combo boxes */ +void CLexiconKeyChooser::setModules( const QList<CSwordModuleInfo*>& modules, const bool refresh ) { + + while (!m_modules.isEmpty()) + m_modules.takeFirst(); // not deleting the pointer + + QList<CSwordModuleInfo*>::const_iterator end_it = modules.end(); + for (QList<CSwordModuleInfo*>::const_iterator it(modules.begin()); it != end_it; ++it) { + CSwordLexiconModuleInfo* lexicon = dynamic_cast<CSwordLexiconModuleInfo*>(*it); + if (lexicon) { + m_modules.append(lexicon); + } + } + + if (refresh) { + refreshContent(); + // adjustFont(); + } +} + +/** No descriptions */ +void CLexiconKeyChooser::updateKey(CSwordKey*) {} + +void CLexiconKeyChooser::setKey(QString& newKey) +{ + m_key->key(newKey); + setKey(m_key); +} diff --git a/src/frontend/keychooser/clexiconkeychooser.h b/src/frontend/keychooser/clexiconkeychooser.h new file mode 100644 index 0000000..a75ce37 --- /dev/null +++ b/src/frontend/keychooser/clexiconkeychooser.h @@ -0,0 +1,86 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + + + +#ifndef CLEXICONKEYCHOOSER_H +#define CLEXICONKEYCHOOSER_H + + +#include "ckeychooser.h" +class CSwordModuleInfo; + + +class CKeyChooserWidget; +class CSwordLexiconModuleInfo; +class CSwordLDKey; + +class QWidget; +class QHBoxLayout; + +/** + * This class implements the KeyChooser for lexicons + * + * it inhertits @ref CKeyChooser + * it uses 1 @ref CKeyChooserWidget to represent the lexicon keys + * + * @author The BibleTime team + */ +class CLexiconKeyChooser : public CKeyChooser { + Q_OBJECT +public: + /** + * The constructor + * + * you should not need to use this, use @ref CKeyChooser::createInstance instead + */ + CLexiconKeyChooser(QList<CSwordModuleInfo*> modules, CSwordKey *key=0, QWidget *parent=0); + +public slots: + /** + * see @ref CKeyChooser::getKey + * @return Return the key object we use. + */ + virtual CSwordKey* key(); + /** + * see @ref CKeyChooser::setKey + */ + virtual void setKey(CSwordKey* key); + /** + * used to react to changes in the @ref CKeyChooserWidget + * + * @param index not used + **/ + virtual void activated(int index); + /** + * Reimplementation. + */ + virtual void refreshContent(); + /** + * Sets the module and refreshes the combo boxes of this keychooser. + */ + virtual void setModules( const QList<CSwordModuleInfo*>& modules, const bool refresh = true ); + +protected: + CKeyChooserWidget *m_widget; + CSwordLDKey* m_key; + QList<CSwordLexiconModuleInfo*> m_modules; + QHBoxLayout *m_layout; + + virtual void adjustFont(); + +public slots: // Public slots + virtual void updateKey(CSwordKey* key); + +protected slots: + virtual void setKey(QString& newKey); + +}; + +#endif diff --git a/src/frontend/keychooser/cscrollbutton.cpp b/src/frontend/keychooser/cscrollbutton.cpp new file mode 100644 index 0000000..742bc53 --- /dev/null +++ b/src/frontend/keychooser/cscrollbutton.cpp @@ -0,0 +1,85 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + + + +#include "cscrollbutton.h" + + +#include <stdlib.h> +#include <math.h> + +//Qt includes +#include <QEvent> +#include <QApplication> +#include <QCursor> +#include <QPoint> +#include <QMouseEvent> +#include <QWheelEvent> + +CScrollButton::CScrollButton(QWidget *parent) : QToolButton(parent) { + setFocusPolicy(Qt::WheelFocus); + setCursor(Qt::SplitVCursor ); + + m_isLocked = false; + connect(this, SIGNAL(pressed() ), SLOT(was_pressed() )); + connect(this, SIGNAL(released()), SLOT(was_released())); +} + +bool CScrollButton::isLocked( ) const { + return m_isLocked; +} + +void CScrollButton::was_pressed( ) { + QApplication::setOverrideCursor(Qt::BlankCursor); + m_isLocked = true; + lock_Point = get_lock_Point(); + + emit lock() + ; +} + +void CScrollButton::was_released( ) { + QApplication::restoreOverrideCursor(); + m_isLocked = false; + + emit unlock(); +} + +const QPoint CScrollButton::get_lock_Point() const { + return mapToGlobal( QPoint( width()/2, height()/2 ) ); +} + +void CScrollButton::mouseMoveEvent( QMouseEvent* e ) { + if (m_isLocked) { + int vchange = (QCursor::pos().y() - lock_Point.y()); + + if (abs(vchange) < 10) { + vchange = (int)((vchange>0 ? 1 : -1) * pow(abs(vchange), 0.3)); + } + else if (abs(vchange) < 30) { + vchange = (int)((vchange>0 ? 1 : -1) * pow(abs(vchange), 0.6)); + } + else if (abs(vchange) < 40) { + vchange = (int)((vchange>0 ? 1 : -1) * pow(abs(vchange), 1.2)); + } + else { + vchange = (int)((vchange>0 ? 1 : -1) * pow(abs(vchange), 2.0)); + } + + if (vchange) { //not emit 0 + emit change_requested( vchange ); + } + + QCursor::setPos( lock_Point ); + } + else { + QToolButton::mouseMoveEvent(e); + } +} diff --git a/src/frontend/keychooser/cscrollbutton.h b/src/frontend/keychooser/cscrollbutton.h new file mode 100644 index 0000000..3a38f37 --- /dev/null +++ b/src/frontend/keychooser/cscrollbutton.h @@ -0,0 +1,85 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + + + +#ifndef CSRCOLLBUTTON_H +#define CSRCOLLBUTTON_H + + +#include <QToolButton> + + +class QMouseEvent; +class QWidget; +class QMouseEvent; +class QWheelEvent; + +/** This Class implements the direct chooser button used in the KeyChooser Widget + * @author The BibleTime team + */ +class CScrollButton : public QToolButton { + Q_OBJECT +public: + /** + * The constructor + */ + CScrollButton(QWidget *parent=0); + bool isLocked() const; + +signals: + /** + * is emitted when the button enters locked state + */ + void lock() + ; + /** + * is emitted when the button leaves locked state + */ + void unlock(); + /** + * indicates a change the user made by moving the mouse + * @param count the number of items to be changed in the KeyChooser ComboBox + */ + void change_requested(int count); + +protected slots: + /* + * used to process the button press events + */ + void was_pressed(); + /** + * used to process the button release events + */ + void was_released(); + +protected: + /** + * Reimplementation from @ref QWidget#mouseMoveEvent - processes + * the mouse move events + */ + virtual void mouseMoveEvent( QMouseEvent* e ); + /** + * used to find the lock point - the middle of the button + * @return the lock point + */ + const QPoint get_lock_Point() const; + +private: + /** + * Indicates whether the button is in locked state or not + */ + bool m_isLocked; + /** + * stores the lock point + */ + QPoint lock_Point; +}; + +#endif diff --git a/src/frontend/keychooser/cscrollerwidgetset.cpp b/src/frontend/keychooser/cscrollerwidgetset.cpp new file mode 100644 index 0000000..3577803 --- /dev/null +++ b/src/frontend/keychooser/cscrollerwidgetset.cpp @@ -0,0 +1,87 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + + +//BibleTime includes +#include "cscrollbutton.h" +#include "cscrollerwidgetset.h" + +//Qt includes +#include <QString> +#include <QToolButton> +#include <QVBoxLayout> +#include <QWheelEvent> + +const unsigned int WIDTH = 16; +const unsigned int ARROW_HEIGHT = 12; +const unsigned int MOVER_HEIGHT = 6; + +CScrollerWidgetSet::CScrollerWidgetSet(QWidget *parent) : QWidget(parent) { + m_layout = new QVBoxLayout(this); + m_layout->setSpacing(0); + m_layout->setContentsMargins(0,0,0,0); + m_layout->setAlignment(this, Qt::AlignHCenter | Qt::AlignCenter); + + btn_up = new QToolButton(this); + btn_up->setArrowType(Qt::UpArrow); + + btn_up->setFixedSize(WIDTH, ARROW_HEIGHT); + btn_up->setFocusPolicy(Qt::NoFocus); + btn_up->setAutoRaise(true); + + btn_fx = new CScrollButton(this); + btn_fx->setFixedSize(WIDTH, MOVER_HEIGHT); + btn_fx->setFocusPolicy(Qt::NoFocus); + + btn_down = new QToolButton(this); + btn_down->setArrowType(Qt::DownArrow); + btn_down->setFixedSize(WIDTH, ARROW_HEIGHT); + btn_down->setFocusPolicy(Qt::NoFocus); + btn_down->setAutoRaise(true); + + m_layout->addWidget( btn_up,0 ); + m_layout->addWidget( btn_fx,0 ); + m_layout->addWidget( btn_down,0 ); + setMinimumWidth(WIDTH); // Kludge to add some spacing but seems to work. + + connect(btn_fx, SIGNAL(lock()), SLOT(slotLock())); + connect(btn_fx, SIGNAL(unlock()), SLOT(slotUnlock())); + connect(btn_fx, SIGNAL(change_requested(int)), SLOT(slotScroller(int))); + connect(btn_up, SIGNAL(clicked()), SLOT(slotUpClick())); + connect(btn_down, SIGNAL(clicked()), SLOT(slotDownClick())); +} + +/** Sets the tooltips for the given entries using the parameters as text. */ +void CScrollerWidgetSet::setToolTips( const QString nextEntryTip, const QString scrollButtonTip, const QString previousEntryTip) { + btn_fx->setToolTip(scrollButtonTip); + btn_down->setToolTip(nextEntryTip); + btn_up->setToolTip(previousEntryTip); +} + + +void CScrollerWidgetSet::wheelEvent( QWheelEvent* e ) { + /** + * The problem is, that wheel events do everytime have the delta value 120 + */ + const int vchange = ((e->delta() > 0) ? (-1) : (1)); + + if (vchange!=0) {//do not emit a change with value 0 + emit change(vchange); + e->accept(); + } + else { + e->ignore(); + } +} + +void CScrollerWidgetSet::slotLock() { emit scroller_pressed(); } +void CScrollerWidgetSet::slotUnlock() { emit scroller_released(); } +void CScrollerWidgetSet::slotScroller(int n) { emit change(n); } +void CScrollerWidgetSet::slotUpClick() { slotScroller(-1); } +void CScrollerWidgetSet::slotDownClick() { slotScroller(1); } diff --git a/src/frontend/keychooser/cscrollerwidgetset.h b/src/frontend/keychooser/cscrollerwidgetset.h new file mode 100644 index 0000000..bd482df --- /dev/null +++ b/src/frontend/keychooser/cscrollerwidgetset.h @@ -0,0 +1,76 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + + + +#ifndef CSCROLLERWIDGETSET_H +#define CSCROLLERWIDGETSET_H + + +#include <QWidget> + + +class QVBoxLayout; +class QToolButton; +class QString; + +class CScrollButton; + +/** + * This class implements the Scroller Widget-set, which + * consists of two normal ref @QToolButton and a enhanced @ref CScrollButton + * + * @author The BibleTime team + */ +class CScrollerWidgetSet : public QWidget { + Q_OBJECT +public: + /** + * the constructor + */ + CScrollerWidgetSet(QWidget *parent=0); + /** + * Sets the tooltips for the given entries using the parameters as text. + */ + void setToolTips( const QString nextEntry, const QString scrollButton, const QString previousEntry); + +signals: + /** + * is emitted to proceed to some other entry relative to the + * current, indicated by the int value + */ + void change(int count); + + /** + * These emit when the scroll button is pressed or released + */ + void scroller_pressed(); + void scroller_released(); + +protected: + + virtual void wheelEvent( QWheelEvent* e ); + + QToolButton* btn_up; + QToolButton* btn_down; + CScrollButton* btn_fx; + +protected slots: + void slotLock(); + void slotUnlock(); + void slotUpClick(); + void slotDownClick(); + void slotScroller(int); + +private: + QVBoxLayout *m_layout; + +}; + +#endif diff --git a/src/frontend/keychooser/versekeychooser/btdropdownchooserbutton.cpp b/src/frontend/keychooser/versekeychooser/btdropdownchooserbutton.cpp new file mode 100644 index 0000000..e4b05c3 --- /dev/null +++ b/src/frontend/keychooser/versekeychooser/btdropdownchooserbutton.cpp @@ -0,0 +1,134 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + +#include "btdropdownchooserbutton.h" +#include "ckeyreferencewidget.h" +#include "btversekeymenu.h" + +#include <QWheelEvent> +#include <QDebug> + +const unsigned int ARROW_HEIGHT = 12; + +BtDropdownChooserButton::BtDropdownChooserButton(CKeyReferenceWidget* ref) + : QToolButton(), + m_ref(ref) +{ + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + + setAutoRaise(true); + setArrowType(Qt::NoArrow); + setFixedHeight(ARROW_HEIGHT); + setFocusPolicy(Qt::NoFocus); + setPopupMode(QToolButton::InstantPopup); + setStyleSheet("QToolButton{margin:0px;}QToolButton::menu-indicator{subcontrol-position: center center;}"); + + BtVerseKeyMenu* m = new BtVerseKeyMenu(this); +// KAcceleratorManager::setNoAccel(m); + setMenu(m); + QObject::connect(m, SIGNAL(triggered(QAction*)), this, SLOT(slotMenuTriggered(QAction*))); +} + + +void BtDropdownChooserButton::mousePressEvent(QMouseEvent* e) +{ + //qDebug("BtDropdownChooserButton::mousePressEvent"); + //recreate the menu + menu()->clear(); + this->newList(); + + QToolButton::mousePressEvent(e); +} + +void BtDropdownChooserButton::wheelEvent(QWheelEvent* e) +{ + // The problem is, that wheel events do everytime have the delta value 120 + const int vchange = ((e->delta() > 0) ? (-1) : (1)); + + if (vchange!=0) {//do not emit a change with value 0 + emit stepItem(vchange); + e->accept(); + } + else { + e->ignore(); + } +} + + +//******************Book dropdown button*************************************/ + +BtBookDropdownChooserButton::BtBookDropdownChooserButton(CKeyReferenceWidget* ref) + : BtDropdownChooserButton(ref) +{ + setToolTip(tr("Select book")); + QObject::connect(this, SIGNAL(stepItem(int)), m_ref, SLOT(slotStepBook(int))); +} + +void BtBookDropdownChooserButton::newList() +{ + QMenu* m = menu(); + QStringList* booklist = ref()->m_module->books(); + foreach (QString bookname, *booklist) { + m->addAction(bookname); + } +} + +void BtBookDropdownChooserButton::slotMenuTriggered(QAction* action) +{ + qDebug() << "BtBookDropdownChooserButton::slotMenuTriggered" << action->text(); + m_ref->slotChangeBook(action->text()); +} + + +//****************** Chapter dropdown button *************************************/ + +BtChapterDropdownChooserButton::BtChapterDropdownChooserButton(CKeyReferenceWidget* ref) + : BtDropdownChooserButton(ref) +{ + setToolTip(tr("Select chapter")); + QObject::connect(this, SIGNAL(stepItem(int)), m_ref, SLOT(slotStepChapter(int))); +} + +void BtChapterDropdownChooserButton::newList() +{ + QMenu* m = menu(); + int count = ref()->m_module->chapterCount(ref()->m_key->book()); + for (int i = 1; i <= count; i++) { + m->addAction(QString::number(i)); + } +} + +void BtChapterDropdownChooserButton::slotMenuTriggered(QAction* action) +{ + m_ref->slotChangeChapter(action->text().toInt()); +} + + +//****************** Verse dropdown button *************************************/ + +BtVerseDropdownChooserButton::BtVerseDropdownChooserButton(CKeyReferenceWidget* ref) + : BtDropdownChooserButton(ref) +{ + setToolTip(tr("Select verse")); + QObject::connect(this, SIGNAL(stepItem(int)), m_ref, SLOT(slotStepVerse(int))); +} + +void BtVerseDropdownChooserButton::newList() +{ + QMenu* m = menu(); + int count = ref()->m_module->verseCount(ref()->m_key->book(), ref()->m_key->Chapter()); + for (int i = 1; i <= count; i++) { + m->addAction(QString::number(i)); + } +} + +void BtVerseDropdownChooserButton::slotMenuTriggered(QAction* action) +{ + m_ref->slotChangeVerse(action->text().toInt()); +} diff --git a/src/frontend/keychooser/versekeychooser/btdropdownchooserbutton.h b/src/frontend/keychooser/versekeychooser/btdropdownchooserbutton.h new file mode 100644 index 0000000..969f5c2 --- /dev/null +++ b/src/frontend/keychooser/versekeychooser/btdropdownchooserbutton.h @@ -0,0 +1,79 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + +#ifndef BTDROPDOWNCHOOSERBUTTON_H +#define BTDROPDOWNCHOOSERBUTTON_H + + +#include <QToolButton> + +class CKeyReferenceWidget; + +/** +* Base class for book/ch/v dropdown list chooser buttons. +*/ +class BtDropdownChooserButton : public QToolButton +{ + Q_OBJECT +public: + BtDropdownChooserButton(CKeyReferenceWidget* ref); + + virtual ~BtDropdownChooserButton() {} + /** The item list is constructed here just before the menu is shown.*/ + virtual void mousePressEvent(QMouseEvent* event); + /** Recreates the menu list.*/ + virtual void newList() = 0; + /** Returns the verse reference widget which this button belongs to.*/ + CKeyReferenceWidget* ref() {return m_ref;} +public slots: + /** When a menu item is selected the key will be changed.*/ + virtual void slotMenuTriggered(QAction* action) = 0; +protected: + CKeyReferenceWidget* m_ref; + void wheelEvent(QWheelEvent* event); +signals: + void stepItem(int step); +}; + +/** See BtDropdownChooserButton.*/ +class BtBookDropdownChooserButton : public BtDropdownChooserButton +{ + Q_OBJECT +public: + BtBookDropdownChooserButton(CKeyReferenceWidget* ref); + ~BtBookDropdownChooserButton() {} + virtual void newList(); +public slots: + virtual void slotMenuTriggered(QAction* action); +}; + +/** See BtDropdownChooserButton.*/ +class BtChapterDropdownChooserButton : public BtDropdownChooserButton +{ + Q_OBJECT +public: + BtChapterDropdownChooserButton(CKeyReferenceWidget* ref); + ~BtChapterDropdownChooserButton() {} + virtual void newList(); +public slots: + virtual void slotMenuTriggered(QAction* action); +}; + +/** See BtDropdownChooserButton.*/ +class BtVerseDropdownChooserButton : public BtDropdownChooserButton +{ + Q_OBJECT +public: + BtVerseDropdownChooserButton(CKeyReferenceWidget* ref); + ~BtVerseDropdownChooserButton() {} + virtual void newList(); +public slots: + virtual void slotMenuTriggered(QAction* action); +}; +#endif diff --git a/src/frontend/keychooser/versekeychooser/btversekeymenu.cpp b/src/frontend/keychooser/versekeychooser/btversekeymenu.cpp new file mode 100644 index 0000000..f8607e4 --- /dev/null +++ b/src/frontend/keychooser/versekeychooser/btversekeymenu.cpp @@ -0,0 +1,52 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + +#include "btversekeymenu.h" + +#include <QMenu> +#include <QTimerEvent> +#include <QMouseEvent> + +#include <QDebug> + +BtVerseKeyMenu::BtVerseKeyMenu(QWidget* parent) + : QMenu(parent), + m_timerId(0), + m_firstClickLock(true) +{ + qDebug("BtVerseKeyMenu::BtVerseKeyMenu"); + QObject::connect(this, SIGNAL(aboutToShow()), this, SLOT(startFirstClickDelayTimer())); +} + +void BtVerseKeyMenu::startFirstClickDelayTimer() +{ + //qDebug() << "BtVerseKeyMenu::startFirstClickDelayTimer"; + m_firstClickLock = true; + killTimer(m_timerId); + m_timerId = startTimer(300); +} + +void BtVerseKeyMenu::timerEvent(QTimerEvent* e) +{ + if (e->timerId() == m_timerId) { + //qDebug() << "BtVerseKeyMenu::timerEvent"; + killTimer(m_timerId); + m_firstClickLock = false; + } else { + QMenu::timerEvent(e); + } +} + +void BtVerseKeyMenu::mouseReleaseEvent(QMouseEvent* e) +{ + //qDebug() << "BtVerseKeyMenu::mouseReleaseEvent"; + if (m_firstClickLock) return; + //qDebug() << "BtVerseKeyMenu::mouseReleaseEvent 2"; + QMenu::mouseReleaseEvent(e); +} diff --git a/src/frontend/keychooser/versekeychooser/btversekeymenu.h b/src/frontend/keychooser/versekeychooser/btversekeymenu.h new file mode 100644 index 0000000..45d9385 --- /dev/null +++ b/src/frontend/keychooser/versekeychooser/btversekeymenu.h @@ -0,0 +1,43 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + +#ifndef BTVERSEKEYMENU_H +#define BTVERSEKEYMENU_H + +#include <QMenu> + +class QMouseEvent; +class QTimerEvent; + +/** +* Menu for book/ch/v dropdown lists. +* +* This is implemented mostly because it needs a delay which prevents unwanted actions after +* the menu has been shown and mouse button is released over some item. +*/ +class BtVerseKeyMenu : public QMenu +{ + Q_OBJECT +public: + BtVerseKeyMenu(QWidget* parent); + ~BtVerseKeyMenu(){} +protected: + virtual void mouseReleaseEvent(QMouseEvent* event); + /** Frees the mouse button release after the delay has elapsed.*/ + virtual void timerEvent(QTimerEvent* event); +private slots: + /** Starts the delay timer for the first mouse button release.*/ + void startFirstClickDelayTimer(); + +private: + int m_timerId; + bool m_firstClickLock; +}; + +#endif diff --git a/src/frontend/keychooser/versekeychooser/cbiblekeychooser.cpp b/src/frontend/keychooser/versekeychooser/cbiblekeychooser.cpp new file mode 100644 index 0000000..2bc9e77 --- /dev/null +++ b/src/frontend/keychooser/versekeychooser/cbiblekeychooser.cpp @@ -0,0 +1,108 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + +#include "cbiblekeychooser.h" + +#include "../bthistory.h" +#include "ckeyreferencewidget.h" +#include "../cscrollbutton.h" + +#include "backend/keys/cswordversekey.h" +#include "backend/drivers/cswordbiblemoduleinfo.h" +#include "backend/drivers/cswordmoduleinfo.h" + +#include "util/cresmgr.h" + +#include <QHBoxLayout> +#include <QDebug> + + +CBibleKeyChooser::CBibleKeyChooser(QList<CSwordModuleInfo*> modules, CSwordKey *key, QWidget *parent) : + CKeyChooser(modules, key, parent), + m_key(dynamic_cast<CSwordVerseKey*>(key)) +{ + w_ref = 0; + setModules(modules, false); + if (!m_modules.count()) { + qWarning() << "CBibleKeyChooser: module is not a Bible or commentary!"; + m_key = 0; + return; + } + QHBoxLayout* layout = new QHBoxLayout(this); + layout->setSpacing(0); + layout->setContentsMargins(0,0,0,0); + layout->setDirection( QBoxLayout::LeftToRight ); + + w_ref = new CKeyReferenceWidget(dynamic_cast<CSwordBibleModuleInfo*>(m_modules.first()), m_key, this); + layout->addWidget(w_ref); + + connect(w_ref,SIGNAL(changed(CSwordVerseKey *)),SLOT(refChanged(CSwordVerseKey *))); + + setKey(m_key); //set the key without changing it, setKey(key()) would change it + + connect(this, SIGNAL(keyChanged(CSwordKey*)), history(), SLOT(add(CSwordKey*)) ); +} + +CSwordKey* CBibleKeyChooser::key() { + return m_key; +} + +void CBibleKeyChooser::setKey(CSwordKey* key) +{ + Q_ASSERT(dynamic_cast<CSwordVerseKey*>(key)); + if (dynamic_cast<CSwordVerseKey*>(key) == 0) return; + + emit (beforeKeyChange(m_key->key())); //required to make direct setKey calls work from the outside + m_key = dynamic_cast<CSwordVerseKey*>(key); + w_ref->setKey(m_key); + emit keyChanged(m_key); +} + +void CBibleKeyChooser::refChanged(CSwordVerseKey* key) +{ + Q_ASSERT(m_key); + Q_ASSERT(key); + + if (!updatesEnabled()) return; + + setUpdatesEnabled(false); + if (m_key) emit beforeKeyChange(m_key->key()); + m_key = key; + emit keyChanged(m_key); + + setUpdatesEnabled(true); +} + +void CBibleKeyChooser::setModules(const QList<CSwordModuleInfo*>& modules, const bool refresh) { + m_modules.clear(); + + foreach (CSwordModuleInfo* mod, modules) { + if (mod->type() == CSwordModuleInfo::Bible || mod->type() == CSwordModuleInfo::Commentary) { + if (CSwordBibleModuleInfo* bible = dynamic_cast<CSwordBibleModuleInfo*>(mod)) m_modules.append(bible); + } + } + + // First time this is called we havnt set up w_ref. + if (w_ref) w_ref->setModule(dynamic_cast<CSwordBibleModuleInfo*>(m_modules.first())); + if (refresh) refreshContent(); +} + +void CBibleKeyChooser::refreshContent() { + setKey(m_key); +} + +void CBibleKeyChooser::updateKey(CSwordKey* /*key*/) {} + +void CBibleKeyChooser::adjustFont() {} + +void CBibleKeyChooser::setKey(QString& newKey) +{ + m_key->key(newKey); + setKey(m_key); +} diff --git a/src/frontend/keychooser/versekeychooser/cbiblekeychooser.h b/src/frontend/keychooser/versekeychooser/cbiblekeychooser.h new file mode 100644 index 0000000..a410354 --- /dev/null +++ b/src/frontend/keychooser/versekeychooser/cbiblekeychooser.h @@ -0,0 +1,78 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + + + +#ifndef CBIBLEKEYCHOOSER_H +#define CBIBLEKEYCHOOSER_H + + +#include "../ckeychooser.h" +#include "backend/drivers/cswordbiblemoduleinfo.h" + +#include <QList> + +class QWidget; + +class CKeyReferenceWidget; +class CSwordVerseKey; +class CSwordBibleModuleInfo; + +/** This class implements the KeyChooser for bibles and commentaries + * + * it inhertits @ref CKeyChooser + * + * it uses a CKeyReferenceWidget 's to represent the bible keys + * + * @author The BibleTime team + */ + +class CBibleKeyChooser : public CKeyChooser { + Q_OBJECT + +public: + /** + * the constructor + * you should not need to use this, use @ref CKeyChooser::createInstance instead + */ + CBibleKeyChooser(QList<CSwordModuleInfo*> modules, CSwordKey *key=0, QWidget *parent=0); + +public slots: + /** + * see @ref CKeyChooser::getKey + */ + CSwordKey* key(); + /** + * see @ref CKeyChooser::setKey + */ + virtual void setKey(CSwordKey *key); + /** + * Sets the module + */ + virtual void setModules(const QList<CSwordModuleInfo*>& modules, const bool refresh = true); + /** + * used to react to changes + * @param index not used + */ + void refChanged(CSwordVerseKey *key); + + void updateKey(CSwordKey* key); + void adjustFont(); + void refreshContent(); + +protected slots: + virtual void setKey(QString& newKey); + +private: + CKeyReferenceWidget* w_ref; + QList<CSwordBibleModuleInfo*> m_modules; + CSwordVerseKey *m_key; +}; + +#endif diff --git a/src/frontend/keychooser/versekeychooser/ckeyreferencewidget.cpp b/src/frontend/keychooser/versekeychooser/ckeyreferencewidget.cpp new file mode 100644 index 0000000..0815a89 --- /dev/null +++ b/src/frontend/keychooser/versekeychooser/ckeyreferencewidget.cpp @@ -0,0 +1,229 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + +//BibleTime includes +#include "ckeyreferencewidget.h" + +#include "../cscrollerwidgetset.h" +#include "btdropdownchooserbutton.h" + +#include "backend/config/cbtconfig.h" + +#include "backend/keys/cswordversekey.h" + +#include "util/cresmgr.h" +#include "util/directoryutil.h" + +//Qt includes +#include <QString> +#include <QStringList> +#include <QEvent> +#include <QPixmap> +#include <QApplication> +#include <QHBoxLayout> +#include <QToolButton> +#include <QDebug> +#include <QLineEdit> + + + +CKeyReferenceWidget::CKeyReferenceWidget( CSwordBibleModuleInfo *mod, CSwordVerseKey *key, QWidget *parent, const char* /*name*/) : + QWidget(parent), + m_key(new CSwordVerseKey(mod)) +{ + + updatelock = false; + m_module = mod; + + setFocusPolicy(Qt::WheelFocus); + + QToolButton* clearRef = new QToolButton(this); + clearRef->setIcon(util::filesystem::DirectoryUtil::getIcon("edit_clear_locationbar")); + clearRef->setAutoRaise(true); + clearRef->setStyleSheet("QToolButton{margin:0px;}"); + connect(clearRef, SIGNAL(clicked()), SLOT(slotClearRef()) ); + + m_bookScroller = new CScrollerWidgetSet(this); + + m_textbox = new QLineEdit( this ); + m_textbox->setStyleSheet("QLineEdit{margin:0px;}"); + + setKey(key); // The order of these two functions is important. + setModule(); + + m_chapterScroller = new CScrollerWidgetSet(this); + m_verseScroller = new CScrollerWidgetSet(this); + + m_bookDropdownButton = new BtBookDropdownChooserButton(this); + m_chapterDropdownButton = new BtChapterDropdownChooserButton(this); + m_verseDropdownButton = new BtVerseDropdownChooserButton(this); + + QHBoxLayout* dropdownButtonsLayout = new QHBoxLayout(); + QVBoxLayout* editorAndButtonsLayout = new QVBoxLayout(); + dropdownButtonsLayout->setContentsMargins(0,0,0,0); + editorAndButtonsLayout->setContentsMargins(0,0,0,0); + dropdownButtonsLayout->setSpacing(0); + editorAndButtonsLayout->setSpacing(0); + + dropdownButtonsLayout->addWidget(m_bookDropdownButton, 2); + dropdownButtonsLayout->addWidget(m_chapterDropdownButton,1); + dropdownButtonsLayout->addWidget(m_verseDropdownButton,1); + editorAndButtonsLayout->addWidget(m_textbox); + editorAndButtonsLayout->addLayout(dropdownButtonsLayout); + + QHBoxLayout* m_mainLayout = new QHBoxLayout( this ); + m_mainLayout->setContentsMargins(0,0,0,0); + m_mainLayout->setSpacing(0); + m_mainLayout->addWidget(clearRef); + m_mainLayout->addWidget(m_bookScroller); + m_mainLayout->addLayout(editorAndButtonsLayout); + m_mainLayout->addWidget(m_chapterScroller); + m_mainLayout->addWidget(m_verseScroller); + + + setTabOrder(m_textbox, 0); + + QString scrollButtonToolTip(tr("Scroll through the entries of the list. Press the button and move the mouse to increase or decrease the item.")); + m_bookScroller->setToolTips( + tr("Next book"), + scrollButtonToolTip, + tr("Previous book") + ); + m_chapterScroller->setToolTips( + tr("Next chapter"), + scrollButtonToolTip, + tr("Previous chapter") + ); + m_verseScroller->setToolTips( + tr("Next verse"), + scrollButtonToolTip, + tr("Previous verse") + ); + + // signals and slots connections + + connect(m_bookScroller, SIGNAL(change(int)), SLOT(slotStepBook(int))); + connect(m_bookScroller, SIGNAL(scroller_pressed()), SLOT(slotUpdateLock())); + connect(m_bookScroller, SIGNAL(scroller_released()), SLOT(slotUpdateUnlock())); + connect(m_textbox, SIGNAL(returnPressed()), SLOT(slotReturnPressed())); + connect(m_chapterScroller, SIGNAL(change(int)), SLOT(slotStepChapter(int))); + connect(m_chapterScroller, SIGNAL(scroller_pressed()), SLOT(slotUpdateLock())); + connect(m_chapterScroller, SIGNAL(scroller_released()), SLOT(slotUpdateUnlock())); + connect(m_verseScroller, SIGNAL(change(int)), SLOT(slotStepVerse(int))); + connect(m_verseScroller, SIGNAL(scroller_pressed()), SLOT(slotUpdateLock())); + connect(m_verseScroller, SIGNAL(scroller_released()), SLOT(slotUpdateUnlock())); +} + +void CKeyReferenceWidget::setModule(CSwordBibleModuleInfo *m) +{ + if (m) //can be null + { + m_module = m; + m_key->module(m); + } +} + +void CKeyReferenceWidget::slotClearRef( ) +{ + m_textbox->setText(""); + m_textbox->setFocus(); +} + +void CKeyReferenceWidget::updateText() +{ + m_textbox->setText(m_key->key()); +} + +bool CKeyReferenceWidget::setKey(CSwordVerseKey *key) +{ + if (!key) return false; + + m_key->key(key->key()); + updateText(); + return true; +} + +QLineEdit* CKeyReferenceWidget::textbox() +{ + return m_textbox; +} + +void CKeyReferenceWidget::slotReturnPressed() +{ + m_key->key(m_textbox->text()); + updateText(); + + emit changed(m_key.get()); +} + +/* Handlers for the various scroller widgetsets. Do we really want a verse scroller? */ +void CKeyReferenceWidget::slotUpdateLock() +{ + updatelock = true; + oldKey = m_key->key(); +} + +void CKeyReferenceWidget::slotUpdateUnlock() +{ + updatelock = false; + if (oldKey != m_key->key()) emit changed(m_key.get()); +} + +void CKeyReferenceWidget::slotStepBook(int n) +{ + n > 0 ? m_key->next( CSwordVerseKey::UseBook ) : m_key->previous( CSwordVerseKey::UseBook ); + updateText(); + if (!updatelock) emit changed(m_key.get()); +} + +void CKeyReferenceWidget::slotStepChapter(int n) +{ + n > 0 ? m_key->next( CSwordVerseKey::UseChapter ) : m_key->previous( CSwordVerseKey::UseChapter ); + updateText(); + if (!updatelock) emit changed(m_key.get()); +} + +void CKeyReferenceWidget::slotStepVerse(int n) +{ + n > 0 ? m_key->next( CSwordVerseKey::UseVerse ) : m_key->previous( CSwordVerseKey::UseVerse ); + updateText(); + if (!updatelock) emit changed(m_key.get()); +} + + +void CKeyReferenceWidget::slotChangeVerse(int n) +{ + if (m_key->Verse() != n) { + m_key->Verse( n ); + setKey( m_key.get() ); + } + updateText(); + if (!updatelock) emit changed(m_key.get()); +} + +void CKeyReferenceWidget::slotChangeChapter(int n) +{ + if (m_key->Chapter() != n) { + m_key->Chapter( n ); + setKey( m_key.get() ); + } + updateText(); + if (!updatelock) emit changed(m_key.get()); +} + +void CKeyReferenceWidget::slotChangeBook(QString bookname) +{ + if (m_key->book() != bookname) { + m_key->book( bookname ); + setKey( m_key.get() ); + } + updateText(); + if (!updatelock) emit changed(m_key.get()); +} + diff --git a/src/frontend/keychooser/versekeychooser/ckeyreferencewidget.h b/src/frontend/keychooser/versekeychooser/ckeyreferencewidget.h new file mode 100644 index 0000000..d6d5eee --- /dev/null +++ b/src/frontend/keychooser/versekeychooser/ckeyreferencewidget.h @@ -0,0 +1,86 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + +#ifndef CKEYREFERENCEWIDGET_H +#define CKEYREFERENCEWIDGET_H + +#include "../cscrollerwidgetset.h" +#include "backend/drivers/cswordbiblemoduleinfo.h" + +#include <QWidget> + +#include <boost/scoped_ptr.hpp> + + +class CLexiconKeyChooser; +class CSwordVerseKey; +class BtDropdownChooserButton; + +class QLineEdit; + + +class CKeyReferenceWidget : public QWidget { + Q_OBJECT +public: + /** + * the constructor + */ + CKeyReferenceWidget(CSwordBibleModuleInfo *, CSwordVerseKey*, QWidget *parent=0, const char *name=0); + bool setKey(CSwordVerseKey* key); + QLineEdit* textbox(); + void setModule(CSwordBibleModuleInfo *m = 0); + +signals: + void changed(CSwordVerseKey* key); + +protected: + void updateText(); + +protected slots: // Protected slots + /** + * Is called when the return key was presed in the textbox. + */ + void slotReturnPressed(); + + void slotClearRef(); + + void slotUpdateLock(); + void slotUpdateUnlock(); + void slotStepBook(int); + void slotStepChapter(int); + void slotStepVerse(int); + void slotChangeBook(QString bookname); + void slotChangeChapter(int chapter); + void slotChangeVerse(int verse); + +private: + friend class CLexiconKeyChooser; + friend class BtDropdownChooserButton; + friend class BtBookDropdownChooserButton; + friend class BtChapterDropdownChooserButton; + friend class BtVerseDropdownChooserButton; + + boost::scoped_ptr<CSwordVerseKey> m_key; + + QLineEdit* m_textbox; + + CScrollerWidgetSet *m_bookScroller; + CScrollerWidgetSet *m_chapterScroller; + CScrollerWidgetSet *m_verseScroller; + + BtDropdownChooserButton* m_bookDropdownButton; + BtDropdownChooserButton* m_chapterDropdownButton; + BtDropdownChooserButton* m_verseDropdownButton; + + bool updatelock; + QString oldKey; + CSwordBibleModuleInfo *m_module; +}; + +#endif |