/********* * * This file is part of BibleTime's source code, http://www.bibletime.info/. * * Copyright 1999-2014 by the BibleTime developers. * The BibleTime source code is licensed under the GNU General Public License version 2.0. * **********/ #include "frontend/searchdialog/crangechooserdialog.h" #include #include #include #include #include #include #include #include #include #include #include "backend/config/btconfig.h" #include "frontend/messagedialog.h" // Sword includes: #include "versekey.h" #include "listkey.h" namespace Search { CRangeChooserDialog::CRangeChooserDialog(QWidget *parentDialog) : QDialog(parentDialog) { initView(); initConnections(); retranslateUi(); // Add the existing scopes BtConfig::StringMap map = btConfig().getSearchScopesForCurrentLocale(); BtConfig::StringMap::Iterator it; for (it = map.begin(); it != map.end(); ++it) { new RangeItem(it.key(), it.value(), m_rangeList); } resetEditControls(); } void CRangeChooserDialog::initView() { m_rangeList = new QListWidget(this); m_rangeListLabel = new QLabel(this); m_rangeListLabel->setBuddy(m_rangeList); m_newRangeButton = new QPushButton(this); m_deleteRangeButton = new QPushButton(this); m_nameEdit = new QLineEdit(this); m_nameEditLabel = new QLabel(this); m_nameEditLabel->setBuddy(m_nameEdit); m_rangeEdit = new QTextEdit(this); m_rangeEditLabel = new QLabel(this); m_rangeEditLabel->setBuddy(m_rangeEdit); m_resultList = new QListWidget(this); m_resultListLabel = new QLabel(this); m_resultListLabel->setBuddy(m_resultList); QFrame *hSeparatorLine = new QFrame(this); hSeparatorLine->setFrameShape(QFrame::HLine); hSeparatorLine->setFrameShadow(QFrame::Sunken); m_buttonBox = new QDialogButtonBox(this); m_buttonBox->setOrientation(Qt::Horizontal); m_buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::RestoreDefaults); message::prepareDialogBox(m_buttonBox); QHBoxLayout *rangeButtonsLayout = new QHBoxLayout(); rangeButtonsLayout->addWidget(m_newRangeButton); rangeButtonsLayout->addWidget(m_deleteRangeButton); QVBoxLayout* rangeListLayout = new QVBoxLayout; rangeListLayout->addWidget(m_rangeListLabel); rangeListLayout->addWidget(m_rangeList); rangeListLayout->addLayout(rangeButtonsLayout); QHBoxLayout* nameEditLayout = new QHBoxLayout(); nameEditLayout->addWidget(m_nameEditLabel); nameEditLayout->addWidget(m_nameEdit); QVBoxLayout* rangeEditLayout = new QVBoxLayout(); rangeEditLayout->addLayout(nameEditLayout); rangeEditLayout->addWidget(m_rangeEditLabel); rangeEditLayout->addWidget(m_rangeEdit); rangeEditLayout->addWidget(m_resultListLabel); rangeEditLayout->addWidget(m_resultList); QHBoxLayout *topLayout = new QHBoxLayout; topLayout->addLayout(rangeListLayout); topLayout->addLayout(rangeEditLayout); QVBoxLayout *vboxLayout = new QVBoxLayout(this); vboxLayout->addLayout(topLayout); vboxLayout->addWidget(hSeparatorLine); vboxLayout->addWidget(m_buttonBox); } void CRangeChooserDialog::initConnections() { connect(m_rangeList, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), this, SLOT(selectedRangeChanged(QListWidgetItem*, QListWidgetItem*))); connect(m_nameEdit, SIGNAL(textEdited(QString)), this, SLOT(nameEditTextChanged(QString))); connect(m_rangeEdit, SIGNAL(textChanged()), this, SLOT(updateResultList())); // Connect buttons: connect(m_buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(m_buttonBox, SIGNAL(rejected()), this, SLOT(reject())); connect(m_newRangeButton, SIGNAL(clicked()), this, SLOT(addNewRange())); connect(m_deleteRangeButton, SIGNAL(clicked()), this, SLOT(deleteCurrentRange())); QPushButton * defaultsButton = m_buttonBox->button(QDialogButtonBox::RestoreDefaults); connect(defaultsButton, SIGNAL(clicked()), this, SLOT(restoreDefaults())); } void CRangeChooserDialog::retranslateUi() { setWindowTitle(tr("Setup Search Scopes")); m_rangeListLabel->setText(tr("S&earch range:")); m_rangeList->setToolTip(tr("Select a scope from the list to edit the search" "ranges")); m_newRangeButton->setText(tr("&Add new scope")); m_newRangeButton->setToolTip(tr("Add a new search scope. First enter an " "appropriate name, then edit the search " "ranges.")); m_deleteRangeButton->setText(tr("Delete current &scope")); m_deleteRangeButton->setToolTip(tr("Delete the selected search scope")); m_nameEditLabel->setText(tr("&Name:")); m_nameEdit->setToolTip(tr("Change the name of the selected search scope")); m_rangeEditLabel->setText(tr("Edi&t current range:")); m_rangeEdit->setToolTip(tr("Change the search ranges of the selected search" "scope item. Have a look at the predefined " "search scopes to see how search ranges are " "constructed.")); m_resultListLabel->setText(tr("Parsed search range:")); m_resultList->setToolTip(tr("The search ranges which will be used for the " "search, parsed to the canonical form")); } void CRangeChooserDialog::saveCurrentToRange(RangeItem * i) { if (!m_nameEdit->text().isEmpty()) i->setCaption(m_nameEdit->text()); i->setRange(m_rangeEdit->toPlainText()); } void CRangeChooserDialog::addNewRange() { static const QString nullStr; RangeItem * const i = new RangeItem(tr("New range"), nullStr, m_rangeList); m_rangeList->setCurrentItem(i); resetEditControls(); } void CRangeChooserDialog::selectedRangeChanged(QListWidgetItem * current, QListWidgetItem * previous) { Q_UNUSED(current); if (previous) { Q_ASSERT(dynamic_cast(previous) != 0); saveCurrentToRange(static_cast(previous)); } resetEditControls(); } void CRangeChooserDialog::resetEditControls() { const QListWidgetItem * const item = m_rangeList->currentItem(); Q_ASSERT(item == 0 || dynamic_cast(item) != 0); const RangeItem * rangeItem = static_cast(item); m_nameEdit->setEnabled(item != 0); m_rangeEdit->setEnabled(item != 0); m_resultList->setEnabled(item != 0); m_deleteRangeButton->setEnabled(item != 0); m_nameEdit->setText(item != 0 ? rangeItem->caption() : ""); m_rangeEdit->setText(item != 0 ? rangeItem->range() : ""); if (item != 0) m_nameEdit->setFocus(); nameEditTextChanged(item != 0 ? rangeItem->caption() : ""); } void CRangeChooserDialog::updateResultList() { typedef sword::VerseKey VK; m_resultList->clear(); /// \todo remove this hack: //HACK: repair range to work with Sword 1.5.6 const QString range = m_rangeEdit->toPlainText().replace(QRegExp("\\s{0,}-\\s{0,}"), "-"); sword::ListKey verses = VK().parseVerseList(range.toUtf8().constData(), "Genesis 1:1", true); for (int i = 0; i < verses.getCount(); i++) { new QListWidgetItem(QString::fromUtf8(verses.getElement(i)->getRangeText()), m_resultList); } } void CRangeChooserDialog::deleteCurrentRange() { Q_ASSERT(dynamic_cast(m_rangeList->currentItem()) != 0); QListWidgetItem *i = m_rangeList->currentItem(); m_rangeList->removeItemWidget(i); delete i; resetEditControls(); } void CRangeChooserDialog::accept() { // Update the active item: QListWidgetItem *currentItem = m_rangeList->currentItem(); if (currentItem != 0) { Q_ASSERT(dynamic_cast(currentItem) != 0); saveCurrentToRange(static_cast(currentItem)); } // Save the new sorted map of search scopes: m_rangeList->sortItems(); BtConfig::StringMap map; for (int i = 0; i < m_rangeList->count(); i++) { Q_ASSERT(dynamic_cast(m_rangeList->item(i)) != 0); const RangeItem * item = static_cast(m_rangeList->item(i)); map[item->caption()] = item->range(); } btConfig().setSearchScopesWithCurrentLocale(map); QDialog::accept(); } void CRangeChooserDialog::restoreDefaults() { typedef BtConfig::StringMap::ConstIterator SMCI; m_rangeList->clear(); btConfig().deleteSearchScopesWithCurrentLocale(); const BtConfig::StringMap map = btConfig().getSearchScopesForCurrentLocale(); for (SMCI it = map.begin(); it != map.end(); ++it) { new RangeItem(it.key(), it.value(), m_rangeList); }; m_rangeList->setCurrentItem(0); resetEditControls(); } void CRangeChooserDialog::nameEditTextChanged(const QString &newText) { const bool e = !newText.isEmpty() || m_rangeList->count() <= 0; m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(e); } } //end of namespace Search