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 "abstracteditor.hpp"
0010 
0011 // lib
0012 #include <bytearraytablelayout.hpp>
0013 #include <bytearraytablecursor.hpp>
0014 #include <abstractbytearrayview.hpp>
0015 // Okteta core
0016 #include <Okteta/AbstractByteArrayModel>
0017 #include <Okteta/TextByteArrayAnalyzer>
0018 // Qt
0019 #include <QKeyEvent>
0020 
0021 namespace Okteta {
0022 
0023 AbstractEditor::AbstractEditor(ByteArrayTableCursor* cursor, AbstractByteArrayView* view, AbstractController* parent)
0024     : AbstractController(parent)
0025     , mCursor(cursor)
0026     , mView(view)
0027 {
0028 }
0029 
0030 AbstractEditor::~AbstractEditor() = default;
0031 
0032 bool AbstractEditor::handleKeyPress(QKeyEvent* keyEvent)
0033 {
0034     const bool shiftPressed =   keyEvent->modifiers() & Qt::SHIFT;
0035     const bool controlPressed = keyEvent->modifiers() & Qt::CTRL;
0036     const bool altPressed =     keyEvent->modifiers() & Qt::ALT;
0037 
0038     bool keyUsed = true;
0039     // we only care for cursor keys and the like, won't hardcode any other keys
0040     // we also don't check whether the commands are allowed
0041     // as the commands are also available as API so the check has to be done
0042     // in each command anyway
0043     switch (keyEvent->key())
0044     {
0045     case Qt::Key_Delete:
0046         if (shiftPressed) {
0047             mView->cut();
0048         } else if (mView->hasSelectedData()) {
0049             mView->removeSelectedData();
0050         } else {
0051             doEditAction(controlPressed ? WordDelete : CharDelete);
0052         }
0053         break;
0054     case Qt::Key_Insert:
0055         if (shiftPressed) {
0056             mView->paste();
0057         } else if (controlPressed) {
0058             mView->copy();
0059         } else {
0060             mView->setOverwriteMode(!mView->isOverwriteMode());
0061         }
0062         break;
0063     case Qt::Key_Backspace:
0064         if (altPressed) {
0065             break;
0066         } else if (mView->hasSelectedData()) {
0067             mView->removeSelectedData();
0068             break;
0069         }
0070 
0071         doEditAction(controlPressed ? WordBackspace : CharBackspace);
0072         break;
0073     case Qt::Key_F16: // "Copy" key on Sun keyboards
0074         mView->copy();
0075         break;
0076     case Qt::Key_F18: // "Paste" key on Sun keyboards
0077         mView->paste();
0078         break;
0079     case Qt::Key_F20: // "Cut" key on Sun keyboards
0080         mView->cut();
0081         break;
0082     default:
0083         keyUsed = false;
0084     }
0085 
0086     return keyUsed ? true : AbstractController::handleKeyPress(keyEvent);
0087 }
0088 
0089 void AbstractEditor::doEditAction(EditAction action)
0090 {
0091     Okteta::AbstractByteArrayModel* byteArrayModel = mView->byteArrayModel();
0092     switch (action)
0093     {
0094     case CharDelete:
0095         if (!mView->isOverwriteMode()) {
0096             const Address index = mCursor->realIndex();
0097             if (index < mView->layout()->length()) {
0098                 byteArrayModel->remove(AddressRange::fromWidth(index, 1));
0099             }
0100         }
0101         break;
0102     case WordDelete: // kills data until the start of the next word
0103         if (!mView->isOverwriteMode()) {
0104             const Address index = mCursor->realIndex();
0105             if (index < mView->layout()->length()) {
0106                 const TextByteArrayAnalyzer textAnalyzer(byteArrayModel, mView->charCodec());
0107                 const Address end = textAnalyzer.indexOfBeforeNextWordStart(index);
0108                 byteArrayModel->remove(AddressRange(index, end));
0109             }
0110         }
0111         break;
0112     case CharBackspace:
0113         if (mView->isOverwriteMode()) {
0114             mView->pauseCursor();
0115             mCursor->gotoPreviousByte();
0116             mView->ensureCursorVisible();
0117             mView->unpauseCursor();
0118         } else {
0119             const Address deleteIndex = mCursor->realIndex() - 1;
0120             if (deleteIndex >= 0) {
0121                 byteArrayModel->remove(AddressRange::fromWidth(deleteIndex, 1));
0122             }
0123         }
0124         break;
0125     case WordBackspace:
0126     {
0127         const int leftIndex = mCursor->realIndex() - 1;
0128         if (leftIndex >= 0) {
0129             const TextByteArrayAnalyzer textAnalyzer(byteArrayModel, mView->charCodec());
0130             const Address wordStart = textAnalyzer.indexOfPreviousWordStart(leftIndex);
0131             if (!mView->isOverwriteMode()) {
0132                 byteArrayModel->remove(AddressRange(wordStart, leftIndex));
0133             }
0134         }
0135     }
0136     }
0137 }
0138 
0139 }