File indexing completed on 2024-05-26 04:46:50

0001 /*
0002    SPDX-FileCopyrightText: 2014-2024 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "textgotolinewidget.h"
0008 
0009 #include <KLocalizedString>
0010 #include <QIcon>
0011 #include <QPushButton>
0012 
0013 #include <QHBoxLayout>
0014 #include <QKeyEvent>
0015 #include <QLabel>
0016 #include <QSpinBox>
0017 #include <QToolButton>
0018 
0019 using namespace TextCustomEditor;
0020 
0021 class Q_DECL_HIDDEN TextCustomEditor::TextGoToLineWidgetPrivate
0022 {
0023 public:
0024     TextGoToLineWidgetPrivate() = default;
0025 
0026     QSpinBox *mSpinbox = nullptr;
0027     QPushButton *mGoToLine = nullptr;
0028 };
0029 
0030 TextGoToLineWidget::TextGoToLineWidget(QWidget *parent)
0031     : QWidget(parent)
0032     , d(new TextCustomEditor::TextGoToLineWidgetPrivate)
0033 {
0034     auto hbox = new QHBoxLayout(this);
0035     hbox->setContentsMargins(2, 2, 2, 2);
0036     auto closeBtn = new QToolButton(this);
0037     closeBtn->setIcon(QIcon::fromTheme(QStringLiteral("dialog-close")));
0038     closeBtn->setIconSize(QSize(16, 16));
0039     closeBtn->setToolTip(i18n("Close"));
0040     closeBtn->setObjectName(QStringLiteral("closebutton"));
0041 #ifndef QT_NO_ACCESSIBILITY
0042     closeBtn->setAccessibleName(i18n("Close"));
0043 #endif
0044 
0045     closeBtn->setAutoRaise(true);
0046     connect(closeBtn, &QToolButton::clicked, this, &TextGoToLineWidget::slotCloseBar);
0047     hbox->addWidget(closeBtn);
0048 
0049     auto lab = new QLabel(i18n("Go to Line:"));
0050     hbox->addWidget(lab);
0051     d->mSpinbox = new QSpinBox(this);
0052     d->mSpinbox->setMinimum(1);
0053     d->mSpinbox->setObjectName(QStringLiteral("line"));
0054     connect(d->mSpinbox, &QSpinBox::editingFinished, this, &TextGoToLineWidget::slotGoToLine);
0055     hbox->addWidget(d->mSpinbox);
0056     d->mGoToLine = new QPushButton(QIcon::fromTheme(QStringLiteral("go-jump")), i18n("Go"));
0057     d->mGoToLine->setFlat(true);
0058     connect(d->mGoToLine, &QPushButton::clicked, this, &TextGoToLineWidget::slotGoToLine);
0059     d->mGoToLine->setObjectName(QStringLiteral("gotoline"));
0060     hbox->addWidget(d->mGoToLine);
0061     hbox->addStretch();
0062     d->mSpinbox->setFocus();
0063     d->mSpinbox->installEventFilter(this);
0064 }
0065 
0066 TextGoToLineWidget::~TextGoToLineWidget()
0067 {
0068     // mSpinbox can emit signals from its dtor, which are connected to this object
0069     // so we need to make sure these connections are removed before we destroy ourselves
0070     delete d->mSpinbox;
0071 }
0072 
0073 bool TextGoToLineWidget::eventFilter(QObject *obj, QEvent *event)
0074 {
0075     if (obj == d->mSpinbox) {
0076         if (event->type() == QEvent::KeyPress) {
0077             auto e = static_cast<QKeyEvent *>(event);
0078             if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
0079                 slotGoToLine();
0080                 return true;
0081             }
0082         }
0083     }
0084     return QObject::eventFilter(obj, event);
0085 }
0086 
0087 void TextGoToLineWidget::setMaximumLineCount(int max)
0088 {
0089     d->mSpinbox->setMaximum(max);
0090 }
0091 
0092 void TextGoToLineWidget::goToLine()
0093 {
0094     show();
0095     d->mSpinbox->setFocus();
0096     d->mSpinbox->selectAll();
0097 }
0098 
0099 void TextGoToLineWidget::slotGoToLine()
0100 {
0101     Q_EMIT moveToLine(d->mSpinbox->value());
0102 }
0103 
0104 void TextGoToLineWidget::showEvent(QShowEvent *e)
0105 {
0106     if (!e->spontaneous()) {
0107         d->mSpinbox->setFocus();
0108     }
0109     QWidget::showEvent(e);
0110 }
0111 
0112 void TextGoToLineWidget::slotBlockCountChanged(int numberBlockCount)
0113 {
0114     if (!isHidden()) {
0115         setMaximumLineCount(numberBlockCount);
0116     }
0117 }
0118 
0119 void TextGoToLineWidget::slotCloseBar()
0120 {
0121     hide();
0122     Q_EMIT hideGotoLine();
0123 }
0124 
0125 bool TextGoToLineWidget::event(QEvent *e)
0126 {
0127     // Close the bar when pressing Escape.
0128     // Not using a QShortcut for this because it could conflict with
0129     // window-global actions (e.g. Emil Sedgh binds Esc to "close tab").
0130     // With a shortcut override we can catch this before it gets to kactions.
0131     const bool shortCutOverride = (e->type() == QEvent::ShortcutOverride);
0132     if (shortCutOverride || e->type() == QEvent::KeyPress) {
0133         auto kev = static_cast<QKeyEvent *>(e);
0134         if (kev->key() == Qt::Key_Escape) {
0135             e->accept();
0136             slotCloseBar();
0137             return true;
0138         }
0139     }
0140     return QWidget::event(e);
0141 }
0142 
0143 #include "moc_textgotolinewidget.cpp"