File indexing completed on 2025-01-05 05:23:29

0001 /*
0002     This file is part of the Okteta Kasten module, made within the KDE community.
0003 
0004     SPDX-FileCopyrightText: 2009 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 "gotooffsettool.hpp"
0010 
0011 // Okteta Kasten gui
0012 #include <Kasten/Okteta/ByteArrayView>
0013 // Okteta Kasten core
0014 #include <Kasten/Okteta/ByteArrayDocument>
0015 // Okteta core
0016 #include <Okteta/AbstractByteArrayModel>
0017 #include <Okteta/ArrayChangeMetricsList>
0018 // KF
0019 #include <KLocalizedString>
0020 
0021 namespace Kasten {
0022 
0023 GotoOffsetTool::GotoOffsetTool()
0024 {
0025     setObjectName(QStringLiteral("GotoOffset"));
0026 }
0027 
0028 GotoOffsetTool::~GotoOffsetTool() = default;
0029 
0030 int GotoOffsetTool::currentOffset() const
0031 {
0032     return mByteArrayView ?
0033            mByteArrayView->startOffset() + mByteArrayView->cursorPosition() :
0034            -1;
0035 }
0036 
0037 bool GotoOffsetTool::isUsable() const
0038 {
0039     return (mByteArrayView && mByteArrayModel && (mByteArrayModel->size() > 0));
0040 }
0041 
0042 bool GotoOffsetTool::isApplyable() const
0043 {
0044     const int newPosition = finalTargetOffset();
0045 
0046     return (mByteArrayView && mByteArrayModel
0047             && (0 <= newPosition) && (newPosition <= mByteArrayModel->size()));
0048 }
0049 
0050 QString GotoOffsetTool::title() const { return i18nc("@title:window of the tool to set a new offset for the cursor", "Goto"); }
0051 
0052 void GotoOffsetTool::setTargetModel(AbstractModel* model)
0053 {
0054     const bool oldIsUsable = isUsable();
0055     const bool oldIsApplyable = isApplyable();
0056 
0057     if (mByteArrayView) {
0058         mByteArrayView->disconnect(this);
0059     }
0060     if (mByteArrayModel) {
0061         mByteArrayModel->disconnect(this);
0062     }
0063 
0064     mByteArrayView = model ? model->findBaseModel<ByteArrayView*>() : nullptr;
0065 
0066     ByteArrayDocument* document =
0067         mByteArrayView ? qobject_cast<ByteArrayDocument*>(mByteArrayView->baseModel()) : nullptr;
0068     mByteArrayModel = document ? document->content() : nullptr;
0069 
0070     if (mByteArrayView && mByteArrayModel) {
0071         connect(mByteArrayModel, &Okteta::AbstractByteArrayModel::contentsChanged,
0072                 this, &GotoOffsetTool::onContentsChanged);
0073         // TODO: update isApplyable on cursor movement and size changes
0074     }
0075 
0076     const bool newIsUsable = isUsable();
0077     const bool newIsApplyable = isApplyable();
0078     if (oldIsUsable != newIsUsable) {
0079         Q_EMIT isUsableChanged(newIsUsable);
0080     }
0081     if (oldIsApplyable != newIsApplyable) {
0082         Q_EMIT isApplyableChanged(newIsApplyable);
0083     }
0084 }
0085 
0086 void GotoOffsetTool::setTargetOffset(Okteta::Address targetOffset)
0087 {
0088     const bool oldIsApplyable = isApplyable();
0089 
0090     mTargetOffset = targetOffset;
0091 
0092     const bool newIsApplyable = isApplyable();
0093     if (oldIsApplyable != newIsApplyable) {
0094         Q_EMIT isApplyableChanged(newIsApplyable);
0095     }
0096 }
0097 
0098 void GotoOffsetTool::setIsRelative(bool isRelative)
0099 {
0100     const bool oldIsApplyable = isApplyable();
0101 
0102     mIsRelative = isRelative;
0103 
0104     const bool newIsApplyable = isApplyable();
0105     if (oldIsApplyable != newIsApplyable) {
0106         Q_EMIT isApplyableChanged(newIsApplyable);
0107     }
0108 }
0109 
0110 void GotoOffsetTool::setIsSelectionToExtent(bool isSelectionToExtent)
0111 {
0112     const bool oldIsApplyable = isApplyable();
0113 
0114     mIsSelectionToExtent = isSelectionToExtent;
0115 
0116     const bool newIsApplyable = isApplyable();
0117     if (oldIsApplyable != newIsApplyable) {
0118         Q_EMIT isApplyableChanged(newIsApplyable);
0119     }
0120 }
0121 
0122 void GotoOffsetTool::setIsBackwards(bool isBackwards)
0123 {
0124     const bool oldIsApplyable = isApplyable();
0125 
0126     mIsBackwards = isBackwards;
0127 
0128     const bool newIsApplyable = isApplyable();
0129     if (oldIsApplyable != newIsApplyable) {
0130         Q_EMIT isApplyableChanged(newIsApplyable);
0131     }
0132 }
0133 
0134 void GotoOffsetTool::gotoOffset()
0135 {
0136     const int newPosition = finalTargetOffset();
0137 
0138     if (mIsSelectionToExtent) {
0139         mByteArrayView->setSelectionCursorPosition(newPosition);
0140     } else {
0141         mByteArrayView->setCursorPosition(newPosition);
0142     }
0143     mByteArrayView->setFocus();
0144 }
0145 
0146 int GotoOffsetTool::finalTargetOffset() const
0147 {
0148     const int newPosition =
0149         (!mByteArrayView) ? -1 :
0150         mIsRelative ?
0151             (mIsBackwards ? mByteArrayView->cursorPosition() - mTargetOffset :
0152                             mByteArrayView->cursorPosition() + mTargetOffset) :
0153             (mIsBackwards ? mByteArrayModel->size() - mTargetOffset :
0154                             mTargetOffset);
0155 
0156     return newPosition;
0157 }
0158 
0159 void GotoOffsetTool::onContentsChanged()
0160 {
0161     // TODO: find status before content changed, e.g. by caching
0162     Q_EMIT isUsableChanged(isUsable());
0163 }
0164 
0165 }
0166 
0167 #include "moc_gotooffsettool.cpp"