BibleTime
clexiconkeychooser.cpp
Go to the documentation of this file.
1/*********
2*
3* In the name of the Father, and of the Son, and of the Holy Spirit.
4*
5* This file is part of BibleTime's source code, https://bibletime.info/
6*
7* Copyright 1999-2025 by the BibleTime developers.
8* The BibleTime source code is licensed under the GNU General Public License
9* version 2.0.
10*
11**********/
12
13#include "clexiconkeychooser.h"
14
15#include <algorithm>
16#include <iterator>
17#include <map>
18#include <QBoxLayout>
19#include <QComboBox>
20#include <QHBoxLayout>
21#include <QLayout>
22#include <QStringList>
23#include <Qt>
24#include <utility>
25#include "../../backend/drivers/btmodulelist.h"
26#include "../../backend/drivers/cswordlexiconmoduleinfo.h"
27#include "../../backend/drivers/cswordmoduleinfo.h"
28#include "../../backend/keys/cswordkey.h"
29#include "../../backend/keys/cswordldkey.h"
30#include "../../util/btconnect.h"
31#include "ckeychooserwidget.h"
32
33
35 CSwordKey * key,
36 QWidget * parent)
37 : CKeyChooser(parent)
38 , m_key(dynamic_cast<CSwordLDKey *>(key))
39{
40 setModules(modules, false);
41
42 //we use a layout because the key chooser should be resized to full size
43 auto * const l = new QHBoxLayout(this);
44 l->setSpacing(0);
45 l->setContentsMargins(0, 0, 0, 0);
46 l->setDirection(QBoxLayout::LeftToRight);
47 l->setSizeConstraint(QLayout::SetNoConstraint);
48
49 m_widget = new CKeyChooserWidget(0, this);
50 setFocusProxy(m_widget);
51
52 //don't allow a too high width, try to keep as narrow as possible
53 //to aid users with smaller screen resolutions
54 m_widget->comboBox().setMaximumWidth(200);
55
57 tr("Entries of the current work"),
58 tr("Next entry"),
59 tr("Scroll through the entries of the list. Press the button and move the mouse to increase or decrease the item."),
60 tr("Previous entry")
61 );
62
63 l->addWidget(m_widget, 0, Qt::AlignLeft);
64
65 auto const activatedSlot =
66 [this](int index) {
67 if (m_key) {
68 auto text(m_widget->comboBox().itemText(index));
69 /* Check to prevent from eternal loop, because activated()
70 is emitted again: */
71 if (m_key->key() != text) {
72 m_key->setKey(std::move(text));
74 }
75 }
76 };
79
80 setModules(modules, true);
81 setKey(key);
82}
83
85 // qWarning("key");
86 return m_key;
87}
88
89/** Update key display without emiting a signal */
91 if (!(m_key = dynamic_cast<CSwordLDKey*>(key))) {
92 return;
93 }
94
95 QString newKey = m_key->key();
96 const int index = m_widget->comboBox().findText(newKey);
97 m_widget->comboBox().setCurrentIndex(index);
98}
99
101 if (!(m_key = dynamic_cast<CSwordLDKey*>(key))) {
102 return;
103 }
104
105 updateKey(key);
106
107 // qWarning("setKey end");
108 Q_EMIT keyChanged( m_key);
109}
110
111/** Reimplementation. */
113 if (m_modules.count() == 1) {
114 m_widget->reset(&m_modules.first()->entries(), 0, true);
115 // qWarning("resetted");
116 }
117 else {
118 std::multimap<unsigned int, QStringList const *> entryMap;
119 for (auto const * const modulePtr : m_modules) {
120 auto const & entries = modulePtr->entries();
121 entryMap.emplace(entries.count(), &entries);
122 }
123
124 QStringList goodEntries; //The string list which contains the entries which are available in all modules
125
126 auto it(entryMap.begin()); // iterator to go though all selected modules
127 QStringList refEntries = *(it->second); //copy the items for the first time
128 const QStringList *cmpEntries = (++it)->second; //list for comparision, starts with the second module in the map
129
130 // Testing for refEntries being empty is not needed for the set union
131 // of all keys, but is a good idea since it is being updated in the
132 // loop. It is necessary for set intersection and prevents a crash.
133 while (it != entryMap.end() && (refEntries.begin() != refEntries.end())) {
134 std::set_union(
135 refEntries.begin(), --(refEntries.end()), //--end() is the last valid entry
136 cmpEntries->begin(), --(cmpEntries->end()),
137 std::back_inserter(goodEntries) //append valid entries to the end of goodEntries
138 );
139
140 cmpEntries = ( ++it )->second; //this is a pointer to the string list of a new module
141
142 /*
143 * use the good entries for next comparision,
144 * because the final list can only have the entries of goodEntries as maxiumum
145 */
146 refEntries = goodEntries;
147 }
148
149 m_widget->reset(goodEntries, 0, true); //write down the entries
150 } //end of ELSE
151
152}
153
155 bool refresh)
156{
157 using CSLMI = CSwordLexiconModuleInfo;
158
159 while (!m_modules.isEmpty())
160 m_modules.takeFirst(); // not deleting the pointer
161
162 for (auto const * const m : modules)
163 if (CSLMI const * const lexicon = dynamic_cast<CSLMI const *>(m))
164 m_modules.append(lexicon);
165
166 if (refresh) {
168 }
169}
#define BT_CONNECT(...)
Definition btconnect.h:20
QList< CSwordModuleInfo const * > BtConstModuleList
void focusOut(int index)
void setToolTips(const QString &comboTip, const QString &nextEntry, const QString &scrollButton, const QString &previousEntry)
void changed(int index)
void reset(const int count, int index, bool do_emit)
QComboBox & comboBox() const
void keyChanged(CSwordKey *newKey)
QList< CSwordLexiconModuleInfo const * > m_modules
CSwordKey * key() final override
void setModules(BtConstModuleList const &modules, bool refresh=true) final override
void setKey(CSwordKey *key) final override
void refreshContent() final override
CKeyChooserWidget * m_widget
CLexiconKeyChooser(BtConstModuleList const &modules, CSwordKey *key=nullptr, QWidget *parent=nullptr)
void updateKey(CSwordKey *key) final override
bool setKey(const QString &newKey) final override
QString key() const final override