diff --git a/src/plugins/find/searchresulttreeitemdelegate.cpp b/src/plugins/find/searchresulttreeitemdelegate.cpp index 379db290b1243556b33fab769d9ac494517e25ca..807381f4cfc41ed3783cdca0341eb79e70f081be 100644 --- a/src/plugins/find/searchresulttreeitemdelegate.cpp +++ b/src/plugins/find/searchresulttreeitemdelegate.cpp @@ -48,6 +48,8 @@ SearchResultTreeItemDelegate::SearchResultTreeItemDelegate(QObject *parent) void SearchResultTreeItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { + static const int iconSize = 16; + painter->save(); QStyleOptionViewItemV3 opt = setOptions(index, option); @@ -55,56 +57,63 @@ void SearchResultTreeItemDelegate::paint(QPainter *painter, const QStyleOptionVi QItemDelegate::drawBackground(painter, opt, index); - int iconAreaWidth = drawIcon(painter, opt, opt.rect, index); - QRect resultRowRect(opt.rect.adjusted(iconAreaWidth, 0, 0, 0)); + // ---- do the layout + QRect checkRect; + QRect pixmapRect; + QRect textRect; + + // check mark + bool checkable = (index.model()->flags(index) & Qt::ItemIsUserCheckable); + Qt::CheckState checkState = Qt::Unchecked; + if (checkable) { + QVariant checkStateData = index.data(Qt::CheckStateRole); + checkState = static_cast<Qt::CheckState>(checkStateData.toInt()); + checkRect = check(opt, opt.rect, checkStateData); + } + + // icon + QIcon icon = index.model()->data(index, ItemDataRoles::ResultIconRole).value<QIcon>(); + if (!icon.isNull()) { + pixmapRect = QRect(0, 0, iconSize, iconSize); + } - int lineNumberAreaWidth = drawLineNumber(painter, opt, resultRowRect, index); - resultRowRect.adjust(lineNumberAreaWidth, 0, 0, 0); + // text + textRect = opt.rect.adjusted(0, 0, checkRect.width() + pixmapRect.width(), 0); + // do layout + doLayout(opt, &checkRect, &pixmapRect, &textRect, false); + + // ---- draw the items + // icon + if (!icon.isNull()) + QItemDelegate::drawDecoration(painter, opt, pixmapRect, icon.pixmap(iconSize)); + + // line numbers + int lineNumberAreaWidth = drawLineNumber(painter, opt, textRect, index); + textRect.adjust(lineNumberAreaWidth, 0, 0, 0); + + // selected text QString displayString = index.model()->data(index, Qt::DisplayRole).toString(); - drawMarker(painter, index, displayString, resultRowRect); + drawMarker(painter, index, displayString, textRect); - // Show number of subresults in displayString + // show number of subresults in displayString if (index.model()->hasChildren(index)) { displayString += QString::fromLatin1(" (") + QString::number(index.model()->rowCount(index)) + QLatin1Char(')'); } - // Draw the text and focus/selection - QItemDelegate::drawDisplay(painter, opt, resultRowRect, displayString); + // text and focus/selection + QItemDelegate::drawDisplay(painter, opt, textRect, displayString); QItemDelegate::drawFocus(painter, opt, opt.rect); - QVariant value = index.data(Qt::CheckStateRole); - if (value.isValid()) { - Qt::CheckState checkState = Qt::Unchecked; - checkState = static_cast<Qt::CheckState>(value.toInt()); - QRect checkRect = check(opt, opt.rect, value); - - QRect emptyRect; - doLayout(opt, &checkRect, &emptyRect, &emptyRect, false); - + // check mark + if (checkable) QItemDelegate::drawCheck(painter, opt, checkRect, checkState); - } painter->restore(); } -int SearchResultTreeItemDelegate::drawIcon(QPainter *painter, const QStyleOptionViewItemV3 &option, - const QRect &rect, - const QModelIndex &index) const -{ - static const int iconWidth = 16; - static const int iconPadding = 4; - QIcon icon = index.model()->data(index, ItemDataRoles::ResultIconRole).value<QIcon>(); - if (icon.isNull()) - return 0; - QRect iconRect = rect.adjusted(iconPadding, 0, /*is set below anyhow*/0, 0); - iconRect.setWidth(iconWidth); - QItemDelegate::drawDecoration(painter, option, iconRect, icon.pixmap(iconWidth)); - return iconWidth + iconPadding; -} - int SearchResultTreeItemDelegate::drawLineNumber(QPainter *painter, const QStyleOptionViewItemV3 &option, const QRect &rect, const QModelIndex &index) const diff --git a/src/plugins/find/searchresulttreeitemdelegate.h b/src/plugins/find/searchresulttreeitemdelegate.h index d9fe62cc7f0dac7c4ef9f4bf50080af0e3562ae6..c788a94437b3806eecf629072fd86e9274880e16 100644 --- a/src/plugins/find/searchresulttreeitemdelegate.h +++ b/src/plugins/find/searchresulttreeitemdelegate.h @@ -42,7 +42,6 @@ public: void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; private: - int drawIcon(QPainter *painter, const QStyleOptionViewItemV3 &option, const QRect &rect, const QModelIndex &index) const; int drawLineNumber(QPainter *painter, const QStyleOptionViewItemV3 &option, const QRect &rect, const QModelIndex &index) const; void drawMarker(QPainter *painter, const QModelIndex &index, const QString text, const QRect &rect) const; diff --git a/src/plugins/find/searchresulttreeitems.cpp b/src/plugins/find/searchresulttreeitems.cpp index 9f240680f37d4fc97ea926af90585e3f21836032..d318b4eae6643cb83b428a80615835d0fdef3e0a 100644 --- a/src/plugins/find/searchresulttreeitems.cpp +++ b/src/plugins/find/searchresulttreeitems.cpp @@ -32,7 +32,7 @@ using namespace Find::Internal; SearchResultTreeItem::SearchResultTreeItem(const Find::SearchResultItem &item, - const SearchResultTreeItem *parent) + SearchResultTreeItem *parent) : item(item), m_parent(parent), m_isUserCheckable(false), @@ -92,7 +92,7 @@ SearchResultTreeItem* SearchResultTreeItem::childAt(int index) const return m_children.at(index); } -const SearchResultTreeItem *SearchResultTreeItem::parent() const +SearchResultTreeItem *SearchResultTreeItem::parent() const { return m_parent; } diff --git a/src/plugins/find/searchresulttreeitems.h b/src/plugins/find/searchresulttreeitems.h index ac7fab03d175c335591b1bdda7e512f816964a7a..1c77eb9f6708bf966094f4a4739c9597b81667ca 100644 --- a/src/plugins/find/searchresulttreeitems.h +++ b/src/plugins/find/searchresulttreeitems.h @@ -44,11 +44,11 @@ class SearchResultTreeItem { public: SearchResultTreeItem(const SearchResultItem &item = SearchResultItem(), - const SearchResultTreeItem *parent = NULL); + SearchResultTreeItem *parent = NULL); virtual ~SearchResultTreeItem(); bool isLeaf() const; - const SearchResultTreeItem *parent() const; + SearchResultTreeItem *parent() const; SearchResultTreeItem *childAt(int index) const; int insertionIndex(const QString &text, SearchResultTreeItem **existingItem) const; int insertionIndex(const SearchResultItem &item, SearchResultTreeItem **existingItem) const; @@ -71,7 +71,7 @@ public: SearchResultItem item; private: - const SearchResultTreeItem *m_parent; + SearchResultTreeItem *m_parent; QList<SearchResultTreeItem *> m_children; bool m_isUserCheckable; Qt::CheckState m_checkState; diff --git a/src/plugins/find/searchresulttreemodel.cpp b/src/plugins/find/searchresulttreemodel.cpp index a03922114dc6adb77925f6ca03c3607b1e9d2a84..0c19da073ca0f3b1bb3ef072c85a15f1519ad5ad 100644 --- a/src/plugins/find/searchresulttreemodel.cpp +++ b/src/plugins/find/searchresulttreemodel.cpp @@ -76,7 +76,7 @@ Qt::ItemFlags SearchResultTreeModel::flags(const QModelIndex &idx) const if (idx.isValid()) { if (const SearchResultTreeItem *item = treeItemAtIndex(idx)) { - if (item->isLeaf() && item->isUserCheckable()) { + if (item->isUserCheckable()) { flags |= Qt::ItemIsUserCheckable; } } @@ -173,12 +173,62 @@ bool SearchResultTreeModel::setData(const QModelIndex &idx, const QVariant &valu { if (role == Qt::CheckStateRole) { Qt::CheckState checkState = static_cast<Qt::CheckState>(value.toInt()); - treeItemAtIndex(idx)->setCheckState(checkState); - return true; + return setCheckState(idx, checkState); } return QAbstractItemModel::setData(idx, value, role); } +bool SearchResultTreeModel::setCheckState(const QModelIndex &idx, Qt::CheckState checkState, bool firstCall) +{ + SearchResultTreeItem *item = treeItemAtIndex(idx); + if (item->checkState() == checkState) + return false; + item->setCheckState(checkState); + if (firstCall) { + emit dataChanged(idx, idx); + // check parents + SearchResultTreeItem *currentItem = item; + QModelIndex currentIndex = idx; + while (SearchResultTreeItem *parent = currentItem->parent()) { + if (parent->isUserCheckable()) { + bool hasChecked = false; + bool hasUnchecked = false; + for (int i = 0; i < parent->childrenCount(); ++i) { + SearchResultTreeItem *child = parent->childAt(i); + if (!child->isUserCheckable()) + continue; + if (child->checkState() == Qt::Checked) { + hasChecked = true; + } else if (child->checkState() == Qt::Unchecked) { + hasUnchecked = true; + } else if (child->checkState() == Qt::PartiallyChecked) { + hasChecked = hasUnchecked = true; + } + } + if (hasChecked && hasUnchecked) + parent->setCheckState(Qt::PartiallyChecked); + else if (hasChecked) + parent->setCheckState(Qt::Checked); + else + parent->setCheckState(Qt::Unchecked); + emit dataChanged(idx.parent(), idx.parent()); + } + currentItem = parent; + currentIndex = idx.parent(); + } + } + // check children + if (int children = item->childrenCount()) { + for (int i = 0; i < children; ++i) { + setCheckState(idx.child(i, 0), checkState, false); + } + emit dataChanged(idx.child(0, 0), idx.child(children-1, 0)); + } + return true; +} + +void setDataInternal(const QModelIndex &index, const QVariant &value, int role); + QVariant SearchResultTreeModel::data(const SearchResultTreeItem *row, int role) const { QVariant result; diff --git a/src/plugins/find/searchresulttreemodel.h b/src/plugins/find/searchresulttreemodel.h index ef0cfefce8e9ef18cfe1cf0acab0924010ef36a3..935eab2f12589387004f1422c90725d302c146d9 100644 --- a/src/plugins/find/searchresulttreemodel.h +++ b/src/plugins/find/searchresulttreemodel.h @@ -82,6 +82,7 @@ private: void addResultsToCurrentParent(const QList<SearchResultItem> &items, SearchResultWindow::AddMode mode); QSet<SearchResultTreeItem *> addPath(const QStringList &path); QVariant data(const SearchResultTreeItem *row, int role) const; + bool setCheckState(const QModelIndex &idx, Qt::CheckState checkState, bool firstCall = true); QModelIndex nextIndex(const QModelIndex &idx) const; QModelIndex prevIndex(const QModelIndex &idx) const; SearchResultTreeItem *treeItemAtIndex(const QModelIndex &idx) const;