diff options
Diffstat (limited to 'src/frontend/keychooser/cbookkeychooser.cpp')
-rw-r--r-- | src/frontend/keychooser/cbookkeychooser.cpp | 278 |
1 files changed, 278 insertions, 0 deletions
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); +} |