File indexing completed on 2025-01-26 04:57:23
0001 /* SPDX-FileCopyrightText: 2010 Torgny Nyblom <nyblom@kde.org> 0002 * SPDX-FileCopyrightText: 2010-2024 Laurent Montel <montel@kde.org> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "findbarbase.h" 0008 #include <KStatefulBrush> 0009 0010 #include <PimCommon/LineEditWithCompleterNg> 0011 0012 #include <KColorScheme> 0013 #include <KLocalizedString> 0014 #include <QIcon> 0015 #include <QLineEdit> 0016 0017 #include <QApplication> 0018 #include <QEvent> 0019 #include <QHBoxLayout> 0020 #include <QKeyEvent> 0021 #include <QLabel> 0022 #include <QMenu> 0023 #include <QPushButton> 0024 #include <QTimer> 0025 #include <QToolButton> 0026 0027 using namespace WebEngineViewer; 0028 0029 FindBarBase::FindBarBase(QWidget *parent) 0030 : QWidget(parent) 0031 { 0032 auto lay = new QHBoxLayout(this); 0033 lay->setContentsMargins({}); 0034 0035 auto closeBtn = new QToolButton(this); 0036 closeBtn->setIcon(QIcon::fromTheme(QStringLiteral("dialog-close"))); 0037 closeBtn->setObjectName(QLatin1StringView("close")); 0038 closeBtn->setIconSize(QSize(16, 16)); 0039 closeBtn->setToolTip(i18n("Close")); 0040 0041 #ifndef QT_NO_ACCESSIBILITY 0042 closeBtn->setAccessibleName(i18n("Close")); 0043 #endif 0044 0045 closeBtn->setAutoRaise(true); 0046 lay->addWidget(closeBtn); 0047 0048 auto label = new QLabel(i18nc("Find text", "F&ind:"), this); 0049 lay->addWidget(label); 0050 0051 mSearch = new PimCommon::LineEditWithCompleterNg(this); 0052 mSearch->setObjectName(QLatin1StringView("searchline")); 0053 mSearch->setToolTip(i18n("Text to search for")); 0054 mSearch->setClearButtonEnabled(true); 0055 label->setBuddy(mSearch); 0056 lay->addWidget(mSearch); 0057 0058 mFindNextBtn = new QPushButton(QIcon::fromTheme(QStringLiteral("go-down-search")), i18nc("Find and go to the next search match", "Next"), this); 0059 mFindNextBtn->setToolTip(i18n("Jump to next match")); 0060 mFindNextBtn->setObjectName(QLatin1StringView("findnext")); 0061 lay->addWidget(mFindNextBtn); 0062 mFindNextBtn->setEnabled(false); 0063 0064 mFindPrevBtn = new QPushButton(QIcon::fromTheme(QStringLiteral("go-up-search")), i18nc("Find and go to the previous search match", "Previous"), this); 0065 mFindPrevBtn->setToolTip(i18n("Jump to previous match")); 0066 mFindPrevBtn->setObjectName(QLatin1StringView("findprevious")); 0067 lay->addWidget(mFindPrevBtn); 0068 mFindPrevBtn->setEnabled(false); 0069 0070 auto optionsBtn = new QPushButton(this); 0071 optionsBtn->setText(i18n("Options")); 0072 optionsBtn->setToolTip(i18n("Modify search behavior")); 0073 mOptionsMenu = new QMenu(optionsBtn); 0074 mCaseSensitiveAct = mOptionsMenu->addAction(i18n("Case sensitive")); 0075 mCaseSensitiveAct->setCheckable(true); 0076 0077 optionsBtn->setMenu(mOptionsMenu); 0078 lay->addWidget(optionsBtn); 0079 0080 connect(closeBtn, &QToolButton::clicked, this, &FindBarBase::closeBar); 0081 connect(mFindNextBtn, &QPushButton::clicked, this, &FindBarBase::findNext); 0082 connect(mFindPrevBtn, &QPushButton::clicked, this, &FindBarBase::findPrev); 0083 connect(mCaseSensitiveAct, &QAction::toggled, this, &FindBarBase::caseSensitivityChanged); 0084 connect(mSearch, &QLineEdit::textChanged, this, &FindBarBase::autoSearch); 0085 connect(mSearch, &QLineEdit::returnPressed, this, &FindBarBase::findNext); 0086 0087 mStatus = new QLabel(this); 0088 mStatus->setObjectName(QLatin1StringView("status")); 0089 mStatus->setTextFormat(Qt::PlainText); 0090 QFontMetrics fm(mStatus->font()); 0091 mNotFoundString = i18n("Phrase not found"); 0092 mStatus->setFixedWidth(fm.boundingRect(mNotFoundString).width()); 0093 lay->addWidget(mStatus); 0094 0095 setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed)); 0096 hide(); 0097 } 0098 0099 FindBarBase::~FindBarBase() = default; 0100 0101 QMenu *FindBarBase::optionsMenu() const 0102 { 0103 return mOptionsMenu; 0104 } 0105 0106 QString FindBarBase::text() const 0107 { 0108 return mSearch->text(); 0109 } 0110 0111 void FindBarBase::setText(const QString &text) 0112 { 0113 mSearch->setText(text); 0114 addToCompletion(text); 0115 } 0116 0117 void FindBarBase::focusAndSetCursor() 0118 { 0119 setFocus(); 0120 mStatus->clear(); 0121 mSearch->selectAll(); 0122 mSearch->setFocus(); 0123 } 0124 0125 void FindBarBase::slotClearSearch() 0126 { 0127 clearSelections(); 0128 } 0129 0130 void FindBarBase::autoSearch(const QString &str) 0131 { 0132 const bool isNotEmpty = (!str.isEmpty()); 0133 mFindPrevBtn->setEnabled(isNotEmpty); 0134 mFindNextBtn->setEnabled(isNotEmpty); 0135 if (isNotEmpty) { 0136 QTimer::singleShot(0, this, [this]() { 0137 slotSearchText(); 0138 }); 0139 } else { 0140 mStatus->clear(); 0141 clearSelections(); 0142 } 0143 } 0144 0145 void FindBarBase::slotSearchText(bool backward, bool isAutoSearch) 0146 { 0147 searchText(backward, isAutoSearch); 0148 } 0149 0150 void FindBarBase::updatePalette() 0151 { 0152 KStatefulBrush bgBrush(KColorScheme::View, KColorScheme::PositiveBackground); 0153 mPositiveBackground = QStringLiteral("QLineEdit{ background-color:%1 }").arg(bgBrush.brush(mSearch->palette()).color().name()); 0154 bgBrush = KStatefulBrush(KColorScheme::View, KColorScheme::NegativeBackground); 0155 mNegativeBackground = QStringLiteral("QLineEdit{ background-color:%1 }").arg(bgBrush.brush(mSearch->palette()).color().name()); 0156 } 0157 0158 void FindBarBase::setFoundMatch(bool match) 0159 { 0160 #ifndef QT_NO_STYLE_STYLESHEET 0161 QString styleSheet; 0162 0163 if (!mSearch->text().isEmpty()) { 0164 if (mNegativeBackground.isEmpty()) { 0165 updatePalette(); 0166 } 0167 if (match) { 0168 styleSheet = mPositiveBackground; 0169 mStatus->clear(); 0170 } else { 0171 styleSheet = mNegativeBackground; 0172 mStatus->setText(mNotFoundString); 0173 } 0174 } 0175 mSearch->setStyleSheet(styleSheet); 0176 #endif 0177 } 0178 0179 void FindBarBase::searchText(bool backward, bool isAutoSearch) 0180 { 0181 Q_UNUSED(backward) 0182 Q_UNUSED(isAutoSearch) 0183 } 0184 0185 void FindBarBase::addToCompletion(const QString &text) 0186 { 0187 mSearch->addCompletionItem(text); 0188 } 0189 0190 void FindBarBase::findNext() 0191 { 0192 searchText(false, false); 0193 addToCompletion(mLastSearchStr); 0194 } 0195 0196 void FindBarBase::findPrev() 0197 { 0198 searchText(true, false); 0199 addToCompletion(mLastSearchStr); 0200 } 0201 0202 void FindBarBase::caseSensitivityChanged(bool b) 0203 { 0204 updateSensitivity(b); 0205 } 0206 0207 void FindBarBase::updateSensitivity(bool) 0208 { 0209 } 0210 0211 void FindBarBase::slotHighlightAllChanged(bool b) 0212 { 0213 updateHighLight(b); 0214 } 0215 0216 void FindBarBase::updateHighLight(bool) 0217 { 0218 } 0219 0220 void FindBarBase::clearSelections() 0221 { 0222 setFoundMatch(false); 0223 } 0224 0225 void FindBarBase::closeBar() 0226 { 0227 // Make sure that all old searches are cleared 0228 mSearch->clear(); 0229 clearSelections(); 0230 mSearch->clearFocus(); 0231 Q_EMIT hideFindBar(); 0232 } 0233 0234 bool FindBarBase::event(QEvent *e) 0235 { 0236 // Close the bar when pressing Escape. 0237 // Not using a QShortcut for this because it could conflict with 0238 // window-global actions (e.g. Emil Sedgh binds Esc to "close tab"). 0239 // With a shortcut override we can catch this before it gets to kactions. 0240 const bool shortCutOverride = (e->type() == QEvent::ShortcutOverride); 0241 if (shortCutOverride || e->type() == QEvent::KeyPress) { 0242 auto kev = static_cast<QKeyEvent *>(e); 0243 if (kev->key() == Qt::Key_Escape) { 0244 if (shortCutOverride) { 0245 e->accept(); 0246 return true; 0247 } 0248 e->accept(); 0249 closeBar(); 0250 return true; 0251 } else if (kev->key() == Qt::Key_Enter || kev->key() == Qt::Key_Return) { 0252 e->accept(); 0253 if (shortCutOverride) { 0254 return true; 0255 } 0256 if (mSearch->text().isEmpty()) { 0257 return true; 0258 } 0259 if (kev->modifiers() & Qt::ShiftModifier) { 0260 findPrev(); 0261 } else if (kev->modifiers() == Qt::NoModifier) { 0262 findNext(); 0263 } 0264 return true; 0265 } 0266 } 0267 if (e->type() == QEvent::ApplicationPaletteChange) { 0268 updatePalette(); 0269 } 0270 return QWidget::event(e); 0271 } 0272 0273 #include "moc_findbarbase.cpp"