File indexing completed on 2024-05-26 05:56:36

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 "selectrangetool.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 SelectRangeTool::SelectRangeTool()
0024     : mIsEndRelative(false)
0025     , mIsEndBackwards(false)
0026 {
0027     setObjectName(QStringLiteral("SelectRange"));
0028 }
0029 
0030 SelectRangeTool::~SelectRangeTool() = default;
0031 
0032 int SelectRangeTool::currentSelectionStart() const
0033 {
0034     return mByteArrayView ?
0035            mByteArrayView->startOffset() + mByteArrayView->selection().start() :
0036            -1;
0037 }
0038 int SelectRangeTool::currentSelectionEnd() const
0039 {
0040     return mByteArrayView ?
0041            mByteArrayView->startOffset() + mByteArrayView->selection().end() :
0042            -1;
0043 }
0044 
0045 bool SelectRangeTool::isUsable() const
0046 {
0047     return (mByteArrayView && mByteArrayModel && (mByteArrayModel->size() > 0));
0048 }
0049 
0050 bool SelectRangeTool::isApplyable() const
0051 {
0052     const int start = finalTargetSelectionStart();
0053     const int end =   finalTargetSelectionEnd();
0054 
0055     return (mByteArrayView && mByteArrayModel
0056             && (start <= end)
0057             && (0 <= start) && (start < mByteArrayModel->size())
0058             && (0 <= end) && (end < mByteArrayModel->size()));
0059 }
0060 
0061 QString SelectRangeTool::title() const { return i18nc("@title:window of the tool to select a range", "Select"); }
0062 
0063 void SelectRangeTool::setTargetModel(AbstractModel* model)
0064 {
0065     const bool oldIsUsable = isUsable();
0066     const bool oldIsApplyable = isApplyable();
0067 
0068     if (mByteArrayView) {
0069         mByteArrayView->disconnect(this);
0070     }
0071     if (mByteArrayModel) {
0072         mByteArrayModel->disconnect(this);
0073     }
0074 
0075     mByteArrayView = model ? model->findBaseModel<ByteArrayView*>() : nullptr;
0076 
0077     ByteArrayDocument* document =
0078         mByteArrayView ? qobject_cast<ByteArrayDocument*>(mByteArrayView->baseModel()) : nullptr;
0079     mByteArrayModel = document ? document->content() : nullptr;
0080 
0081     if (mByteArrayView && mByteArrayModel) {
0082         connect(mByteArrayModel, &Okteta::AbstractByteArrayModel::contentsChanged,
0083                 this, &SelectRangeTool::onContentsChanged);
0084         // TODO: update isApplyable on cursor movement and size changes
0085     }
0086 
0087     const bool newIsUsable = isUsable();
0088     const bool newIsApplyable = isApplyable();
0089     if (oldIsUsable != newIsUsable) {
0090         Q_EMIT isUsableChanged(newIsUsable);
0091     }
0092     if (oldIsApplyable != newIsApplyable) {
0093         Q_EMIT isApplyableChanged(newIsApplyable);
0094     }
0095 }
0096 
0097 void SelectRangeTool::setTargetStart(Okteta::Address start)
0098 {
0099     const bool oldIsApplyable = isApplyable();
0100 
0101     mTargetStart = start;
0102 
0103     const bool newIsApplyable = isApplyable();
0104     if (oldIsApplyable != newIsApplyable) {
0105         Q_EMIT isApplyableChanged(newIsApplyable);
0106     }
0107 }
0108 
0109 void SelectRangeTool::setTargetEnd(Okteta::Address end)
0110 {
0111     const bool oldIsApplyable = isApplyable();
0112 
0113     mTargetEnd = end;
0114 
0115     const bool newIsApplyable = isApplyable();
0116     if (oldIsApplyable != newIsApplyable) {
0117         Q_EMIT isApplyableChanged(newIsApplyable);
0118     }
0119 }
0120 
0121 void SelectRangeTool::setIsEndRelative(bool isEndRelative)
0122 {
0123     const bool oldIsApplyable = isApplyable();
0124 
0125     mIsEndRelative = isEndRelative;
0126 
0127     const bool newIsApplyable = isApplyable();
0128     if (oldIsApplyable != newIsApplyable) {
0129         Q_EMIT isApplyableChanged(newIsApplyable);
0130     }
0131 }
0132 
0133 void SelectRangeTool::setIsEndBackwards(bool isEndBackwards)
0134 {
0135     const bool oldIsApplyable = isApplyable();
0136 
0137     mIsEndBackwards = isEndBackwards;
0138 
0139     const bool newIsApplyable = isApplyable();
0140     if (oldIsApplyable != newIsApplyable) {
0141         Q_EMIT isApplyableChanged(newIsApplyable);
0142     }
0143 }
0144 
0145 void SelectRangeTool::select()
0146 {
0147     const int start = finalTargetSelectionStart();
0148     const int end =   finalTargetSelectionEnd();
0149 
0150     mByteArrayView->setSelection(start, end);
0151     mByteArrayView->setFocus();
0152 }
0153 
0154 int SelectRangeTool::finalTargetSelectionStart() const
0155 {
0156     const int start =
0157         (!mByteArrayView) ?
0158             -1 :
0159         mIsEndRelative && mIsEndBackwards ?
0160             mTargetStart - mTargetEnd + 1 :
0161         /* else */
0162             mTargetStart;
0163 
0164     return start;
0165 }
0166 
0167 int SelectRangeTool::finalTargetSelectionEnd() const
0168 {
0169     const int end =
0170         (!mByteArrayView) ?
0171             -1 :
0172         (!mIsEndRelative) ?
0173             mTargetEnd :
0174         mIsEndBackwards ?
0175             mTargetStart :
0176         /* else */
0177             mTargetStart + mTargetEnd - 1;
0178 
0179     return end;
0180 }
0181 
0182 void SelectRangeTool::onContentsChanged()
0183 {
0184     // TODO: find status before content changed, e.g. by caching
0185     Q_EMIT isUsableChanged(isUsable());
0186 }
0187 
0188 }
0189 
0190 #include "moc_selectrangetool.cpp"