Find: Remember the find flags per completer entry

Replace the QStringListModel used by the completer
by a special model storing a struct of the text and find flags.
On activating the completer, the flags are applied.

Change-Id: I05031641647692196ce60dcad36fc8970131f516
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
Friedemann Kleint
2017-12-20 16:40:45 +01:00
parent b3dd52b30f
commit 91530a3e0c
6 changed files with 151 additions and 18 deletions

View File

@@ -48,6 +48,7 @@
#include <QMenu> #include <QMenu>
#include <QStringListModel> #include <QStringListModel>
#include <QVector>
#include <QAction> #include <QAction>
#include <QtPlugin> #include <QtPlugin>
@@ -70,6 +71,103 @@ namespace {
namespace Core { namespace Core {
struct CompletionEntry
{
QString text;
FindFlags findFlags;
};
QDebug operator<<(QDebug d, const CompletionEntry &e)
{
QDebugStateSaver saver(d);
d.noquote();
d.nospace();
d << "CompletionEntry(\"" << e.text << "\", flags=" << hex
<< showbase << int(e.findFlags) << dec << noshowbase << ')';
return d;
}
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;
void writeSettings(QSettings *settings) const;
void readSettings(QSettings *settings);
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();
}
static inline QString completionSettingsArrayPrefix() { return QStringLiteral("FindCompletions"); }
static inline QString completionSettingsTextKey() { return QStringLiteral("Text"); }
static inline QString completionSettingsFlagsKey() { return QStringLiteral("Flags"); }
void CompletionModel::writeSettings(QSettings *settings) const
{
const int size = m_entries.size();
settings->beginWriteArray(completionSettingsArrayPrefix(), size);
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();
}
void CompletionModel::readSettings(QSettings *settings)
{
beginResetModel();
const int size = settings->beginReadArray(completionSettingsArrayPrefix());
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();
}
class FindPrivate : public QObject class FindPrivate : public QObject
{ {
Q_DECLARE_TR_FUNCTIONS(Core::Find) Q_DECLARE_TR_FUNCTIONS(Core::Find)
@@ -88,9 +186,8 @@ public:
Internal::FindToolWindow *m_findDialog = 0; Internal::FindToolWindow *m_findDialog = 0;
SearchResultWindow *m_searchResultWindow = 0; SearchResultWindow *m_searchResultWindow = 0;
FindFlags m_findFlags; FindFlags m_findFlags;
QStringListModel m_findCompletionModel; CompletionModel m_findCompletionModel;
QStringListModel m_replaceCompletionModel; QStringListModel m_replaceCompletionModel;
QStringList m_findCompletions;
QStringList m_replaceCompletions; QStringList m_replaceCompletions;
QAction *m_openFindDialog = 0; QAction *m_openFindDialog = 0;
}; };
@@ -288,7 +385,7 @@ void FindPrivate::writeSettings()
settings->setValue(QLatin1String("WholeWords"), bool(m_findFlags & FindWholeWords)); settings->setValue(QLatin1String("WholeWords"), bool(m_findFlags & FindWholeWords));
settings->setValue(QLatin1String("RegularExpression"), bool(m_findFlags & FindRegularExpression)); settings->setValue(QLatin1String("RegularExpression"), bool(m_findFlags & FindRegularExpression));
settings->setValue(QLatin1String("PreserveCase"), bool(m_findFlags & FindPreserveCase)); settings->setValue(QLatin1String("PreserveCase"), bool(m_findFlags & FindPreserveCase));
settings->setValue(QLatin1String("FindStrings"), m_findCompletions); m_findCompletionModel.writeSettings(settings);
settings->setValue(QLatin1String("ReplaceStrings"), m_replaceCompletions); settings->setValue(QLatin1String("ReplaceStrings"), m_replaceCompletions);
settings->endGroup(); settings->endGroup();
m_findToolBar->writeSettings(); m_findToolBar->writeSettings();
@@ -308,9 +405,8 @@ void FindPrivate::readSettings()
Find::setRegularExpression(settings->value(QLatin1String("RegularExpression"), false).toBool()); Find::setRegularExpression(settings->value(QLatin1String("RegularExpression"), false).toBool());
Find::setPreserveCase(settings->value(QLatin1String("PreserveCase"), false).toBool()); Find::setPreserveCase(settings->value(QLatin1String("PreserveCase"), false).toBool());
} }
m_findCompletions = settings->value(QLatin1String("FindStrings")).toStringList(); m_findCompletionModel.readSettings(settings);
m_replaceCompletions = settings->value(QLatin1String("ReplaceStrings")).toStringList(); m_replaceCompletions = settings->value(QLatin1String("ReplaceStrings")).toStringList();
m_findCompletionModel.setStringList(m_findCompletions);
m_replaceCompletionModel.setStringList(m_replaceCompletions); m_replaceCompletionModel.setStringList(m_replaceCompletions);
settings->endGroup(); settings->endGroup();
m_findToolBar->readSettings(); m_findToolBar->readSettings();
@@ -318,9 +414,9 @@ void FindPrivate::readSettings()
emit m_instance->findFlagsChanged(); // would have been done in the setXXX methods above emit m_instance->findFlagsChanged(); // would have been done in the setXXX methods above
} }
void Find::updateFindCompletion(const QString &text) void Find::updateFindCompletion(const QString &text, FindFlags flags)
{ {
d->updateCompletion(text, d->m_findCompletions, &d->m_findCompletionModel); d->m_findCompletionModel.updateCompletion(text, flags);
} }
void Find::updateReplaceCompletion(const QString &text) void Find::updateReplaceCompletion(const QString &text)
@@ -353,7 +449,7 @@ void Find::openFindToolBar(FindDirection direction)
} }
} }
QStringListModel *Find::findCompletionModel() QAbstractListModel *Find::findCompletionModel()
{ {
return &(d->m_findCompletionModel); return &(d->m_findCompletionModel);
} }

