2022-08-19 15:59:36 +02:00
|
|
|
// Copyright (C) 2016 The Qt Company Ltd.
|
2022-12-21 10:12:09 +01:00
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
2014-01-13 16:17:34 +01:00
|
|
|
|
|
|
|
|
#include "findplugin.h"
|
|
|
|
|
|
2023-01-16 17:20:07 +01:00
|
|
|
#include "../actionmanager/actioncontainer.h"
|
|
|
|
|
#include "../actionmanager/actionmanager.h"
|
|
|
|
|
#include "../actionmanager/command.h"
|
|
|
|
|
#include "../coreconstants.h"
|
|
|
|
|
#include "../coreplugintr.h"
|
|
|
|
|
#include "../icontext.h"
|
|
|
|
|
#include "../icore.h"
|
2024-05-28 14:13:11 +02:00
|
|
|
#include "../session.h"
|
|
|
|
|
#include "currentdocumentfind.h"
|
|
|
|
|
#include "findtoolbar.h"
|
|
|
|
|
#include "findtoolwindow.h"
|
|
|
|
|
#include "ifindfilter.h"
|
|
|
|
|
#include "searchresultwindow.h"
|
|
|
|
|
#include "textfindconstants.h"
|
2014-01-13 16:17:34 +01:00
|
|
|
|
|
|
|
|
#include <extensionsystem/pluginmanager.h>
|
|
|
|
|
|
2016-02-03 10:24:28 +02:00
|
|
|
#include <utils/algorithm.h>
|
2014-01-13 16:17:34 +01:00
|
|
|
#include <utils/qtcassert.h>
|
|
|
|
|
|
2022-09-29 12:12:29 +02:00
|
|
|
#include <QApplication>
|
2014-01-13 16:17:34 +01:00
|
|
|
#include <QMenu>
|
|
|
|
|
#include <QStringListModel>
|
2017-12-20 16:40:45 +01:00
|
|
|
#include <QVector>
|
2014-01-13 16:17:34 +01:00
|
|
|
#include <QAction>
|
|
|
|
|
|
|
|
|
|
/*!
|
2020-02-13 16:14:56 +01:00
|
|
|
\namespace Core::Internal::ItemDataRoles
|
2014-01-13 16:17:34 +01:00
|
|
|
\internal
|
|
|
|
|
*/
|
2020-02-13 16:14:56 +01:00
|
|
|
|
2014-01-13 16:17:34 +01:00
|
|
|
/*!
|
2020-02-13 16:14:56 +01:00
|
|
|
\class Core::Find
|
|
|
|
|
\inmodule QtCreator
|
2014-01-13 16:17:34 +01:00
|
|
|
\internal
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
Q_DECLARE_METATYPE(Core::IFindFilter*)
|
|
|
|
|
|
2019-11-12 13:28:42 +01:00
|
|
|
using namespace Qt;
|
2020-06-26 13:59:38 +02:00
|
|
|
using namespace Utils;
|
2019-11-12 13:28:42 +01:00
|
|
|
|
2014-01-13 16:17:34 +01:00
|
|
|
namespace {
|
|
|
|
|
const int MAX_COMPLETIONS = 50;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace Core {
|
|
|
|
|
|
2017-12-20 16:40:45 +01:00
|
|
|
struct CompletionEntry
|
|
|
|
|
{
|
2021-12-06 05:11:04 +01:00
|
|
|
friend QDebug operator<<(QDebug d, const CompletionEntry &e)
|
|
|
|
|
{
|
|
|
|
|
QDebugStateSaver saver(d);
|
|
|
|
|
d.noquote();
|
|
|
|
|
d.nospace();
|
|
|
|
|
d << "CompletionEntry(\"" << e.text << "\", flags="
|
|
|
|
|
<< "0x" << QString::number(e.findFlags, 16) << ')';
|
|
|
|
|
return d;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-20 16:40:45 +01:00
|
|
|
QString text;
|
|
|
|
|
FindFlags findFlags;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class CompletionModel : public QAbstractListModel
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
explicit CompletionModel(QObject *p = nullptr) : QAbstractListModel(p) {}
|
|
|
|
|
|
|
|
|
|
int rowCount(const QModelIndex & = QModelIndex()) const override { return m_entries.size(); }
|
|
|
|
|
|
|
|
|
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
|
|
|
|
|
2024-05-28 14:13:11 +02:00
|
|
|
void restore(const Store &s);
|
|
|
|
|
Store save() const;
|
|
|
|
|
|
|
|
|
|
// TODO deprecated since QtC 14.0
|
2023-09-22 16:15:27 +02:00
|
|
|
void writeSettings(QtcSettings *settings) const;
|
|
|
|
|
void readSettings(QtcSettings *settings);
|
2017-12-20 16:40:45 +01:00
|
|
|
|
|
|
|
|
void updateCompletion(const QString &text, FindFlags f);
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
QVector<CompletionEntry> m_entries;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
QVariant CompletionModel::data(const QModelIndex &index, int role) const
|
|
|
|
|
{
|
|
|
|
|
if (index.isValid()) {
|
|
|
|
|
const CompletionEntry &entry = m_entries.at(index.row());
|
|
|
|
|
switch (role) {
|
|
|
|
|
case Qt::DisplayRole:
|
|
|
|
|
case Qt::EditRole:
|
|
|
|
|
return QVariant(entry.text);
|
|
|
|
|
case Find::CompletionModelFindFlagsRole:
|
|
|
|
|
return QVariant(int(entry.findFlags));
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return QVariant();
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-22 16:15:27 +02:00
|
|
|
static Utils::Key completionSettingsArrayPrefix() { return "FindCompletions"; }
|
|
|
|
|
static Utils::Key completionSettingsTextKey() { return "Text"; }
|
|
|
|
|
static Utils::Key completionSettingsFlagsKey() { return "Flags"; }
|
2017-12-20 16:40:45 +01:00
|
|
|
|
2024-05-28 14:13:11 +02:00
|
|
|
void CompletionModel::restore(const Store &s)
|
|
|
|
|
{
|
|
|
|
|
beginResetModel();
|
|
|
|
|
const QStringList texts = s.value(completionSettingsTextKey()).toStringList();
|
|
|
|
|
const QList<FindFlags> flags
|
|
|
|
|
= transform(s.value(completionSettingsFlagsKey()).toList(), [](const QVariant &v) {
|
|
|
|
|
return FindFlags(v.toInt());
|
|
|
|
|
});
|
|
|
|
|
const int size = texts.size();
|
|
|
|
|
m_entries.clear();
|
|
|
|
|
m_entries.reserve(size);
|
|
|
|
|
for (int i = 0; i < size; ++i) {
|
|
|
|
|
CompletionEntry entry;
|
|
|
|
|
entry.text = texts.at(i);
|
|
|
|
|
entry.findFlags = i < flags.size() ? flags.at(i) : FindFlags();
|
|
|
|
|
if (!entry.text.isEmpty())
|
|
|
|
|
m_entries.append(entry);
|
|
|
|
|
}
|
|
|
|
|
endResetModel();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Store CompletionModel::save() const
|
|
|
|
|
{
|
|
|
|
|
if (m_entries.isEmpty())
|
|
|
|
|
return {};
|
|
|
|
|
const QStringList texts = transform(m_entries, [](const CompletionEntry &e) { return e.text; });
|
|
|
|
|
const QVariantList flags = transform(m_entries, [](const CompletionEntry &e) {
|
|
|
|
|
return QVariant::fromValue(int(e.findFlags));
|
|
|
|
|
});
|
|
|
|
|
Store s;
|
|
|
|
|
s.insert(completionSettingsTextKey(), texts);
|
|
|
|
|
s.insert(completionSettingsFlagsKey(), flags);
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-22 16:15:27 +02:00
|
|
|
void CompletionModel::writeSettings(QtcSettings *settings) const
|
2017-12-20 16:40:45 +01:00
|
|
|
{
|
2020-12-10 11:24:27 +01:00
|
|
|
if (m_entries.isEmpty()) {
|
|
|
|
|
settings->remove(completionSettingsArrayPrefix());
|
|
|
|
|
} else {
|
|
|
|
|
const int size = m_entries.size();
|
2023-09-28 07:11:56 +02:00
|
|
|
settings->beginWriteArray(stringFromKey(completionSettingsArrayPrefix()), size);
|
2020-12-10 11:24:27 +01:00
|
|
|
for (int i = 0; i < size; ++i) {
|
|
|
|
|
settings->setArrayIndex(i);
|
|
|
|
|
settings->setValue(completionSettingsTextKey(), m_entries.at(i).text);
|
|
|
|
|
settings->setValue(completionSettingsFlagsKey(), int(m_entries.at(i).findFlags));
|
|
|
|
|
}
|
|
|
|
|
settings->endArray();
|
2017-12-20 16:40:45 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-22 16:15:27 +02:00
|
|
|
void CompletionModel::readSettings(QtcSettings *settings)
|
2017-12-20 16:40:45 +01:00
|
|
|
{
|
|
|
|
|
beginResetModel();
|
2023-09-28 07:11:56 +02:00
|
|
|
const int size = settings->beginReadArray(stringFromKey(completionSettingsArrayPrefix()));
|
2017-12-20 16:40:45 +01:00
|
|
|
m_entries.clear();
|
|
|
|
|
m_entries.reserve(size);
|
|
|
|
|
for (int i = 0; i < size; ++i) {
|
|
|
|
|
settings->setArrayIndex(i);
|
|
|
|
|
CompletionEntry entry;
|
|
|
|
|
entry.text = settings->value(completionSettingsTextKey()).toString();
|
|
|
|
|
entry.findFlags = FindFlags(settings->value(completionSettingsFlagsKey(), 0).toInt());
|
|
|
|
|
if (!entry.text.isEmpty())
|
|
|
|
|
m_entries.append(entry);
|
|
|
|
|
}
|
|
|
|
|
settings->endArray();
|
|
|
|
|
endResetModel();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CompletionModel::updateCompletion(const QString &text, FindFlags f)
|
|
|
|
|
{
|
|
|
|
|
if (text.isEmpty())
|
|
|
|
|
return;
|
|
|
|
|
beginResetModel();
|
|
|
|
|
Utils::erase(m_entries, Utils::equal(&CompletionEntry::text, text));
|
|
|
|
|
m_entries.prepend({text, f});
|
|
|
|
|
while (m_entries.size() > MAX_COMPLETIONS)
|
|
|
|
|
m_entries.removeLast();
|
|
|
|
|
endResetModel();
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-11 19:12:07 +01:00
|
|
|
class FindPrivate : public QObject
|
|
|
|
|
{
|
|
|
|
|
public:
|
2016-11-18 10:43:05 +01:00
|
|
|
bool isAnyFilterEnabled() const;
|
2016-03-11 19:12:07 +01:00
|
|
|
void writeSettings();
|
2023-05-22 13:56:37 +02:00
|
|
|
void setFindFlag(FindFlag flag, bool enabled);
|
2020-12-10 00:59:50 +01:00
|
|
|
static void updateCompletion(const QString &text, QStringList &completions,
|
|
|
|
|
QStringListModel *model);
|
2016-03-11 19:12:07 +01:00
|
|
|
void setupMenu();
|
|
|
|
|
void setupFilterMenuItems();
|
|
|
|
|
void readSettings();
|
2014-01-13 16:17:34 +01:00
|
|
|
|
2018-07-21 21:11:46 +02:00
|
|
|
Internal::CurrentDocumentFind *m_currentDocumentFind = nullptr;
|
|
|
|
|
Internal::FindToolBar *m_findToolBar = nullptr;
|
|
|
|
|
Internal::FindToolWindow *m_findDialog = nullptr;
|
|
|
|
|
SearchResultWindow *m_searchResultWindow = nullptr;
|
2014-01-13 16:17:34 +01:00
|
|
|
FindFlags m_findFlags;
|
2017-12-20 16:40:45 +01:00
|
|
|
CompletionModel m_findCompletionModel;
|
2016-03-11 19:12:07 +01:00
|
|
|
QStringListModel m_replaceCompletionModel;
|
2014-01-13 16:17:34 +01:00
|
|
|
QStringList m_replaceCompletions;
|
2018-07-21 21:11:46 +02:00
|
|
|
QAction *m_openFindDialog = nullptr;
|
2014-01-13 16:17:34 +01:00
|
|
|
};
|
|
|
|
|
|
2018-07-21 21:11:46 +02:00
|
|
|
Find *m_instance = nullptr;
|
|
|
|
|
FindPrivate *d = nullptr;
|
2014-01-13 16:17:34 +01:00
|
|
|
|
2016-03-11 19:12:07 +01:00
|
|
|
void Find::destroy()
|
2014-01-13 16:17:34 +01:00
|
|
|
{
|
2016-03-11 19:12:07 +01:00
|
|
|
delete m_instance;
|
2018-07-21 21:11:46 +02:00
|
|
|
m_instance = nullptr;
|
2016-12-02 09:50:14 +01:00
|
|
|
if (d) {
|
|
|
|
|
delete d->m_currentDocumentFind;
|
|
|
|
|
delete d->m_findToolBar;
|
|
|
|
|
delete d->m_findDialog;
|
|
|
|
|
ExtensionSystem::PluginManager::removeObject(d->m_searchResultWindow);
|
|
|
|
|
delete d->m_searchResultWindow;
|
|
|
|
|
delete d;
|
|
|
|
|
}
|
2014-01-13 16:17:34 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-11 19:12:07 +01:00
|
|
|
Find *Find::instance()
|
2014-01-13 16:17:34 +01:00
|
|
|
{
|
2016-03-11 19:12:07 +01:00
|
|
|
return m_instance;
|
2014-01-13 16:17:34 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-11 19:12:07 +01:00
|
|
|
void Find::initialize()
|
2014-01-13 16:17:34 +01:00
|
|
|
{
|
2016-03-11 19:12:07 +01:00
|
|
|
QTC_ASSERT(!m_instance, return);
|
|
|
|
|
m_instance = new Find;
|
|
|
|
|
|
|
|
|
|
d = new FindPrivate;
|
|
|
|
|
d->setupMenu();
|
2014-01-13 16:17:34 +01:00
|
|
|
|
|
|
|
|
d->m_currentDocumentFind = new Internal::CurrentDocumentFind;
|
|
|
|
|
|
2016-03-11 19:12:07 +01:00
|
|
|
d->m_findToolBar = new Internal::FindToolBar(d->m_currentDocumentFind);
|
2024-07-03 14:55:42 +02:00
|
|
|
IContext::attach(d->m_findToolBar, Context(Constants::C_FINDTOOLBAR));
|
2014-03-03 11:55:50 +01:00
|
|
|
|
2016-03-11 19:12:07 +01:00
|
|
|
d->m_findDialog = new Internal::FindToolWindow;
|
2014-01-13 16:17:34 +01:00
|
|
|
d->m_searchResultWindow = new SearchResultWindow(d->m_findDialog);
|
|
|
|
|
ExtensionSystem::PluginManager::addObject(d->m_searchResultWindow);
|
2024-05-28 14:13:11 +02:00
|
|
|
|
2016-03-11 19:12:07 +01:00
|
|
|
QObject::connect(ICore::instance(), &ICore::saveSettingsRequested, d, &FindPrivate::writeSettings);
|
2024-05-28 14:13:11 +02:00
|
|
|
QObject::connect(
|
|
|
|
|
SessionManager::instance(),
|
|
|
|
|
&SessionManager::aboutToSaveSession,
|
|
|
|
|
d,
|
|
|
|
|
&FindPrivate::writeSettings);
|
|
|
|
|
QObject::connect(
|
|
|
|
|
SessionManager::instance(), &SessionManager::sessionLoaded, d, &FindPrivate::readSettings);
|
2014-01-13 16:17:34 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-11 19:12:07 +01:00
|
|
|
void Find::extensionsInitialized()
|
2014-01-13 16:17:34 +01:00
|
|
|
{
|
2016-03-11 19:12:07 +01:00
|
|
|
d->setupFilterMenuItems();
|
2014-01-13 16:17:34 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-11 19:12:07 +01:00
|
|
|
void Find::aboutToShutdown()
|
2014-01-13 16:17:34 +01:00
|
|
|
{
|
|
|
|
|
d->m_findToolBar->setVisible(false);
|
2018-07-21 21:11:46 +02:00
|
|
|
d->m_findToolBar->setParent(nullptr);
|
2014-01-13 16:17:34 +01:00
|
|
|
d->m_currentDocumentFind->removeConnections();
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-18 10:43:05 +01:00
|
|
|
bool FindPrivate::isAnyFilterEnabled() const
|
2014-01-13 16:17:34 +01:00
|
|
|
{
|
2016-11-18 10:43:05 +01:00
|
|
|
return Utils::anyOf(m_findDialog->findFilters(), &IFindFilter::isEnabled);
|
2014-01-13 16:17:34 +01:00
|
|
|
}
|
|
|
|
|
|
2022-09-02 15:31:21 +02:00
|
|
|
void Find::openFindDialog(IFindFilter *filter, const QString &findString)
|
2014-01-13 16:17:34 +01:00
|
|
|
{
|
2014-11-04 14:58:48 +01:00
|
|
|
d->m_currentDocumentFind->acceptCandidate();
|
2022-09-02 15:31:21 +02:00
|
|
|
const QString currentFindString = [findString] {
|
|
|
|
|
if (!findString.isEmpty())
|
|
|
|
|
return findString;
|
|
|
|
|
if (d->m_findToolBar->isVisible()
|
|
|
|
|
&& QApplication::focusWidget() == d->m_findToolBar->focusWidget()
|
|
|
|
|
&& !d->m_findToolBar->getFindText().isEmpty()) {
|
|
|
|
|
return d->m_findToolBar->getFindText();
|
|
|
|
|
}
|
|
|
|
|
if (d->m_currentDocumentFind->isEnabled())
|
|
|
|
|
return d->m_currentDocumentFind->currentFindString();
|
|
|
|
|
return QString();
|
|
|
|
|
}();
|
2014-01-13 16:17:34 +01:00
|
|
|
if (!currentFindString.isEmpty())
|
|
|
|
|
d->m_findDialog->setFindText(currentFindString);
|
|
|
|
|
d->m_findDialog->setCurrentFilter(filter);
|
|
|
|
|
SearchResultWindow::instance()->openNewSearchPanel();
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-11 19:12:07 +01:00
|
|
|
void FindPrivate::setupMenu()
|
2014-01-13 16:17:34 +01:00
|
|
|
{
|
2014-11-16 10:52:41 +02:00
|
|
|
ActionContainer *medit = ActionManager::actionContainer(Constants::M_EDIT);
|
|
|
|
|
ActionContainer *mfind = ActionManager::createMenu(Constants::M_FIND);
|
|
|
|
|
medit->addMenu(mfind, Constants::G_EDIT_FIND);
|
2023-01-16 17:20:07 +01:00
|
|
|
mfind->menu()->setTitle(Tr::tr("&Find/Replace"));
|
2014-01-13 16:17:34 +01:00
|
|
|
mfind->appendGroup(Constants::G_FIND_CURRENTDOCUMENT);
|
|
|
|
|
mfind->appendGroup(Constants::G_FIND_FILTERS);
|
|
|
|
|
mfind->appendGroup(Constants::G_FIND_FLAGS);
|
|
|
|
|
mfind->appendGroup(Constants::G_FIND_ACTIONS);
|
2015-02-26 13:58:00 +01:00
|
|
|
mfind->addSeparator(Constants::G_FIND_FLAGS);
|
|
|
|
|
mfind->addSeparator(Constants::G_FIND_ACTIONS);
|
2014-01-13 16:17:34 +01:00
|
|
|
|
2014-11-16 10:52:41 +02:00
|
|
|
ActionContainer *mfindadvanced = ActionManager::createMenu(Constants::M_FIND_ADVANCED);
|
2023-01-16 17:20:07 +01:00
|
|
|
mfindadvanced->menu()->setTitle(Tr::tr("Advanced Find"));
|
2014-01-13 16:17:34 +01:00
|
|
|
mfind->addMenu(mfindadvanced, Constants::G_FIND_FILTERS);
|
2023-11-13 09:57:26 +01:00
|
|
|
|
|
|
|
|
ActionBuilder openFindDialog(this, Constants::ADVANCED_FIND);
|
|
|
|
|
openFindDialog.setText(Tr::tr("Open Advanced Find..."));
|
|
|
|
|
openFindDialog.setIconText(Tr::tr("Advanced..."));
|
|
|
|
|
openFindDialog.bindContextAction(&m_openFindDialog);
|
|
|
|
|
openFindDialog.setDefaultKeySequence(Tr::tr("Ctrl+Shift+F"));
|
2023-12-13 09:02:02 +01:00
|
|
|
openFindDialog.addToContainer(Constants::M_FIND_ADVANCED);
|
2023-12-13 12:29:46 +01:00
|
|
|
openFindDialog.addOnTriggered(this, [] { Find::openFindDialog(nullptr); });
|
2016-11-18 10:43:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static QString filterActionName(const IFindFilter *filter)
|
|
|
|
|
{
|
|
|
|
|
return QLatin1String(" ") + filter->displayName();
|
2014-01-13 16:17:34 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-11 19:12:07 +01:00
|
|
|
void FindPrivate::setupFilterMenuItems()
|
2014-01-13 16:17:34 +01:00
|
|
|
{
|
|
|
|
|
bool haveEnabledFilters = false;
|
2014-11-16 10:52:41 +02:00
|
|
|
const Id base("FindFilter.");
|
2022-10-21 14:05:12 +02:00
|
|
|
const QList<IFindFilter *> sortedFilters = Utils::sorted(IFindFilter::allFindFilters(),
|
|
|
|
|
&IFindFilter::displayName);
|
|
|
|
|
for (IFindFilter *filter : sortedFilters) {
|
2023-11-13 09:57:26 +01:00
|
|
|
ActionBuilder findScope(this, base.withSuffix(filter->id()));
|
|
|
|
|
findScope.setText(filterActionName(filter));
|
2014-01-13 16:17:34 +01:00
|
|
|
bool isEnabled = filter->isEnabled();
|
|
|
|
|
if (isEnabled)
|
|
|
|
|
haveEnabledFilters = true;
|
2023-11-13 09:57:26 +01:00
|
|
|
findScope.setEnabled(isEnabled);
|
|
|
|
|
findScope.setDefaultKeySequence(filter->defaultShortcut());
|
|
|
|
|
findScope.setCommandAttribute(Command::CA_UpdateText);
|
2023-12-13 09:02:02 +01:00
|
|
|
findScope.addToContainer(Constants::M_FIND_ADVANCED);
|
2023-12-13 12:29:46 +01:00
|
|
|
findScope.addOnTriggered(this, [filter] { Find::openFindDialog(filter); });
|
2023-11-13 09:57:26 +01:00
|
|
|
|
|
|
|
|
QAction *findScopeAction = findScope.contextAction();
|
|
|
|
|
connect(filter, &IFindFilter::enabledChanged, this, [filter, findScopeAction] {
|
|
|
|
|
findScopeAction->setEnabled(filter->isEnabled());
|
2016-11-18 10:43:05 +01:00
|
|
|
d->m_openFindDialog->setEnabled(d->isAnyFilterEnabled());
|
|
|
|
|
});
|
2023-11-13 09:57:26 +01:00
|
|
|
connect(filter, &IFindFilter::displayNameChanged, this, [filter, findScopeAction] {
|
|
|
|
|
findScopeAction->setText(filterActionName(filter));
|
|
|
|
|
});
|
2014-01-13 16:17:34 +01:00
|
|
|
}
|
2016-02-03 10:24:28 +02:00
|
|
|
d->m_findDialog->setFindFilters(sortedFilters);
|
2014-01-13 16:17:34 +01:00
|
|
|
d->m_openFindDialog->setEnabled(haveEnabledFilters);
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-11 19:12:07 +01:00
|
|
|
FindFlags Find::findFlags()
|
2014-01-13 16:17:34 +01:00
|
|
|
{
|
|
|
|
|
return d->m_findFlags;
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-11 19:12:07 +01:00
|
|
|
void Find::setCaseSensitive(bool sensitive)
|
2014-01-13 16:17:34 +01:00
|
|
|
{
|
2016-03-11 19:12:07 +01:00
|
|
|
d->setFindFlag(FindCaseSensitively, sensitive);
|
2014-01-13 16:17:34 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-11 19:12:07 +01:00
|
|
|
void Find::setWholeWord(bool wholeOnly)
|
2014-01-13 16:17:34 +01:00
|
|
|
{
|
2016-03-11 19:12:07 +01:00
|
|
|
d->setFindFlag(FindWholeWords, wholeOnly);
|
2014-01-13 16:17:34 +01:00
|
|
|
}
|
|
|
|
|
|
2024-07-12 10:50:29 +02:00
|
|
|
void Find::setIgnoreBinaryFiles(bool ignoreBinaryFiles)
|
|
|
|
|
{
|
|
|
|
|
d->setFindFlag(DontFindBinaryFiles, ignoreBinaryFiles);
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-11 19:12:07 +01:00
|
|
|
void Find::setBackward(bool backward)
|
2014-01-13 16:17:34 +01:00
|
|
|
{
|
2016-03-11 19:12:07 +01:00
|
|
|
d->setFindFlag(FindBackward, backward);
|
2014-01-13 16:17:34 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-11 19:12:07 +01:00
|
|
|
void Find::setRegularExpression(bool regExp)
|
2014-01-13 16:17:34 +01:00
|
|
|
{
|
2016-03-11 19:12:07 +01:00
|
|
|
d->setFindFlag(FindRegularExpression, regExp);
|
2014-01-13 16:17:34 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-11 19:12:07 +01:00
|
|
|
void Find::setPreserveCase(bool preserveCase)
|
2014-01-13 16:17:34 +01:00
|
|
|
{
|
2016-03-11 19:12:07 +01:00
|
|
|
d->setFindFlag(FindPreserveCase, preserveCase);
|
2014-01-13 16:17:34 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-11 19:12:07 +01:00
|
|
|
void FindPrivate::setFindFlag(FindFlag flag, bool enabled)
|
2014-01-13 16:17:34 +01:00
|
|
|
{
|
2016-03-11 19:12:07 +01:00
|
|
|
bool hasFlag = m_findFlags & flag;
|
2014-01-13 16:17:34 +01:00
|
|
|
if ((hasFlag && enabled) || (!hasFlag && !enabled))
|
|
|
|
|
return;
|
|
|
|
|
if (enabled)
|
2016-03-11 19:12:07 +01:00
|
|
|
m_findFlags |= flag;
|
2014-01-13 16:17:34 +01:00
|
|
|
else
|
2016-03-11 19:12:07 +01:00
|
|
|
m_findFlags &= ~flag;
|
2014-01-13 16:17:34 +01:00
|
|
|
if (flag != FindBackward)
|
2016-03-11 19:12:07 +01:00
|
|
|
emit m_instance->findFlagsChanged();
|
2014-01-13 16:17:34 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-11 19:12:07 +01:00
|
|
|
bool Find::hasFindFlag(FindFlag flag)
|
2014-01-13 16:17:34 +01:00
|
|
|
{
|
|
|
|
|
return d->m_findFlags & flag;
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-11 19:12:07 +01:00
|
|
|
void FindPrivate::writeSettings()
|
2014-01-13 16:17:34 +01:00
|
|
|
{
|
2024-05-28 14:13:11 +02:00
|
|
|
// TODO for backwards compatibility
|
|
|
|
|
// deprecated since QtC 14.0
|
2020-12-10 11:24:27 +01:00
|
|
|
QtcSettings *settings = ICore::settings();
|
2023-09-05 15:25:26 +02:00
|
|
|
settings->beginGroup("Find");
|
2020-12-10 11:24:27 +01:00
|
|
|
settings->setValueWithDefault("Backward", bool(m_findFlags & FindBackward), false);
|
|
|
|
|
settings->setValueWithDefault("CaseSensitively", bool(m_findFlags & FindCaseSensitively), false);
|
|
|
|
|
settings->setValueWithDefault("WholeWords", bool(m_findFlags & FindWholeWords), false);
|
2024-07-12 10:50:29 +02:00
|
|
|
settings
|
|
|
|
|
->setValueWithDefault("IgnoreBinaryFiles", bool(m_findFlags & DontFindBinaryFiles), false);
|
2020-12-10 11:24:27 +01:00
|
|
|
settings->setValueWithDefault("RegularExpression",
|
|
|
|
|
bool(m_findFlags & FindRegularExpression),
|
|
|
|
|
false);
|
|
|
|
|
settings->setValueWithDefault("PreserveCase", bool(m_findFlags & FindPreserveCase), false);
|
2017-12-20 16:40:45 +01:00
|
|
|
m_findCompletionModel.writeSettings(settings);
|
2020-12-10 11:24:27 +01:00
|
|
|
settings->setValueWithDefault("ReplaceStrings", m_replaceCompletions);
|
2014-01-13 16:17:34 +01:00
|
|
|
settings->endGroup();
|
2016-03-11 19:12:07 +01:00
|
|
|
m_findToolBar->writeSettings();
|
|
|
|
|
m_findDialog->writeSettings();
|
|
|
|
|
m_searchResultWindow->writeSettings();
|
2024-05-28 14:13:11 +02:00
|
|
|
|
|
|
|
|
// save in session
|
|
|
|
|
Store s;
|
|
|
|
|
if (m_findFlags & FindBackward)
|
|
|
|
|
s.insert("Backward", true);
|
|
|
|
|
if (m_findFlags & FindCaseSensitively)
|
|
|
|
|
s.insert("CaseSensitively", true);
|
2024-07-12 10:50:29 +02:00
|
|
|
if (m_findFlags & DontFindBinaryFiles)
|
|
|
|
|
s.insert("IgnoreBinaryFiles", true);
|
2024-05-28 14:13:11 +02:00
|
|
|
if (m_findFlags & FindWholeWords)
|
|
|
|
|
s.insert("WholeWords", true);
|
|
|
|
|
if (m_findFlags & FindRegularExpression)
|
|
|
|
|
s.insert("RegularExpression", true);
|
|
|
|
|
if (m_findFlags & FindPreserveCase)
|
|
|
|
|
s.insert("PreserveCase", true);
|
|
|
|
|
const Store completion = m_findCompletionModel.save();
|
|
|
|
|
if (!completion.isEmpty())
|
|
|
|
|
s.insert("FindCompletions", variantFromStore(completion));
|
|
|
|
|
if (!m_replaceCompletions.isEmpty())
|
|
|
|
|
s.insert("ReplaceStrings", m_replaceCompletions);
|
|
|
|
|
const Store toolbar = m_findToolBar->save();
|
|
|
|
|
if (!toolbar.isEmpty())
|
|
|
|
|
s.insert("ToolBar", variantFromStore(toolbar));
|
|
|
|
|
const Store advanced = m_findDialog->save();
|
|
|
|
|
if (!advanced.isEmpty())
|
|
|
|
|
s.insert("AdvancedSearch", variantFromStore(advanced));
|
|
|
|
|
SessionManager::setValue("Find", variantFromStore(s));
|
2014-01-13 16:17:34 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-11 19:12:07 +01:00
|
|
|
void FindPrivate::readSettings()
|
2014-01-13 16:17:34 +01:00
|
|
|
{
|
2024-05-28 14:13:11 +02:00
|
|
|
const Store s = storeFromVariant(SessionManager::value("Find"));
|
|
|
|
|
if (s.isEmpty() && SessionManager::isDefaultVirgin()) {
|
|
|
|
|
// TODO compatibility path when opening Qt Creator
|
|
|
|
|
// TODO deprecated since QtC 14.0
|
|
|
|
|
QtcSettings *settings = ICore::settings();
|
|
|
|
|
settings->beginGroup("Find");
|
|
|
|
|
{
|
|
|
|
|
QSignalBlocker blocker(m_instance);
|
|
|
|
|
Find::setBackward(settings->value("Backward", false).toBool());
|
|
|
|
|
Find::setCaseSensitive(settings->value("CaseSensitively", false).toBool());
|
|
|
|
|
Find::setWholeWord(settings->value("WholeWords", false).toBool());
|
|
|
|
|
Find::setRegularExpression(settings->value("RegularExpression", false).toBool());
|
|
|
|
|
Find::setPreserveCase(settings->value("PreserveCase", false).toBool());
|
2024-07-12 10:50:29 +02:00
|
|
|
Find::setIgnoreBinaryFiles(settings->value("IgnoreBinaryFiles", false).toBool());
|
2024-05-28 14:13:11 +02:00
|
|
|
}
|
|
|
|
|
m_findCompletionModel.readSettings(settings);
|
|
|
|
|
m_replaceCompletions = settings->value("ReplaceStrings").toStringList();
|
|
|
|
|
m_replaceCompletionModel.setStringList(m_replaceCompletions);
|
|
|
|
|
settings->endGroup();
|
|
|
|
|
m_findToolBar->readSettings();
|
|
|
|
|
m_findDialog->readSettings();
|
|
|
|
|
} else if (!s.empty()) {
|
|
|
|
|
{
|
|
|
|
|
QSignalBlocker blocker(m_instance);
|
|
|
|
|
Find::setBackward(s.value("Backward", false).toBool());
|
|
|
|
|
Find::setCaseSensitive(s.value("CaseSensitively", false).toBool());
|
|
|
|
|
Find::setWholeWord(s.value("WholeWords", false).toBool());
|
|
|
|
|
Find::setRegularExpression(s.value("RegularExpression", false).toBool());
|
|
|
|
|
Find::setPreserveCase(s.value("PreserveCase", false).toBool());
|
2024-07-12 10:50:29 +02:00
|
|
|
Find::setIgnoreBinaryFiles(s.value("IgnoreBinaryFiles", false).toBool());
|
2024-05-28 14:13:11 +02:00
|
|
|
}
|
|
|
|
|
m_findCompletionModel.restore(storeFromVariant(s.value("FindCompletions")));
|
|
|
|
|
m_replaceCompletions = s.value("ReplaceStrings").toStringList();
|
|
|
|
|
m_replaceCompletionModel.setStringList(m_replaceCompletions);
|
|
|
|
|
m_findToolBar->restore(storeFromVariant(s.value("ToolBar")));
|
|
|
|
|
m_findDialog->restore(storeFromVariant(s.value("AdvancedSearch")));
|
2017-09-30 07:12:57 +02:00
|
|
|
}
|
2016-03-11 19:12:07 +01:00
|
|
|
emit m_instance->findFlagsChanged(); // would have been done in the setXXX methods above
|
2014-01-13 16:17:34 +01:00
|
|
|
}
|
|
|
|
|
|
2017-12-20 16:40:45 +01:00
|
|
|
void Find::updateFindCompletion(const QString &text, FindFlags flags)
|
2014-01-13 16:17:34 +01:00
|
|
|
{
|
2017-12-20 16:40:45 +01:00
|
|
|
d->m_findCompletionModel.updateCompletion(text, flags);
|
2014-01-13 16:17:34 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-11 19:12:07 +01:00
|
|
|
void Find::updateReplaceCompletion(const QString &text)
|
2014-01-13 16:17:34 +01:00
|
|
|
{
|
2020-12-10 00:59:50 +01:00
|
|
|
FindPrivate::updateCompletion(text, d->m_replaceCompletions, &d->m_replaceCompletionModel);
|
2014-01-13 16:17:34 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-11 19:12:07 +01:00
|
|
|
void FindPrivate::updateCompletion(const QString &text, QStringList &completions, QStringListModel *model)
|
2014-01-13 16:17:34 +01:00
|
|
|
{
|
|
|
|
|
if (text.isEmpty())
|
|
|
|
|
return;
|
|
|
|
|
completions.removeAll(text);
|
|
|
|
|
completions.prepend(text);
|
|
|
|
|
while (completions.size() > MAX_COMPLETIONS)
|
|
|
|
|
completions.removeLast();
|
|
|
|
|
model->setStringList(completions);
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-11 19:12:07 +01:00
|
|
|
void Find::setUseFakeVim(bool on)
|
2014-01-13 16:17:34 +01:00
|
|
|
{
|
|
|
|
|
if (d->m_findToolBar)
|
|
|
|
|
d->m_findToolBar->setUseFakeVim(on);
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-11 19:12:07 +01:00
|
|
|
void Find::openFindToolBar(FindDirection direction)
|
2014-01-13 16:17:34 +01:00
|
|
|
{
|
|
|
|
|
if (d->m_findToolBar) {
|
|
|
|
|
d->m_findToolBar->setBackward(direction == FindBackwardDirection);
|
|
|
|
|
d->m_findToolBar->openFindToolBar();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-20 16:40:45 +01:00
|
|
|
QAbstractListModel *Find::findCompletionModel()
|
2014-01-13 16:17:34 +01:00
|
|
|
{
|
2016-03-11 19:12:07 +01:00
|
|
|
return &(d->m_findCompletionModel);
|
2014-01-13 16:17:34 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-11 19:12:07 +01:00
|
|
|
QStringListModel *Find::replaceCompletionModel()
|
2014-01-13 16:17:34 +01:00
|
|
|
{
|
2016-03-11 19:12:07 +01:00
|
|
|
return &(d->m_replaceCompletionModel);
|
2014-01-13 16:17:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace Core
|