File indexing completed on 2024-05-05 03:58:35

0001 /*
0002     SPDX-FileCopyrightText: 2013-2016 Simon St James <kdedevel@etotheipiplusone.com>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "interactivesedreplacemode.h"
0008 
0009 #include <QKeyEvent>
0010 #include <QLabel>
0011 
0012 using namespace KateVi;
0013 
0014 InteractiveSedReplaceMode::InteractiveSedReplaceMode(EmulatedCommandBar *emulatedCommandBar,
0015                                                      MatchHighlighter *matchHighlighter,
0016                                                      InputModeManager *viInputModeManager,
0017                                                      KTextEditor::ViewPrivate *view)
0018     : ActiveMode(emulatedCommandBar, matchHighlighter, viInputModeManager, view)
0019     , m_isActive(false)
0020 {
0021     m_interactiveSedReplaceLabel = new QLabel();
0022     m_interactiveSedReplaceLabel->setObjectName(QStringLiteral("interactivesedreplace"));
0023 }
0024 
0025 void InteractiveSedReplaceMode::activate(std::shared_ptr<SedReplace::InteractiveSedReplacer> interactiveSedReplace)
0026 {
0027     Q_ASSERT_X(interactiveSedReplace->currentMatch().isValid(),
0028                "startInteractiveSearchAndReplace",
0029                "KateCommands shouldn't initiate an interactive sed replace with no initial match");
0030 
0031     m_isActive = true;
0032     m_interactiveSedReplacer = interactiveSedReplace;
0033 
0034     hideAllWidgetsExcept(m_interactiveSedReplaceLabel);
0035     m_interactiveSedReplaceLabel->show();
0036     updateInteractiveSedReplaceLabelText();
0037 
0038     updateMatchHighlight(interactiveSedReplace->currentMatch());
0039     moveCursorTo(interactiveSedReplace->currentMatch().start());
0040 }
0041 
0042 bool InteractiveSedReplaceMode::handleKeyPress(const QKeyEvent *keyEvent)
0043 {
0044     // TODO - it would be better to use e.g. keyEvent->key() == Qt::Key_Y instead of keyEvent->text() == "y",
0045     // but this would require some slightly dicey changes to the "feed key press" code in order to make it work
0046     // with mappings and macros.
0047     if (keyEvent->text() == QLatin1String("y") || keyEvent->text() == QLatin1String("n")) {
0048         const KTextEditor::Cursor cursorPosIfFinalMatch = m_interactiveSedReplacer->currentMatch().start();
0049         if (keyEvent->text() == QLatin1String("y")) {
0050             m_interactiveSedReplacer->replaceCurrentMatch();
0051         } else {
0052             m_interactiveSedReplacer->skipCurrentMatch();
0053         }
0054         updateMatchHighlight(m_interactiveSedReplacer->currentMatch());
0055         updateInteractiveSedReplaceLabelText();
0056         moveCursorTo(m_interactiveSedReplacer->currentMatch().start());
0057 
0058         if (!m_interactiveSedReplacer->currentMatch().isValid()) {
0059             moveCursorTo(cursorPosIfFinalMatch);
0060             finishInteractiveSedReplace();
0061         }
0062         return true;
0063     } else if (keyEvent->text() == QLatin1String("l")) {
0064         m_interactiveSedReplacer->replaceCurrentMatch();
0065         finishInteractiveSedReplace();
0066         return true;
0067     } else if (keyEvent->text() == QLatin1String("q")) {
0068         finishInteractiveSedReplace();
0069         return true;
0070     } else if (keyEvent->text() == QLatin1String("a")) {
0071         m_interactiveSedReplacer->replaceAllRemaining();
0072         finishInteractiveSedReplace();
0073         return true;
0074     }
0075     return false;
0076 }
0077 
0078 void InteractiveSedReplaceMode::deactivate(bool wasAborted)
0079 {
0080     Q_UNUSED(wasAborted);
0081     m_isActive = false;
0082     m_interactiveSedReplaceLabel->hide();
0083 }
0084 
0085 QWidget *InteractiveSedReplaceMode::label()
0086 {
0087     return m_interactiveSedReplaceLabel;
0088 }
0089 
0090 void InteractiveSedReplaceMode::updateInteractiveSedReplaceLabelText()
0091 {
0092     m_interactiveSedReplaceLabel->setText(m_interactiveSedReplacer->currentMatchReplacementConfirmationMessage() + QLatin1String(" (y/n/a/q/l)"));
0093 }
0094 
0095 void InteractiveSedReplaceMode::finishInteractiveSedReplace()
0096 {
0097     deactivate(false);
0098     closeWithStatusMessage(m_interactiveSedReplacer->finalStatusReportMessage());
0099     m_interactiveSedReplacer.reset();
0100 }