File indexing completed on 2024-05-19 05:42:27

0001 // ct_lvtqtw_searchwidget.h                                            -*-C++-*-
0002 
0003 /*
0004 // Copyright 2023 Codethink Ltd <codethink@codethink.co.uk>
0005 // SPDX-License-Identifier: Apache-2.0
0006 //
0007 // Licensed under the Apache License, Version 2.0 (the "License");
0008 // you may not use this file except in compliance with the License.
0009 // You may obtain a copy of the License at
0010 //
0011 //     http://www.apache.org/licenses/LICENSE-2.0
0012 //
0013 // Unless required by applicable law or agreed to in writing, software
0014 // distributed under the License is distributed on an "AS IS" BASIS,
0015 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0016 // See the License for the specific language governing permissions and
0017 // limitations under the License.
0018 */
0019 
0020 #include <ct_lvtqtw_searchwidget.h>
0021 #include <ui_ct_lvtqtw_searchwidget.h>
0022 
0023 #include <QAction>
0024 #include <QActionGroup>
0025 #include <QKeyEvent>
0026 
0027 using namespace Codethink::lvtqtw;
0028 
0029 struct SearchWidget::Private {
0030     int elementsFound = 0;
0031     int currentElement = 0;
0032 
0033     QToolButton *lastBtn = nullptr;
0034 };
0035 
0036 SearchWidget::SearchWidget(QWidget *parent):
0037     QWidget(parent), d(std::make_unique<SearchWidget::Private>()), ui(std::make_unique<Ui::SearchWidget>())
0038 {
0039     ui->setupUi(this);
0040     connect(ui->btnNext, &QToolButton::clicked, this, [this] {
0041         d->lastBtn = ui->btnNext;
0042         Q_EMIT requestNextElement();
0043     });
0044 
0045     connect(ui->btnPrevious, &QToolButton::clicked, this, [this] {
0046         d->lastBtn = ui->btnPrevious;
0047         Q_EMIT requestPreviousElement();
0048     });
0049 
0050     auto *actions = new QActionGroup(this);
0051     actions->setExclusive(true);
0052 
0053     auto *ignoreCaseAction = new QAction(tr("Ignore Case"));
0054     auto *matchCaseAction = new QAction(tr("Match Case"));
0055     auto *regularExpression = new QAction(tr("Regular Expression"));
0056 
0057     for (const auto& [action, enum_] : std::initializer_list<std::pair<QAction *, lvtshr::SearchMode>>{
0058              {ignoreCaseAction, lvtshr::SearchMode::CaseInsensitive},
0059              {matchCaseAction, lvtshr::SearchMode::CaseSensitive},
0060              {regularExpression, lvtshr::SearchMode::RegularExpressions}}) {
0061         action->setCheckable(true);
0062         actions->addAction(action);
0063         ui->btnConfig->addAction(action);
0064         connect(action, &QAction::triggered, this, [this, action = action, enum_ = enum_](bool toggled) {
0065             if (action->isChecked()) {
0066                 Q_EMIT searchModeChanged(enum_);
0067             }
0068         });
0069     }
0070     ignoreCaseAction->setChecked(true);
0071     d->lastBtn = ui->btnNext;
0072 
0073     connect(ui->searchLine, &QLineEdit::textChanged, this, &SearchWidget::searchStringChanged);
0074     calculateNrOfElementsLabel();
0075     ui->searchLine->installEventFilter(this);
0076 }
0077 
0078 SearchWidget::~SearchWidget() = default;
0079 
0080 bool SearchWidget::eventFilter(QObject *object, QEvent *event)
0081 {
0082     Q_UNUSED(object);
0083     if (event->type() == QEvent::KeyPress) {
0084         auto *ev = static_cast<QKeyEvent *>(event); // NOLINT
0085         if (ev->key() == Qt::Key_Return) {
0086             d->lastBtn->click();
0087         }
0088         if (ev->key() == Qt::Key_Escape) {
0089             setVisible(false);
0090         }
0091     }
0092     return false;
0093 }
0094 
0095 void SearchWidget::setNumberOfMatchedItems(int nr)
0096 {
0097     d->elementsFound = nr;
0098     d->currentElement = 0;
0099     calculateNrOfElementsLabel();
0100 }
0101 
0102 void SearchWidget::setCurrentItem(int nr)
0103 {
0104     d->currentElement = nr;
0105     calculateNrOfElementsLabel();
0106 }
0107 
0108 void SearchWidget::calculateNrOfElementsLabel()
0109 {
0110     const QString text =
0111         tr("%1 out of %2 ocurrences").arg(d->elementsFound == 0 ? 0 : d->currentElement).arg(d->elementsFound);
0112 
0113     ui->lblFound->setText(text);
0114     ui->btnNext->setEnabled(d->elementsFound != 0);
0115     ui->btnPrevious->setEnabled(d->elementsFound != 0);
0116 }
0117 
0118 void SearchWidget::hideEvent(QHideEvent *ev)
0119 {
0120     Q_UNUSED(ev);
0121     ui->searchLine->setText(QString());
0122     setNumberOfMatchedItems(0);
0123     setCurrentItem(0);
0124 }
0125 
0126 void SearchWidget::showEvent(QShowEvent *ev)
0127 {
0128     Q_UNUSED(ev);
0129     ui->searchLine->setFocus();
0130 }