File indexing completed on 2024-04-28 05:52:36

0001 /*
0002     This file is part of the Okteta Gui library, made within the KDE community.
0003 
0004     SPDX-FileCopyrightText: 2004, 2008 Friedrich W. H. Kossebau <kossebau@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0007 */
0008 
0009 #include "keynavigator.hpp"
0010 
0011 // lib
0012 #include <bytearraytableranges.hpp>
0013 #include <bytearraytablecursor.hpp>
0014 #include <abstractbytearrayview.hpp>
0015 // Okteta core
0016 #include <Okteta/TextByteArrayAnalyzer>
0017 #include <Okteta/AbstractByteArrayModel>
0018 // KF
0019 #include <KLocalizedString>
0020 // Qt
0021 #include <QKeyEvent>
0022 #include <QMenu>
0023 #include <QAction>
0024 
0025 namespace Okteta {
0026 
0027 KeyNavigator::KeyNavigator(AbstractByteArrayView* view, AbstractController* parent)
0028     : AbstractController(parent)
0029     , mView(view)
0030 {
0031 }
0032 
0033 bool KeyNavigator::handleKeyPress(QKeyEvent* keyEvent)
0034 {
0035     bool keyUsed;
0036 
0037     if (keyEvent == QKeySequence::SelectAll) {
0038         selectAll();
0039         keyUsed = true;
0040     } else if (keyEvent->modifiers() & Qt::ALT) {
0041         // currently there is no input with the Alt modifier used, so ignore them all
0042         keyUsed = false;
0043     } else {
0044         keyUsed = true;
0045 
0046         const bool shiftPressed =  keyEvent->modifiers() & Qt::SHIFT;
0047         const bool controlPressed = keyEvent->modifiers() & Qt::CTRL;
0048 
0049         // we only care for cursor keys and the like, won't hardcode any other keys
0050         // we also don't check whether the commands are allowed
0051         // as the commands are also available as API so the check has to be done
0052         // in each command anyway
0053         switch (keyEvent->key())
0054         {
0055         case Qt::Key_Left:
0056             moveCursor(controlPressed ? MoveWordBackward : MoveBackward, shiftPressed);
0057             break;
0058         case Qt::Key_Right:
0059             moveCursor(controlPressed ? MoveWordForward : MoveForward, shiftPressed);
0060             break;
0061         case Qt::Key_Up:
0062             moveCursor(controlPressed ? MovePgUp : MoveUp, shiftPressed);
0063             break;
0064         case Qt::Key_Down:
0065             moveCursor(controlPressed ? MovePgDown : MoveDown, shiftPressed);
0066             break;
0067         case Qt::Key_Home:
0068             moveCursor(controlPressed ? MoveHome : MoveLineStart, shiftPressed);
0069             break;
0070         case Qt::Key_End:
0071             moveCursor(controlPressed ? MoveEnd : MoveLineEnd, shiftPressed);
0072             break;
0073         case Qt::Key_PageUp:
0074             moveCursor(MovePgUp, shiftPressed);
0075             break;
0076         case Qt::Key_PageDown:
0077             moveCursor(MovePgDown, shiftPressed);
0078             break;
0079         default:
0080             keyUsed = false;
0081         }
0082     }
0083 
0084     return keyUsed ? true : AbstractController::handleKeyPress(keyEvent);
0085 }
0086 
0087 void KeyNavigator::moveCursor(MoveAction action, bool select)
0088 {
0089     mView->pauseCursor();
0090     mView->finishByteEdit();
0091 
0092     ByteArrayTableCursor* tableCursor = mView->tableCursor();
0093     ByteArrayTableRanges* tableRanges = mView->tableRanges();
0094 
0095     if (select) {
0096         if (!tableRanges->selectionStarted()) {
0097             tableRanges->setSelectionStart(tableCursor->realIndex());
0098         }
0099     } else {
0100         tableRanges->removeSelection();
0101     }
0102 
0103     switch (action)
0104     {
0105     case MoveBackward:     tableCursor->gotoPreviousByte(); break;
0106     case MoveWordBackward: {
0107         const Okteta::TextByteArrayAnalyzer textAnalyzer(mView->byteArrayModel(), mView->charCodec());
0108         const int newIndex = textAnalyzer.indexOfPreviousWordStart(tableCursor->realIndex());
0109         tableCursor->gotoIndex(newIndex);
0110         break;
0111     }
0112     case MoveForward:      tableCursor->gotoNextByte();     break;
0113     case MoveWordForward:  {
0114         const Okteta::TextByteArrayAnalyzer textAnalyzer(mView->byteArrayModel(), mView->charCodec());
0115         const int newIndex = textAnalyzer.indexOfNextWordStart(tableCursor->realIndex());
0116         tableCursor->gotoCIndex(newIndex);
0117         break;
0118     }
0119     case MoveUp:           tableCursor->gotoUp();             break;
0120     case MovePgUp:         tableCursor->gotoPageUp();         break;
0121     case MoveDown:         tableCursor->gotoDown();           break;
0122     case MovePgDown:       tableCursor->gotoPageDown();       break;
0123     case MoveLineStart:    tableCursor->gotoLineStart();      break;
0124     case MoveHome:         tableCursor->gotoStart();          break;
0125     case MoveLineEnd:      tableCursor->gotoLineEnd();        break;
0126     case MoveEnd:          tableCursor->gotoEnd();            break;
0127     }
0128 
0129     if (select) {
0130         tableRanges->setSelectionEnd(tableCursor->realIndex());
0131     }
0132 
0133     mView->ensureCursorVisible();
0134 
0135     mView->updateChanged();
0136     mView->unpauseCursor();
0137     mView->emitSelectionSignals();
0138 }
0139 
0140 int KeyNavigator::addContextMenuActions(QMenu* menu)
0141 {
0142     QAction* selectAllAction = menu->addAction(QIcon::fromTheme(QStringLiteral("edit-select-all")),
0143                                                i18nc("@action:inmenu", "Select &All") + QLatin1Char('\t') + QKeySequence(QKeySequence::SelectAll).toString(QKeySequence::NativeText),
0144                                                mView, [this] { selectAll(); });
0145     selectAllAction->setEnabled(mView->byteArrayModel()->size() > 0);
0146 
0147     selectAllAction->setObjectName(QStringLiteral("select-all"));
0148 
0149     return 1;
0150 }
0151 
0152 void KeyNavigator::selectAll()
0153 {
0154     mView->selectAll(true);
0155 }
0156 
0157 }