View File

@@ -30,6 +30,7 @@
#include <QObject> #include <QObject>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QAbstractListModel;
class QStringListModel; class QStringListModel;
QT_END_NAMESPACE QT_END_NAMESPACE
@@ -49,11 +50,13 @@ public:
FindBackwardDirection FindBackwardDirection
}; };
enum { CompletionModelFindFlagsRole = Qt::UserRole + 1 };
static FindFlags findFlags(); static FindFlags findFlags();
static bool hasFindFlag(FindFlag flag); static bool hasFindFlag(FindFlag flag);
static void updateFindCompletion(const QString &text); static void updateFindCompletion(const QString &text, FindFlags flags = 0);
static void updateReplaceCompletion(const QString &text); static void updateReplaceCompletion(const QString &text);
static QStringListModel *findCompletionModel(); static QAbstractListModel *findCompletionModel();
static QStringListModel *replaceCompletionModel(); static QStringListModel *replaceCompletionModel();
static void setUseFakeVim(bool on); static void setUseFakeVim(bool on);
static void openFindToolBar(FindDirection direction); static void openFindToolBar(FindDirection direction);

View File

@@ -116,6 +116,9 @@ FindToolBar::FindToolBar(CurrentDocumentFind *currentDocumentFind)
this, &FindToolBar::invokeFindEnter, Qt::QueuedConnection); this, &FindToolBar::invokeFindEnter, Qt::QueuedConnection);
connect(m_ui.replaceEdit, &Utils::FancyLineEdit::returnPressed, connect(m_ui.replaceEdit, &Utils::FancyLineEdit::returnPressed,
this, &FindToolBar::invokeReplaceEnter, Qt::QueuedConnection); this, &FindToolBar::invokeReplaceEnter, Qt::QueuedConnection);
connect(m_findCompleter,
static_cast<void (QCompleter::*)(const QModelIndex &)>(&QCompleter::activated),
this, &FindToolBar::findCompleterActivated);
QAction *shiftEnterAction = new QAction(m_ui.findEdit); QAction *shiftEnterAction = new QAction(m_ui.findEdit);
shiftEnterAction->setShortcut(QKeySequence(tr("Shift+Enter"))); shiftEnterAction->setShortcut(QKeySequence(tr("Shift+Enter")));
@@ -313,6 +316,17 @@ FindToolBar::~FindToolBar()
{ {
} }
void FindToolBar::findCompleterActivated(const QModelIndex &index)
{
const int findFlagsI = index.data(Find::CompletionModelFindFlagsRole).toInt();
const FindFlags findFlags(findFlagsI);
setFindFlag(FindCaseSensitively, findFlags.testFlag(FindCaseSensitively));
setFindFlag(FindBackward, findFlags.testFlag(FindBackward));
setFindFlag(FindWholeWords, findFlags.testFlag(FindWholeWords));
setFindFlag(FindRegularExpression, findFlags.testFlag(FindRegularExpression));
setFindFlag(FindPreserveCase, findFlags.testFlag(FindPreserveCase));
}
void FindToolBar::installEventFilters() void FindToolBar::installEventFilters()
{ {
if (!m_eventFiltersInstalled) { if (!m_eventFiltersInstalled) {
@@ -527,9 +541,10 @@ void FindToolBar::invokeFindStep()
m_findStepTimer.stop(); m_findStepTimer.stop();
m_findIncrementalTimer.stop(); m_findIncrementalTimer.stop();
if (m_currentDocumentFind->isEnabled()) { if (m_currentDocumentFind->isEnabled()) {
Find::updateFindCompletion(getFindText()); const FindFlags ef = effectiveFindFlags();
Find::updateFindCompletion(getFindText(), ef);
IFindSupport::Result result = IFindSupport::Result result =
m_currentDocumentFind->findStep(getFindText(), effectiveFindFlags()); m_currentDocumentFind->findStep(getFindText(), ef);
indicateSearchState(result); indicateSearchState(result);
if (result == IFindSupport::NotYetFound) if (result == IFindSupport::NotYetFound)
m_findStepTimer.start(50); m_findStepTimer.start(50);
@@ -556,9 +571,10 @@ void FindToolBar::invokeReplace()
{ {
setFindFlag(FindBackward, false); setFindFlag(FindBackward, false);
if (m_currentDocumentFind->isEnabled() && m_currentDocumentFind->supportsReplace()) { if (m_currentDocumentFind->isEnabled() && m_currentDocumentFind->supportsReplace()) {
Find::updateFindCompletion(getFindText()); const FindFlags ef = effectiveFindFlags();
Find::updateFindCompletion(getFindText(), ef);
Find::updateReplaceCompletion(getReplaceText()); Find::updateReplaceCompletion(getReplaceText());
m_currentDocumentFind->replace(getFindText(), getReplaceText(), effectiveFindFlags()); m_currentDocumentFind->replace(getFindText(), getReplaceText(), ef);
} }
} }
@@ -595,18 +611,20 @@ void FindToolBar::invokeGlobalReplacePrevious()
void FindToolBar::invokeReplaceStep() void FindToolBar::invokeReplaceStep()
{ {
if (m_currentDocumentFind->isEnabled() && m_currentDocumentFind->supportsReplace()) { if (m_currentDocumentFind->isEnabled() && m_currentDocumentFind->supportsReplace()) {
Find::updateFindCompletion(getFindText()); const FindFlags ef = effectiveFindFlags();
Find::updateFindCompletion(getFindText(), ef);
Find::updateReplaceCompletion(getReplaceText()); Find::updateReplaceCompletion(getReplaceText());
m_currentDocumentFind->replaceStep(getFindText(), getReplaceText(), effectiveFindFlags()); m_currentDocumentFind->replaceStep(getFindText(), getReplaceText(), ef);
} }
} }
void FindToolBar::invokeReplaceAll() void FindToolBar::invokeReplaceAll()
{ {
Find::updateFindCompletion(getFindText()); const FindFlags ef = effectiveFindFlags();
Find::updateFindCompletion(getFindText(), ef);
Find::updateReplaceCompletion(getReplaceText()); Find::updateReplaceCompletion(getReplaceText());
if (m_currentDocumentFind->isEnabled() && m_currentDocumentFind->supportsReplace()) if (m_currentDocumentFind->isEnabled() && m_currentDocumentFind->supportsReplace())
m_currentDocumentFind->replaceAll(getFindText(), getReplaceText(), effectiveFindFlags()); m_currentDocumentFind->replaceAll(getFindText(), getReplaceText(), ef);
} }
void FindToolBar::invokeGlobalReplaceAll() void FindToolBar::invokeGlobalReplaceAll()

View File

@@ -125,6 +125,7 @@ private:
void updateToolBar(); void updateToolBar();
void findFlagsChanged(); void findFlagsChanged();
void findEditButtonClicked(); void findEditButtonClicked();
void findCompleterActivated(const QModelIndex &);
void setCaseSensitive(bool sensitive); void setCaseSensitive(bool sensitive);
void setWholeWord(bool wholeOnly); void setWholeWord(bool wholeOnly);

View File

@@ -83,6 +83,9 @@ FindToolWindow::FindToolWindow(QWidget *parent)
m_findCompleter->setModel(Find::findCompletionModel()); m_findCompleter->setModel(Find::findCompletionModel());
m_ui.searchTerm->setSpecialCompleter(m_findCompleter); m_ui.searchTerm->setSpecialCompleter(m_findCompleter);
m_ui.searchTerm->installEventFilter(this); m_ui.searchTerm->installEventFilter(this);
connect(m_findCompleter,
static_cast<void (QCompleter::*)(const QModelIndex &)>(&QCompleter::activated),
this, &FindToolWindow::findCompleterActivated);
m_ui.searchTerm->setValidationFunction(validateRegExp); m_ui.searchTerm->setValidationFunction(validateRegExp);
connect(Find::instance(), &Find::findFlagsChanged, connect(Find::instance(), &Find::findFlagsChanged,
@@ -318,3 +321,14 @@ void FindToolWindow::readSettings()
} }
settings->endGroup(); settings->endGroup();
} }
void FindToolWindow::findCompleterActivated(const QModelIndex &index)
{
const int findFlagsI = index.data(Find::CompletionModelFindFlagsRole).toInt();
const FindFlags findFlags(findFlagsI);
Find::setCaseSensitive(findFlags.testFlag(FindCaseSensitively));
Find::setBackward(findFlags.testFlag(FindBackward));
Find::setWholeWord(findFlags.testFlag(FindWholeWords));
Find::setRegularExpression(findFlags.testFlag(FindRegularExpression));
Find::setPreserveCase(findFlags.testFlag(FindPreserveCase));
}

View File

@@ -65,6 +65,7 @@ private:
void updateButtonStates(); void updateButtonStates();
void updateFindFlags(); void updateFindFlags();
void updateFindFilterName(IFindFilter *filter); void updateFindFilterName(IFindFilter *filter);
void findCompleterActivated(const QModelIndex &index);
void acceptAndGetParameters(QString *term, IFindFilter **filter); void acceptAndGetParameters(QString *term, IFindFilter **filter);