BibleTime
ckeychooserwidget.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-2021 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 "ckeychooserwidget.h"
14 
15 #include <QComboBox>
16 #include <QEvent>
17 #include <QFocusEvent>
18 #include <QHBoxLayout>
19 #include <QLineEdit>
20 #include <QNonConstOverload>
21 #include <QString>
22 #include <Qt>
23 #include "../../util/btassert.h"
24 #include "../../util/btconnect.h"
25 #include "cscrollerwidgetset.h"
26 
27 
28 class BtKeyLineEdit : public QLineEdit {
29 
30 public: // methods:
31 
33  : QLineEdit(parent) {}
34 
35 protected: // methods:
36 
37  void focusInEvent(QFocusEvent * event) override {
38  const Qt::FocusReason reason = event->reason();
39  if (reason == Qt::OtherFocusReason)
40  selectAll();
41  QWidget::focusInEvent(event);
42  }
43 
44 };
45 
46 
48  : QComboBox(parent)
49 {
50  setFocusPolicy(Qt::WheelFocus);
51  setLineEdit(new BtKeyLineEdit(this));
52  if (lineEdit())
53  installEventFilter(lineEdit());
54 }
55 
56 bool CKCComboBox::eventFilter(QObject * o, QEvent * e) {
57  if (e->type() == QEvent::FocusOut) {
58  QFocusEvent * const f = static_cast<QFocusEvent *>(e);
59 
60  if (o == lineEdit() && f->reason() == Qt::TabFocusReason) {
61  int index = findText(currentText());
62  if (index == -1)
63  index = 0; // return 0 if not found
64  setCurrentIndex(index);
65  Q_EMIT focusOut(index);
66  return false;
67  }
68 
69  if (f->reason() == Qt::PopupFocusReason)
70  return false;
71 
72  if (f->reason() == Qt::ActiveWindowFocusReason) {
73  Q_EMIT textActivated(currentText());
74  return false;
75  }
76 
77  if (f->reason() == Qt::MouseFocusReason) {
78  Q_EMIT textActivated(currentText());
79  return false;
80  }
81 
82  if (o == this) {
83  Q_EMIT textActivated(currentText());
84  return false;
85  }
86  }
87 
88  return QComboBox::eventFilter(o, e);
89 }
90 
91 
92 //**********************************************************************************/
93 
95  : QWidget(parent)
96 {
97  for (int index = 1; index <= count; index++) {
98  m_list.append( QString::number(index) );
99  }
100  init();
101  reset(m_list, 0, false);
102 }
103 
104 CKeyChooserWidget::CKeyChooserWidget(QStringList * list, QWidget * parent )
105  : QWidget(parent)
106 {
107  if (list)
108  m_list = *list;
109 
110  init();
111  reset(m_list, 0, false);
112 }
113 
114 void CKeyChooserWidget::reset(const int count, int index, bool do_emit) {
115  //This prevents the widget from resetting during application load, which
116  //produces undesirable behavior.
117  //if (!updatesEnabled())
118  // return;
119 
120  m_list.clear();
121  for (int i = 1; i <= count; i++) /// \todo CHECK
122  m_list.append(QString::number(i));
123 
124  reset(&m_list, index, do_emit);
125 }
126 
127 void CKeyChooserWidget::reset(const QStringList & list, int index, bool do_emit) {
128  //This prevents the widget from resetting during application load, which
129  //produces undesirable behavior.
130  //if (!updatesEnabled())
131  // return;
132 
133  m_list = list;
134  reset(&m_list, index, do_emit);
135 }
136 
137 
138 void CKeyChooserWidget::reset(const QStringList * list, int index, bool do_emit) {
139  //if (isResetting || !updatesEnabled())
140  if (m_isResetting)
141  return;
142 
143  // qWarning("starting insert");
144  m_isResetting = true;
145 
146  m_oldKey = QString();
147 
148  // m_comboBox->setUpdatesEnabled(false);
149  //DON'T REMOVE THE HIDE: Otherwise QComboBox's sizeHint() function won't work properly
150  m_comboBox->hide();
151  m_comboBox->clear();
152  if (list && !list->empty()) {
153  m_comboBox->insertItems(0, *list); // Prepend items
154  setEnabled(true);
155  m_comboBox->setCurrentIndex(index);
156  } else {
157  setEnabled(false);
158  }
159 
160  if (do_emit)
161  Q_EMIT changed(m_comboBox->currentIndex());
162 
163  m_comboBox->sizeHint(); //without this function call the combo box won't be properly sized!
164  //DON'T REMOVE OR MOVE THE show()! Otherwise QComboBox's sizeHint() function won't work properly!
165  m_comboBox->show();
166 
167  // m_comboBox->setFont( m_comboBox->font() );
168  // m_comboBox->setUpdatesEnabled(true);
169 
170  m_isResetting = false;
171  // qWarning("inserted");
172 }
173 
174 /** Initializes this widget. We need this function because we have more than one constructor. */
176  m_oldKey = QString();
177 
178  setFocusPolicy(Qt::WheelFocus);
179 
180  m_comboBox = new CKCComboBox(this);
181  setFocusProxy(m_comboBox);
182  m_comboBox->setEditable(true); // Also sets completer
183  BT_ASSERT(m_comboBox->completer());
184  m_comboBox->setInsertPolicy(QComboBox::NoInsert);
185  m_comboBox->setFocusPolicy(Qt::WheelFocus);
186 
187  m_mainLayout = new QHBoxLayout(this);
188  m_mainLayout->setSpacing(0);
189  m_mainLayout->setContentsMargins(0, 0, 0, 0);
190  m_mainLayout->addWidget(m_comboBox);
191 
192  m_scroller = new CScrollerWidgetSet(this);
193 
194  m_mainLayout->addWidget(m_scroller);
195  m_mainLayout->addSpacing(0);
196 
197  setTabOrder(m_comboBox, nullptr);
198  setFocusProxy(m_comboBox);
199 
201  [this]{
202  updatelock = true;
203  m_comboBox->setEditable(false);
204  m_oldKey = m_comboBox->currentText();
205  });
207  [this]{
208  updatelock = false;
209  m_comboBox->setEditable(true);
210  m_comboBox->setEditText(
211  m_comboBox->itemText(
212  m_comboBox->currentIndex()));
213  if (m_comboBox->currentText() != m_oldKey)
214  Q_EMIT changed(m_comboBox->currentIndex());
215  });
217  [this](int n) {
218  const int old_index = m_comboBox->currentIndex();
219  int new_index = old_index + n;
220 
221  //index of highest Item
222  const int max = m_comboBox->count() - 1;
223  if (new_index > max)
224  new_index = max;
225  if (new_index < 0)
226  new_index = 0;
227 
228  if (new_index != old_index) {
229  m_comboBox->setCurrentIndex(new_index);
230  if (!updatelock)
231  Q_EMIT changed(new_index);
232  }
233  });
234  BT_CONNECT(m_comboBox, qOverload<int>(&QComboBox::activated),
235  [this](int index) {
236  if (!updatesEnabled())
237  return;
238 
239  setUpdatesEnabled(false);
240 
241  const QString key(m_comboBox->itemText(index));
242  if (m_oldKey.isNull() || (m_oldKey != key))
243  Q_EMIT changed(index);
244 
245  m_oldKey = key;
246 
247  setUpdatesEnabled(true);
248  });
249  BT_CONNECT(m_comboBox->lineEdit(), &QLineEdit::returnPressed,
250  [this]{
251  BT_ASSERT(m_comboBox->lineEdit());
252 
253  const QString text(m_comboBox->lineEdit()->text());
254  for (int index = 0; index < m_comboBox->count(); ++index) {
255  if (m_comboBox->itemText(index) == text) {
256  // emit changed(index);
257  /* a workaround because focusOut is not checked, the
258  slot connected to changed to check: */
259  Q_EMIT focusOut(index);
260  break;
261  }
262  }
263  });
264  BT_CONNECT(m_comboBox, &CKCComboBox::focusOut,
266 
267  updatelock = false;
268  m_isResetting = false;
269 }
270 
271 /** Sets the tooltips for the given entries using the parameters as text. */
272 void CKeyChooserWidget::setToolTips(const QString & comboTip,
273  const QString & nextEntryTip,
274  const QString & scrollButtonTip,
275  const QString & previousEntryTip)
276 {
277  m_comboBox->setToolTip(comboTip);
278  m_scroller->setToolTips(nextEntryTip, scrollButtonTip, previousEntryTip);
279 }
280 
281 /** Sets the current item to the one with the given text */
282 bool CKeyChooserWidget::setItem(const QString & item) {
283  bool ret = false;
284  const int count = m_comboBox->count();
285  for (int i = 0; i < count; ++i) {
286  if (m_comboBox->itemText(i) == item) {
287  m_comboBox->setCurrentIndex(i);
288  ret = true;
289  break;
290  }
291  }
292  if (!ret)
293  m_comboBox->setCurrentIndex(-1);
294  return ret;
295 }
#define BT_ASSERT(...)
Definition: btassert.h:17
#define BT_CONNECT(...)
Definition: btconnect.h:20
BtKeyLineEdit(QWidget *parent)
void focusInEvent(QFocusEvent *event) override
CKCComboBox(QWidget *parent=nullptr)
void focusOut(int itemIndex)
bool eventFilter(QObject *o, QEvent *e) override
QHBoxLayout * m_mainLayout
void focusOut(int index)
bool setItem(const QString &item)
CKeyChooserWidget(QStringList *list=nullptr, QWidget *parent=nullptr)
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)
CScrollerWidgetSet * m_scroller
CKCComboBox * m_comboBox
void setToolTips(const QString &nextEntry, const QString &scrollButton, const QString &previousEntry)
void change(int count)
if(plainSearchedText)