Skip to content
Snippets Groups Projects
Commit 6cc0abfe authored by con's avatar con
Browse files

Fix check boxes in search result window.

Use the right painting methods to make it look good, and also make
(de-)selecting all subitems of a node possible.
parent 77942894
No related branches found
No related tags found
No related merge requests found
......@@ -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
......
......@@ -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;
......
......@@ -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;
}
......
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment