From 2a4803249bc80ddfd53dc5e74704c400ed73bb23 Mon Sep 17 00:00:00 2001 From: con <qtc-committer@nokia.com> Date: Tue, 29 Jun 2010 13:16:54 +0200 Subject: [PATCH] Make search panel searchable. Task-number: QTCREATORBUG-1438 --- src/plugins/find/searchresulttreeitemroles.h | 3 +- src/plugins/find/searchresulttreemodel.cpp | 62 +++++++- src/plugins/find/searchresulttreemodel.h | 9 +- src/plugins/find/searchresultwindow.cpp | 153 ++++++++++++++++--- src/plugins/find/searchresultwindow.h | 4 +- 5 files changed, 202 insertions(+), 29 deletions(-) diff --git a/src/plugins/find/searchresulttreeitemroles.h b/src/plugins/find/searchresulttreeitemroles.h index 94b409529d5..eae775192b3 100644 --- a/src/plugins/find/searchresulttreeitemroles.h +++ b/src/plugins/find/searchresulttreeitemroles.h @@ -44,7 +44,8 @@ enum Roles ResultLineNumberRole, SearchTermStartRole, SearchTermLengthRole, - RowOfItem // The ?-th child of its parent is this this item + RowOfItem, // The ?-th child of its parent is this this item + TextRole // for files == FileNameRole, for results == ResultLineRole }; } // namespace Internal diff --git a/src/plugins/find/searchresulttreemodel.cpp b/src/plugins/find/searchresulttreemodel.cpp index 621664e3049..080edd5c585 100644 --- a/src/plugins/find/searchresulttreemodel.cpp +++ b/src/plugins/find/searchresulttreemodel.cpp @@ -36,6 +36,8 @@ #include <QtGui/QFontMetrics> #include <QtGui/QColor> #include <QtGui/QPalette> +#include <QtGui/QTextDocument> +#include <QtGui/QTextCursor> #include <QtCore/QDir> #include <QtCore/QDebug> @@ -195,6 +197,7 @@ QVariant SearchResultTreeModel::data(const SearchResultTextRow *row, int role) c case Qt::FontRole: result = m_textEditorFont; break; + case ItemDataRoles::TextRole: case ItemDataRoles::ResultLineRole: case Qt::DisplayRole: result = row->rowText(); @@ -252,6 +255,7 @@ QVariant SearchResultTreeModel::data(const SearchResultFile *file, int role) con + QLatin1Char(')'); return QVariant(result); } + case ItemDataRoles::TextRole: case ItemDataRoles::FileNameRole: case Qt::ToolTipRole: return QVariant(QDir::toNativeSeparators(file->fileName())); @@ -349,7 +353,7 @@ void SearchResultTreeModel::clear() reset(); } -QModelIndex SearchResultTreeModel::next(const QModelIndex &idx) const +QModelIndex SearchResultTreeModel::next(const QModelIndex &idx, bool includeTopLevel) const { QModelIndex parent = idx.parent(); if (parent.isValid()) { @@ -367,6 +371,8 @@ QModelIndex SearchResultTreeModel::next(const QModelIndex &idx) const // Wrap around nextParent = index(0,0); } + if (includeTopLevel) + return nextParent; return nextParent.child(0, 0); } } else { @@ -376,7 +382,7 @@ QModelIndex SearchResultTreeModel::next(const QModelIndex &idx) const return QModelIndex(); } -QModelIndex SearchResultTreeModel::prev(const QModelIndex &idx) const +QModelIndex SearchResultTreeModel::prev(const QModelIndex &idx, bool includeTopLevel) const { QModelIndex parent = idx.parent(); if (parent.isValid()) { @@ -385,6 +391,8 @@ QModelIndex SearchResultTreeModel::prev(const QModelIndex &idx) const // Same parent return index(row - 1, 0, parent); } else { + if (includeTopLevel) + return parent; // Prev parent int parentRow = parent.row(); QModelIndex prevParent; @@ -399,10 +407,56 @@ QModelIndex SearchResultTreeModel::prev(const QModelIndex &idx) const } else { // We are on a top level item int row = idx.row(); + QModelIndex prevParent; if (row > 0) { - QModelIndex prevParent = index(row - 1, 0); - return prevParent.child(rowCount(prevParent) ,0); + prevParent = index(row - 1, 0); + } else { + // wrap around + prevParent = index(rowCount() -1, 0); } + return prevParent.child(rowCount(prevParent) -1,0); } return QModelIndex(); } + +QModelIndex SearchResultTreeModel::find(const QRegExp &expr, const QModelIndex &index, QTextDocument::FindFlags flags) +{ + QModelIndex resultIndex; + QModelIndex currentIndex = index; + bool backward = (flags & QTextDocument::FindBackward); + + do { + if (backward) + currentIndex = prev(currentIndex, true); + else + currentIndex = next(currentIndex, true); + if (currentIndex.isValid()) { + const QString &text = data(currentIndex, ItemDataRoles::TextRole).toString(); + if (expr.indexIn(text) != -1) + resultIndex = currentIndex; + } + } while (!resultIndex.isValid() && currentIndex.isValid() && currentIndex != index); + return resultIndex; +} + +QModelIndex SearchResultTreeModel::find(const QString &term, const QModelIndex &index, QTextDocument::FindFlags flags) +{ + QModelIndex resultIndex; + QModelIndex currentIndex = index; + bool backward = (flags & QTextDocument::FindBackward); + flags = (flags & (~QTextDocument::FindBackward)); // backward is handled by us ourselves + + do { + if (backward) + currentIndex = prev(currentIndex, true); + else + currentIndex = next(currentIndex, true); + if (currentIndex.isValid()) { + const QString &text = data(currentIndex, ItemDataRoles::TextRole).toString(); + QTextDocument doc(text); + if (!doc.find(term, 0, flags).isNull()) + resultIndex = currentIndex; + } + } while (!resultIndex.isValid() && currentIndex.isValid() && currentIndex != index); + return resultIndex; +} diff --git a/src/plugins/find/searchresulttreemodel.h b/src/plugins/find/searchresulttreemodel.h index 89418b45cc0..d143c1213a1 100644 --- a/src/plugins/find/searchresulttreemodel.h +++ b/src/plugins/find/searchresulttreemodel.h @@ -33,7 +33,9 @@ #include "searchresultwindow.h" #include <QtCore/QAbstractItemModel> +#include <QtCore/QRegExp> #include <QtGui/QFont> +#include <QtGui/QTextDocument> namespace Find { namespace Internal { @@ -62,11 +64,14 @@ public: bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); QVariant headerData(int section, Qt::Orientation orientation, int role) const; - QModelIndex next(const QModelIndex &idx) const; - QModelIndex prev(const QModelIndex &idx) const; + QModelIndex next(const QModelIndex &idx, bool includeTopLevel = false) const; + QModelIndex prev(const QModelIndex &idx, bool includeTopLevel = false) const; QList<int> addResultLines(const QList<SearchResultItem> &items); + QModelIndex find(const QRegExp &expr, const QModelIndex &index, QTextDocument::FindFlags flags); + QModelIndex find(const QString &term, const QModelIndex &index, QTextDocument::FindFlags flags); + signals: void jumpToSearchResult(const QString &fileName, int lineNumber, int searchTermStart, int searchTermLength); diff --git a/src/plugins/find/searchresultwindow.cpp b/src/plugins/find/searchresultwindow.cpp index 7af93b2cc40..404582902da 100644 --- a/src/plugins/find/searchresultwindow.cpp +++ b/src/plugins/find/searchresultwindow.cpp @@ -31,7 +31,9 @@ #include "searchresulttreemodel.h" #include "searchresulttreeitems.h" #include "searchresulttreeview.h" +#include "ifindsupport.h" +#include <aggregation/aggregate.h> #include <coreplugin/icore.h> #include <utils/qtcassert.h> @@ -52,6 +54,8 @@ static const char SETTINGSKEYEXPANDRESULTS[] = "ExpandResults"; namespace Find { +namespace Internal { + class WideEnoughLineEdit : public QLineEdit { Q_OBJECT public: @@ -70,31 +74,137 @@ namespace Find { void updateGeometry() { QLineEdit::updateGeometry(); } }; + class SearchResultFindSupport : public IFindSupport + { + Q_OBJECT + public: + SearchResultFindSupport(SearchResultTreeView *view) + : m_view(view) + { + } -struct SearchResultWindowPrivate { - SearchResultWindowPrivate(); + bool supportsReplace() const { return false; } - Internal::SearchResultTreeView *m_searchResultTreeView; - QListWidget *m_noMatchesFoundDisplay; - QToolButton *m_expandCollapseToolButton; - QLabel *m_replaceLabel; - QLineEdit *m_replaceTextEdit; - QToolButton *m_replaceButton; - static const bool m_initiallyExpand = false; - QStackedWidget *m_widget; - SearchResult *m_currentSearch; - QList<SearchResultItem> m_items; - bool m_isShowingReplaceUI; - bool m_focusReplaceEdit; -}; + IFindSupport::FindFlags supportedFindFlags() const + { + return IFindSupport::FindBackward | IFindSupport::FindCaseSensitively + | IFindSupport::FindRegularExpression | IFindSupport::FindWholeWords; + } -SearchResultWindowPrivate::SearchResultWindowPrivate() - : m_currentSearch(0), - m_isShowingReplaceUI(false), - m_focusReplaceEdit(false) -{ + void resetIncrementalSearch() + { + m_incrementalFindStart = QModelIndex(); + } + + void clearResults() { } + + QString currentFindString() const + { + return QString(); + } + + QString completedFindString() const + { + return QString(); + } + + void highlightAll(const QString &txt, IFindSupport::FindFlags findFlags) + { + Q_UNUSED(txt) + Q_UNUSED(findFlags) + return; + } + + IFindSupport::Result findIncremental(const QString &txt, IFindSupport::FindFlags findFlags) + { + if (!m_incrementalFindStart.isValid()) + m_incrementalFindStart = m_view->currentIndex(); + m_view->setCurrentIndex(m_incrementalFindStart); + return find(txt, findFlags); + } + + IFindSupport::Result findStep(const QString &txt, IFindSupport::FindFlags findFlags) + { + IFindSupport::Result result = find(txt, findFlags); + if (result == IFindSupport::Found) + m_incrementalFindStart = m_view->currentIndex(); + return result; + } + + IFindSupport::Result find(const QString &txt, IFindSupport::FindFlags findFlags) + { + if (txt.isEmpty()) + return IFindSupport::NotFound; + QModelIndex index; + if (findFlags & IFindSupport::FindRegularExpression) { + bool sensitive = (findFlags & IFindSupport::FindCaseSensitively); + index = m_view->model()->find(QRegExp(txt, (sensitive ? Qt::CaseSensitive : Qt::CaseInsensitive)), + m_view->currentIndex(), + IFindSupport::textDocumentFlagsForFindFlags(findFlags)); + } else { + index = m_view->model()->find(txt, m_view->currentIndex(), + IFindSupport::textDocumentFlagsForFindFlags(findFlags)); + } + if (index.isValid()) { + m_view->setCurrentIndex(index); + m_view->scrollTo(index); + if (index.parent().isValid()) + m_view->expand(index.parent()); + return IFindSupport::Found; + } + return IFindSupport::NotFound; + } + + bool replaceStep(const QString &before, const QString &after, + IFindSupport::FindFlags findFlags) + { + Q_UNUSED(before) + Q_UNUSED(after) + Q_UNUSED(findFlags) + return false; + } + + int replaceAll(const QString &before, const QString &after, + IFindSupport::FindFlags findFlags) + { + Q_UNUSED(before) + Q_UNUSED(after) + Q_UNUSED(findFlags) + return 0; + } + + private: + SearchResultTreeView *m_view; + QModelIndex m_incrementalFindStart; + }; + + struct SearchResultWindowPrivate { + SearchResultWindowPrivate(); + + Internal::SearchResultTreeView *m_searchResultTreeView; + QListWidget *m_noMatchesFoundDisplay; + QToolButton *m_expandCollapseToolButton; + QLabel *m_replaceLabel; + QLineEdit *m_replaceTextEdit; + QToolButton *m_replaceButton; + static const bool m_initiallyExpand = false; + QStackedWidget *m_widget; + SearchResult *m_currentSearch; + QList<SearchResultItem> m_items; + bool m_isShowingReplaceUI; + bool m_focusReplaceEdit; + }; + + SearchResultWindowPrivate::SearchResultWindowPrivate() + : m_currentSearch(0), + m_isShowingReplaceUI(false), + m_focusReplaceEdit(false) + { + } } +using namespace Find::Internal; + SearchResultWindow::SearchResultWindow() : d(new SearchResultWindowPrivate) { d->m_widget = new QStackedWidget; @@ -104,6 +214,9 @@ SearchResultWindow::SearchResultWindow() : d(new SearchResultWindowPrivate) d->m_searchResultTreeView->setFrameStyle(QFrame::NoFrame); d->m_searchResultTreeView->setAttribute(Qt::WA_MacShowFocusRect, false); d->m_widget->addWidget(d->m_searchResultTreeView); + Aggregation::Aggregate * agg = new Aggregation::Aggregate; + agg->add(d->m_searchResultTreeView); + agg->add(new SearchResultFindSupport(d->m_searchResultTreeView)); d->m_noMatchesFoundDisplay = new QListWidget(d->m_widget); d->m_noMatchesFoundDisplay->addItem(tr("No matches found!")); diff --git a/src/plugins/find/searchresultwindow.h b/src/plugins/find/searchresultwindow.h index 46932f6fb11..47a80c24682 100644 --- a/src/plugins/find/searchresultwindow.h +++ b/src/plugins/find/searchresultwindow.h @@ -43,6 +43,7 @@ QT_END_NAMESPACE namespace Find { namespace Internal { class SearchResultTreeView; + struct SearchResultWindowPrivate; } class SearchResultWindow; @@ -69,7 +70,6 @@ signals: friend class SearchResultWindow; }; -struct SearchResultWindowPrivate; class FIND_EXPORT SearchResultWindow : public Core::IOutputPane { Q_OBJECT @@ -128,7 +128,7 @@ private: void writeSettings(); QList<SearchResultItem> checkedItems() const; - SearchResultWindowPrivate *d; + Internal::SearchResultWindowPrivate *d; }; } // namespace Find -- GitLab