From 6553746b8679ec8bd535aa74619eb23eebaa6725 Mon Sep 17 00:00:00 2001 From: apo Date: Fri, 4 Oct 2013 09:11:06 +0000 Subject: [PATCH] On behalf of Sergey Pokhodenko (SPO): refs #3308 : Issue 32333: "next" button is not working Fix QtxSearchTool. The case when tree based on first column and search by any other column. --- src/Qtx/QtxSearchTool.cxx | 139 ++++++++++++++++++++++++++++++++++++-- src/Qtx/QtxSearchTool.h | 15 +++- 2 files changed, 146 insertions(+), 8 deletions(-) diff --git a/src/Qtx/QtxSearchTool.cxx b/src/Qtx/QtxSearchTool.cxx index 0a58da5d3..a1475100c 100644 --- a/src/Qtx/QtxSearchTool.cxx +++ b/src/Qtx/QtxSearchTool.cxx @@ -1411,12 +1411,24 @@ QModelIndexList QtxViewSearcher::findItems( const QString& text, QtxSearchTool* } if ( model() ) - return model()->match( model()->index( 0, myColumn ), + return match( model()->index( 0, myColumn ), Qt::DisplayRole, s, -1, fl ); return QModelIndexList(); } +/*! + \brief Returns list of indexes like QAbstractItemModel::match. + \internal + \details Uses default QAbstractItemModel::match. +*/ +QModelIndexList QtxViewSearcher::match(const QModelIndex &start, int role, + const QVariant &value, int hits, + Qt::MatchFlags flags) const +{ + return model()->match( start, role, value, hits, flags ); +} + /*! \brief Find model index from the list nearest to the specified index. \internal @@ -1436,7 +1448,7 @@ QModelIndex QtxViewSearcher::findNearest( const QModelIndex& index, { QModelIndex found = it.next(); if ( compareIndices( found, index ) > 0 ) - return found; + return found; } } else @@ -1447,7 +1459,7 @@ QModelIndex QtxViewSearcher::findNearest( const QModelIndex& index, { QModelIndex found = it.previous(); if ( compareIndices( found, index ) < 0 ) - return found; + return found; } } return QModelIndex(); @@ -1614,9 +1626,20 @@ void QtxTreeViewSearcher::showItem( const QModelIndex& index ) */ QModelIndexList QtxTreeViewSearcher::selectedItems() const { - return ( myView && myView->selectionModel() ) ? - myView->selectionModel()->selectedIndexes() : - QModelIndexList(); + QModelIndexList anSelectedIndexes = ( myView && myView->selectionModel() ) ? + myView->selectionModel()->selectedIndexes() : + QModelIndexList(); + // filter indexes by column for eliminate finding the same line + QModelIndexList anFilteredIndexes; + QListIterator it( anSelectedIndexes ); + while ( it.hasNext() ) + { + QModelIndex anIndex = it.next(); + if ( anIndex.column() == searchColumn() ) + anFilteredIndexes.push_back( anIndex ); + } + + return anFilteredIndexes; } /*! @@ -1628,6 +1651,110 @@ QAbstractItemModel* QtxTreeViewSearcher::model() const return myView ? myView->model() : 0; } +/*! + \brief Copy from Qt to fix problem with trees organized by first column. + \internal + \details "model()->" is added for functions call (e.g. rowCount, data...). + For recurse match first column is used. + Adjusted for tree models with hierarchy based on first column +*/ +QModelIndexList QtxTreeViewSearcher::match(const QModelIndex &start, int role, + const QVariant &value, int hits, + Qt::MatchFlags flags) const +{ + QModelIndexList result; + uint matchType = flags & 0x0F; + Qt::CaseSensitivity cs = flags & Qt::MatchCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive; + bool recurse = flags & Qt::MatchRecursive; + bool wrap = flags & Qt::MatchWrap; + bool allHits = (hits == -1); + QString text; // only convert to a string if it is needed + QModelIndex p = model()->parent(start); // "model()->" added + int from = start.row(); + int to = model()->rowCount(p); // "model()->" added + + // iterates twice if wrapping + for (int i = 0; (wrap && i < 2) || (!wrap && i < 1); ++i) { + for (int r = from; (r < to) && (allHits || result.count() < hits); ++r) { + QModelIndex idx = model()->index(r, start.column(), p); // "model()->" added + if (!idx.isValid()) + continue; + QVariant v = model()->data(idx, role); // "model()->" added + // QVariant based matching + if (matchType == Qt::MatchExactly) { + if (value == v) + result.append(idx); + } else { // QString based matching + if (text.isEmpty()) // lazy conversion + text = value.toString(); + QString t = v.toString(); + switch (matchType) { + case Qt::MatchRegExp: + if (QRegExp(text, cs).exactMatch(t)) + result.append(idx); + break; + case Qt::MatchWildcard: + if (QRegExp(text, cs, QRegExp::Wildcard).exactMatch(t)) + result.append(idx); + break; + case Qt::MatchStartsWith: + if (t.startsWith(text, cs)) + result.append(idx); + break; + case Qt::MatchEndsWith: + if (t.endsWith(text, cs)) + result.append(idx); + break; + case Qt::MatchFixedString: + if (t.compare(text, cs) == 0) + result.append(idx); + break; + case Qt::MatchContains: + default: + if (t.contains(text, cs)) + result.append(idx); + } + } + QModelIndex treeIdx = model()->index( idx.row(), 0, idx.parent() ); // all added + if (recurse && model()->hasChildren(treeIdx)) { // search the hierarchy // "model()->" added // idx -> treeIdx + result += match(model()->index(0, idx.column(), treeIdx), role, // "model()->" added // idx -> treeIdx + (text.isEmpty() ? value : text), + (allHits ? -1 : hits - result.count()), flags); + } + } + // prepare for the next iteration + from = 0; + to = start.row(); + } + return result; +} + +/*! + \brief Compare items. + \param left first model index to be compared + \param right last model index to be compared + \return 0 if items are equal, negative value if left item is less than right one + and positive value otherwise + \details Adjusted for tree models with hierarchy based on first column +*/ +int QtxTreeViewSearcher::compareIndices( const QModelIndex& left, + const QModelIndex& right ) const +{ + QModelIndexList idsLeft = getId( left ); + QModelIndexList idsRight = getId( right ); + for ( int i = 0; i < idsLeft.count() && i < idsRight.count(); i++ ) + { + QModelIndex lid = idsLeft[i]; + QModelIndex rid = idsRight[i]; + if ( lid.row() != rid.row() ) + return lid.row() - rid.row(); +// else if ( lid.column() != rid.column() ) +// return lid.column() - rid.column(); + } + return idsLeft.count() < idsRight.count() ? -1 : + ( idsLeft.count() == idsRight.count() ? 0 : 1 ); +} + //------------------------------------------------------------------------------ diff --git a/src/Qtx/QtxSearchTool.h b/src/Qtx/QtxSearchTool.h index 9e489b36d..6d14a3ab4 100644 --- a/src/Qtx/QtxSearchTool.h +++ b/src/Qtx/QtxSearchTool.h @@ -205,15 +205,19 @@ protected: virtual void showItem( const QModelIndex& ) = 0; virtual QModelIndexList selectedItems() const = 0; virtual QAbstractItemModel* model() const = 0; + virtual QModelIndexList match( const QModelIndex &start, int role, + const QVariant &value, int hits, + Qt::MatchFlags flags) const; inline void setCurrentIndex( const QModelIndex& index ); inline const QPersistentModelIndex& currentIndex() const; - + private: QModelIndexList findItems( const QString&, QtxSearchTool* ); QModelIndex findNearest( const QModelIndex&, const QModelIndexList&, bool ); +protected: QModelIndexList getId( const QModelIndex& ) const; - int compareIndices( const QModelIndex&, const QModelIndex& ) const; + virtual int compareIndices( const QModelIndex&, const QModelIndex& ) const; private: int myColumn; @@ -248,6 +252,13 @@ protected: virtual QModelIndexList selectedItems() const; virtual QAbstractItemModel* model() const; +protected: + virtual QModelIndexList match( const QModelIndex &start, int role, + const QVariant &value, int hits, + Qt::MatchFlags flags) const; + + virtual int compareIndices( const QModelIndex&, const QModelIndex& ) const; + private: QTreeView* myView; }; -- 2.39.2