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
......@@ -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;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment