File indexing completed on 2025-01-05 05:23:37
0001 /* 0002 This file is part of the Okteta Kasten module, made within the KDE community. 0003 0004 SPDX-FileCopyrightText: 2009, 2023 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 "searchtool.hpp" 0010 0011 // libconfigentries 0012 #include <casesensitivityconfigentry.hpp> 0013 // libbytearraysearch 0014 #include <bytearraysearchjob.hpp> 0015 #include <bytearraysearchutils.hpp> 0016 // controller 0017 #include "searchuserqueryable.hpp" 0018 // Okteta Kasten gui 0019 #include <Kasten/Okteta/ByteArrayView> 0020 // Okteta Kasten core 0021 #include <Kasten/Okteta/ByteArrayDocument> 0022 // Okteta core 0023 #include <Okteta/CharCodec> 0024 #include <Okteta/AbstractByteArrayModel> 0025 // KF 0026 #include <KConfigGroup> 0027 #include <KSharedConfig> 0028 #include <KLocalizedString> 0029 // Qt 0030 #include <QApplication> 0031 0032 0033 namespace Kasten { 0034 0035 SearchTool::SearchTool() 0036 { 0037 setObjectName(QStringLiteral("Search")); 0038 0039 const KConfigGroup configGroup(KSharedConfig::openConfig(), ConfigGroupId); 0040 mCaseSensitivity = configGroup.readEntry(CaseSensitivityConfigKey, DefaultCaseSensitivity); 0041 } 0042 0043 SearchTool::~SearchTool() = default; 0044 0045 bool SearchTool::isApplyable() const 0046 { 0047 return (mByteArrayView && mByteArrayModel); 0048 // const int newPosition = finalTargetOffset(); 0049 0050 // return ( mByteArrayView && mByteArrayModel 0051 // && (0 <= newPosition) && (newPosition <= mByteArrayModel->size()) ); 0052 } 0053 0054 QString SearchTool::title() const { return i18nc("@title", "Search"); } 0055 0056 bool SearchTool::hasSelectedData() const { return mByteArrayView->hasSelectedData(); } 0057 QString SearchTool::charCodingName() const { return mByteArrayView->charCodingName(); } 0058 0059 void SearchTool::setTargetModel(AbstractModel* model) 0060 { 0061 const bool oldIsApplyable = isApplyable(); 0062 0063 if (mByteArrayView) { 0064 mByteArrayView->disconnect(this); 0065 } 0066 if (mByteArrayModel) { 0067 mByteArrayModel->disconnect(this); 0068 } 0069 0070 mByteArrayView = model ? model->findBaseModel<ByteArrayView*>() : nullptr; 0071 0072 ByteArrayDocument* document = 0073 mByteArrayView ? qobject_cast<ByteArrayDocument*>(mByteArrayView->baseModel()) : nullptr; 0074 mByteArrayModel = document ? document->content() : nullptr; 0075 0076 if (mByteArrayView && mByteArrayModel) { 0077 connect(mByteArrayView, &ByteArrayView::charCodecChanged, 0078 this, &SearchTool::charCodecChanged); 0079 // TODO: update isApplyable on cursor movement and size changes 0080 } 0081 0082 const bool newIsApplyable = isApplyable(); 0083 if (oldIsApplyable != newIsApplyable) { 0084 Q_EMIT isApplyableChanged(newIsApplyable); 0085 } 0086 } 0087 0088 void SearchTool::setUserQueryAgent(If::SearchUserQueryable* userQueryAgent) 0089 { 0090 mUserQueryAgent = userQueryAgent; 0091 } 0092 0093 void SearchTool::setSearchData(const QByteArray& searchData) 0094 { 0095 // const bool oldIsApplyable = isApplyable(); 0096 0097 mSearchData = searchData; 0098 0099 // const bool newIsApplyable = isApplyable(); 0100 // if( oldIsApplyable != newIsApplyable ) 0101 // Q_EMIT isApplyableChanged( newIsApplyable ); 0102 } 0103 0104 void SearchTool::setCaseSensitivity(Qt::CaseSensitivity caseSensitivity) 0105 { 0106 if (mCaseSensitivity == caseSensitivity) { 0107 return; 0108 } 0109 0110 // const bool oldIsApplyable = isApplyable(); 0111 0112 mCaseSensitivity = caseSensitivity; 0113 0114 KConfigGroup configGroup(KSharedConfig::openConfig(), ConfigGroupId); 0115 configGroup.writeEntry(CaseSensitivityConfigKey, mCaseSensitivity); 0116 0117 // const bool newIsApplyable = isApplyable(); 0118 // if( oldIsApplyable != newIsApplyable ) 0119 // Q_EMIT isApplyableChanged( newIsApplyable ); 0120 } 0121 0122 void SearchTool::search(FindDirection direction, bool fromCursor, bool inSelection) 0123 { 0124 mPreviousFound = false; 0125 0126 if (!ByteArraySearchUtils::getSearchIndexes(&mSearchFirstIndex, &mSearchLastIndex, 0127 mByteArrayModel, 0128 mByteArrayView->selection(), 0129 mByteArrayView->cursorPosition(), 0130 mSearchData, 0131 direction, 0132 fromCursor, inSelection)) { 0133 // no search doable, so skip any search and finish now 0134 Q_EMIT dataNotFound(); 0135 return; 0136 } 0137 0138 doSearch(direction); 0139 } 0140 0141 void SearchTool::doSearch(FindDirection direction) 0142 { 0143 // TODO: should start at last 0144 Okteta::Address startIndex = (direction == FindForward) ? mSearchFirstIndex : mSearchLastIndex /*-mSearchData.size()*/; 0145 bool wrapEnabled = (direction == FindForward) ? (mSearchLastIndex < startIndex) : (startIndex < mSearchFirstIndex); 0146 0147 while (true) { 0148 const bool isWithin = !wrapEnabled || (direction == FindForward) ? (startIndex <= mByteArrayModel->size() - 1) : (startIndex >= 0); 0149 0150 if (isWithin) { 0151 QApplication::setOverrideCursor(Qt::WaitCursor); 0152 0153 Okteta::Address endIndex = wrapEnabled ? 0154 ((direction == FindForward) ? mByteArrayModel->size() - 1 : 0) : 0155 ((direction == FindForward) ? mSearchLastIndex : mSearchFirstIndex); 0156 0157 auto* searchJob = 0158 new ByteArraySearchJob(mByteArrayModel, mSearchData, startIndex, endIndex, mCaseSensitivity, mByteArrayView->charCodingName()); 0159 const Okteta::AddressRange matchRange = searchJob->exec(); 0160 0161 QApplication::restoreOverrideCursor(); 0162 0163 if (matchRange.isValid()) { 0164 mPreviousFound = true; 0165 mByteArrayView->setSelection(matchRange.start(), matchRange.end()); 0166 break; 0167 } 0168 } 0169 0170 if (wrapEnabled) { 0171 const bool wrapping = mUserQueryAgent ? mUserQueryAgent->queryContinue(direction) : true; 0172 0173 if (!wrapping) { 0174 break; 0175 } 0176 startIndex = (direction == FindForward) ? 0 : mByteArrayModel->size() - 1; 0177 wrapEnabled = false; 0178 } else { 0179 if (!mPreviousFound) { 0180 Q_EMIT dataNotFound(); 0181 } 0182 break; 0183 } 0184 } 0185 mByteArrayView->setFocus(); 0186 } 0187 0188 } 0189 0190 #include "moc_searchtool.cpp"