Fix group mouse interaction issues
This commit is contained in:
parent
b2bf50a6d7
commit
eb0ed082d8
39
Group.cpp
39
Group.cpp
@ -9,9 +9,9 @@
|
|||||||
Group::Group(const QString &text, GroupView *view) : view(view), text(text), collapsed(false)
|
Group::Group(const QString &text, GroupView *view) : view(view), text(text), collapsed(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Group::Group(const Group *other)
|
Group::Group(const Group *other)
|
||||||
: view(other->view), text(other->text), collapsed(other->collapsed),
|
: view(other->view), text(other->text), collapsed(other->collapsed)
|
||||||
iconRect(other->iconRect), textRect(other->textRect)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,6 +27,37 @@ void Group::update()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Group::HitResults Group::pointIntersect(const QPoint &pos) const
|
||||||
|
{
|
||||||
|
Group::HitResults results = Group::NoHit;
|
||||||
|
int y_start = top();
|
||||||
|
int body_start = y_start + headerHeight();
|
||||||
|
int body_end = body_start + contentHeight() + 5; // FIXME: wtf is this 5?
|
||||||
|
int y = pos.y();
|
||||||
|
// int x = pos.x();
|
||||||
|
if(y < y_start)
|
||||||
|
{
|
||||||
|
results = Group::NoHit;
|
||||||
|
}
|
||||||
|
else if(y < body_start)
|
||||||
|
{
|
||||||
|
results = Group::HeaderHit;
|
||||||
|
int collapseSize = headerHeight() - 4;
|
||||||
|
|
||||||
|
// the icon
|
||||||
|
QRect iconRect = QRect(view->m_leftMargin + 2, 2 + y_start, collapseSize, collapseSize);
|
||||||
|
if(iconRect.contains(pos))
|
||||||
|
{
|
||||||
|
results |= Group::CheckboxHit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (y < body_end)
|
||||||
|
{
|
||||||
|
results |= Group::BodyHit;
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
void Group::drawHeader(QPainter *painter, const int y)
|
void Group::drawHeader(QPainter *painter, const int y)
|
||||||
{
|
{
|
||||||
painter->save();
|
painter->save();
|
||||||
@ -35,7 +66,7 @@ void Group::drawHeader(QPainter *painter, const int y)
|
|||||||
int collapseSize = height;
|
int collapseSize = height;
|
||||||
|
|
||||||
// the icon
|
// the icon
|
||||||
iconRect = QRect(view->m_rightMargin + 2, 2 + y, collapseSize, collapseSize);
|
QRect iconRect = QRect(view->m_leftMargin + 2, 2 + y, collapseSize, collapseSize);
|
||||||
painter->setPen(QPen(Qt::black, 1));
|
painter->setPen(QPen(Qt::black, 1));
|
||||||
painter->drawRect(iconRect);
|
painter->drawRect(iconRect);
|
||||||
static const int margin = 2;
|
static const int margin = 2;
|
||||||
@ -50,7 +81,7 @@ void Group::drawHeader(QPainter *painter, const int y)
|
|||||||
|
|
||||||
// the text
|
// the text
|
||||||
int textWidth = painter->fontMetrics().width(text);
|
int textWidth = painter->fontMetrics().width(text);
|
||||||
textRect = QRect(iconRect.right() + 4, y, textWidth, headerHeight());
|
QRect textRect = QRect(iconRect.right() + 4, y, textWidth, headerHeight());
|
||||||
painter->setBrush(view->viewOptions().palette.text());
|
painter->setBrush(view->viewOptions().palette.text());
|
||||||
view->style()->drawItemText(painter, textRect, Qt::AlignHCenter | Qt::AlignVCenter,
|
view->style()->drawItemText(painter, textRect, Qt::AlignHCenter | Qt::AlignVCenter,
|
||||||
view->viewport()->palette(), true, text);
|
view->viewport()->palette(), true, text);
|
||||||
|
16
Group.h
16
Group.h
@ -15,8 +15,6 @@ struct Group
|
|||||||
GroupView *view;
|
GroupView *view;
|
||||||
QString text;
|
QString text;
|
||||||
bool collapsed;
|
bool collapsed;
|
||||||
QRect iconRect;
|
|
||||||
QRect textRect;
|
|
||||||
QVector<int> rowHeights;
|
QVector<int> rowHeights;
|
||||||
int firstRow;
|
int firstRow;
|
||||||
|
|
||||||
@ -29,8 +27,22 @@ struct Group
|
|||||||
int numRows() const;
|
int numRows() const;
|
||||||
int top() const;
|
int top() const;
|
||||||
|
|
||||||
|
enum HitResult
|
||||||
|
{
|
||||||
|
NoHit = 0x0,
|
||||||
|
TextHit = 0x1,
|
||||||
|
CheckboxHit = 0x2,
|
||||||
|
HeaderHit = 0x4,
|
||||||
|
BodyHit = 0x8
|
||||||
|
};
|
||||||
|
Q_DECLARE_FLAGS(HitResults, HitResult)
|
||||||
|
|
||||||
|
HitResults pointIntersect (const QPoint &pos) const;
|
||||||
|
|
||||||
QList<QModelIndex> items() const;
|
QList<QModelIndex> items() const;
|
||||||
int numItems() const;
|
int numItems() const;
|
||||||
QModelIndex firstItem() const;
|
QModelIndex firstItem() const;
|
||||||
QModelIndex lastItem() const;
|
QModelIndex lastItem() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_OPERATORS_FOR_FLAGS(Group::HitResults)
|
||||||
|
@ -36,7 +36,7 @@ GroupView::GroupView(QWidget *parent)
|
|||||||
// setWordWrap(true);
|
// setWordWrap(true);
|
||||||
// setDragDropMode(QListView::InternalMove);
|
// setDragDropMode(QListView::InternalMove);
|
||||||
setAcceptDrops(true);
|
setAcceptDrops(true);
|
||||||
// setSpacing(10);
|
m_spacing = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupView::~GroupView()
|
GroupView::~GroupView()
|
||||||
@ -145,31 +145,31 @@ Group *GroupView::category(const QModelIndex &index) const
|
|||||||
|
|
||||||
Group *GroupView::category(const QString &cat) const
|
Group *GroupView::category(const QString &cat) const
|
||||||
{
|
{
|
||||||
for (int i = 0; i < m_categories.size(); ++i)
|
for (auto group : m_categories)
|
||||||
{
|
{
|
||||||
if (m_categories.at(i)->text == cat)
|
if (group->text == cat)
|
||||||
{
|
{
|
||||||
return m_categories.at(i);
|
return group;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Group *GroupView::categoryAt(const QPoint &pos) const
|
Group *GroupView::categoryAt(const QPoint &pos) const
|
||||||
{
|
{
|
||||||
for (int i = 0; i < m_categories.size(); ++i)
|
for (auto group : m_categories)
|
||||||
{
|
{
|
||||||
if (m_categories.at(i)->iconRect.contains(pos))
|
if(group->pointIntersect(pos) & Group::CheckboxHit)
|
||||||
{
|
{
|
||||||
return m_categories.at(i);
|
return group;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GroupView::itemsPerRow() const
|
int GroupView::itemsPerRow() const
|
||||||
{
|
{
|
||||||
return qFloor((qreal)(contentWidth()) / (qreal)(itemWidth() + /* spacing */ 10));
|
return qFloor((qreal)(contentWidth()) / (qreal)(itemWidth() + m_spacing));
|
||||||
}
|
}
|
||||||
|
|
||||||
int GroupView::contentWidth() const
|
int GroupView::contentWidth() const
|
||||||
@ -261,7 +261,7 @@ void GroupView::mousePressEvent(QMouseEvent *event)
|
|||||||
|
|
||||||
m_pressedIndex = index;
|
m_pressedIndex = index;
|
||||||
m_pressedAlreadySelected = selectionModel()->isSelected(m_pressedIndex);
|
m_pressedAlreadySelected = selectionModel()->isSelected(m_pressedIndex);
|
||||||
QItemSelectionModel::SelectionFlags command = selectionCommand(index, event);
|
QItemSelectionModel::SelectionFlags selection_flags = selectionCommand(index, event);
|
||||||
m_pressedPosition = pos;
|
m_pressedPosition = pos;
|
||||||
|
|
||||||
m_pressedCategory = categoryAt(m_pressedPosition);
|
m_pressedCategory = categoryAt(m_pressedPosition);
|
||||||
@ -428,9 +428,8 @@ void GroupView::mouseDoubleClickEvent(QMouseEvent *event)
|
|||||||
void GroupView::paintEvent(QPaintEvent *event)
|
void GroupView::paintEvent(QPaintEvent *event)
|
||||||
{
|
{
|
||||||
QPainter painter(this->viewport());
|
QPainter painter(this->viewport());
|
||||||
painter.translate(-offset());
|
|
||||||
|
|
||||||
int y = 0;
|
int y = -verticalOffset();
|
||||||
for (int i = 0; i < m_categories.size(); ++i)
|
for (int i = 0; i < m_categories.size(); ++i)
|
||||||
{
|
{
|
||||||
Group *category = m_categories.at(i);
|
Group *category = m_categories.at(i);
|
||||||
@ -502,7 +501,7 @@ void GroupView::resizeEvent(QResizeEvent *event)
|
|||||||
// if (m_categoryEditor)
|
// if (m_categoryEditor)
|
||||||
// {
|
// {
|
||||||
// m_categoryEditor->resize(qMax(contentWidth() / 2,
|
// m_categoryEditor->resize(qMax(contentWidth() / 2,
|
||||||
//m_editedCategory->textRect.width()),
|
// m_editedCategory->textRect.width()),
|
||||||
// m_categoryEditor->height());
|
// m_categoryEditor->height());
|
||||||
// }
|
// }
|
||||||
|
|
||||||
@ -618,6 +617,11 @@ void GroupView::startDrag(Qt::DropActions supportedActions)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QRect GroupView::visualRect(const QModelIndex &index) const
|
QRect GroupView::visualRect(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
return geometryRect(index).translated(-offset());
|
||||||
|
}
|
||||||
|
|
||||||
|
QRect GroupView::geometryRect(const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
if (!index.isValid() || isIndexHidden(index) || index.column() > 0)
|
if (!index.isValid() || isIndexHidden(index) || index.column() > 0)
|
||||||
{
|
{
|
||||||
@ -627,15 +631,16 @@ QRect GroupView::visualRect(const QModelIndex &index) const
|
|||||||
const Group *cat = category(index);
|
const Group *cat = category(index);
|
||||||
QPair<int, int> pos = categoryInternalPosition(index);
|
QPair<int, int> pos = categoryInternalPosition(index);
|
||||||
int x = pos.first;
|
int x = pos.first;
|
||||||
int y = pos.second;
|
// int y = pos.second;
|
||||||
|
|
||||||
QRect out;
|
QRect out;
|
||||||
out.setTop(cat->top() + cat->headerHeight() + 5 + categoryInternalRowTop(index));
|
out.setTop(cat->top() + cat->headerHeight() + 5 + categoryInternalRowTop(index));
|
||||||
out.setLeft(/*spacing*/ 10 + x * itemWidth() + x * /*spacing()*/ 10);
|
out.setLeft(m_spacing + x * (itemWidth() + m_spacing));
|
||||||
out.setSize(itemDelegate()->sizeHint(viewOptions(), index));
|
out.setSize(itemDelegate()->sizeHint(viewOptions(), index));
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
void CategorizedView::startCategoryEditor(Category *category)
|
void CategorizedView::startCategoryEditor(Category *category)
|
||||||
{
|
{
|
||||||
@ -680,7 +685,7 @@ QModelIndex GroupView::indexAt(const QPoint &point) const
|
|||||||
for (int i = 0; i < model()->rowCount(); ++i)
|
for (int i = 0; i < model()->rowCount(); ++i)
|
||||||
{
|
{
|
||||||
QModelIndex index = model()->index(i, 0);
|
QModelIndex index = model()->index(i, 0);
|
||||||
if (visualRect(index).contains(point))
|
if (geometryRect(index).contains(point))
|
||||||
{
|
{
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
@ -694,7 +699,7 @@ void GroupView::setSelection(const QRect &rect,
|
|||||||
for (int i = 0; i < model()->rowCount(); ++i)
|
for (int i = 0; i < model()->rowCount(); ++i)
|
||||||
{
|
{
|
||||||
QModelIndex index = model()->index(i, 0);
|
QModelIndex index = model()->index(i, 0);
|
||||||
if (visualRect(index).intersects(rect))
|
if (geometryRect(index).intersects(rect))
|
||||||
{
|
{
|
||||||
selectionModel()->select(index, commands);
|
selectionModel()->select(index, commands);
|
||||||
}
|
}
|
||||||
@ -734,7 +739,7 @@ QList<QPair<QRect, QModelIndex>> GroupView::draggablePaintPairs(const QModelInde
|
|||||||
for (int i = 0; i < indices.count(); ++i)
|
for (int i = 0; i < indices.count(); ++i)
|
||||||
{
|
{
|
||||||
const QModelIndex &index = indices.at(i);
|
const QModelIndex &index = indices.at(i);
|
||||||
const QRect current = visualRect(index);
|
const QRect current = geometryRect(index);
|
||||||
if (current.intersects(viewportRect))
|
if (current.intersects(viewportRect))
|
||||||
{
|
{
|
||||||
ret += qMakePair(current, index);
|
ret += qMakePair(current, index);
|
||||||
@ -857,3 +862,24 @@ QPoint GroupView::offset() const
|
|||||||
{
|
{
|
||||||
return QPoint(horizontalOffset(), verticalOffset());
|
return QPoint(horizontalOffset(), verticalOffset());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QRegion GroupView::visualRegionForSelection(const QItemSelection &selection) const
|
||||||
|
{
|
||||||
|
QRegion region;
|
||||||
|
for (auto &range : selection)
|
||||||
|
{
|
||||||
|
int start_row = range.top();
|
||||||
|
int end_row = range.bottom();
|
||||||
|
for (int row = start_row; row <= end_row; ++row)
|
||||||
|
{
|
||||||
|
int start_column = range.left();
|
||||||
|
int end_column = range.right();
|
||||||
|
for (int column = start_column; column <= end_column; ++column)
|
||||||
|
{
|
||||||
|
QModelIndex index = model()->index(row, column, rootIndex());
|
||||||
|
region += visualRect(index); // OK
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
23
GroupView.h
23
GroupView.h
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <QListView>
|
#include <QListView>
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
|
#include <QScrollBar>
|
||||||
|
|
||||||
struct CategorizedViewRoles
|
struct CategorizedViewRoles
|
||||||
{
|
{
|
||||||
@ -23,7 +24,8 @@ public:
|
|||||||
GroupView(QWidget *parent = 0);
|
GroupView(QWidget *parent = 0);
|
||||||
~GroupView();
|
~GroupView();
|
||||||
|
|
||||||
virtual QRect visualRect(const QModelIndex &index) const;
|
virtual QRect geometryRect(const QModelIndex &index) const;
|
||||||
|
virtual QRect visualRect(const QModelIndex &index) const override;
|
||||||
QModelIndex indexAt(const QPoint &point) const;
|
QModelIndex indexAt(const QPoint &point) const;
|
||||||
void setSelection(const QRect &rect,
|
void setSelection(const QRect &rect,
|
||||||
const QItemSelectionModel::SelectionFlags commands) override;
|
const QItemSelectionModel::SelectionFlags commands) override;
|
||||||
@ -34,12 +36,18 @@ public:
|
|||||||
|
|
||||||
virtual int horizontalOffset() const override
|
virtual int horizontalOffset() const override
|
||||||
{
|
{
|
||||||
return 0;
|
return horizontalScrollBar()->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int verticalOffset() const override
|
virtual int verticalOffset() const override
|
||||||
{
|
{
|
||||||
return 0;
|
return verticalScrollBar()->value();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void scrollContentsBy(int dx, int dy) override
|
||||||
|
{
|
||||||
|
scrollDirtyRegion(dx, dy);
|
||||||
|
viewport()->scroll(dx, dy);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible) override
|
virtual void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible) override
|
||||||
@ -53,10 +61,7 @@ public:
|
|||||||
return QModelIndex();
|
return QModelIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual QRegion visualRegionForSelection(const QItemSelection &) const override
|
virtual QRegion visualRegionForSelection(const QItemSelection &selection) const override;
|
||||||
{
|
|
||||||
return QRegion();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* End of BS
|
* End of BS
|
||||||
@ -116,14 +121,16 @@ private:
|
|||||||
private slots:
|
private slots:
|
||||||
void endCategoryEditor();*/
|
void endCategoryEditor();*/
|
||||||
|
|
||||||
private:
|
private: /* variables */
|
||||||
QPoint m_pressedPosition;
|
QPoint m_pressedPosition;
|
||||||
QPersistentModelIndex m_pressedIndex;
|
QPersistentModelIndex m_pressedIndex;
|
||||||
bool m_pressedAlreadySelected;
|
bool m_pressedAlreadySelected;
|
||||||
Group *m_pressedCategory;
|
Group *m_pressedCategory;
|
||||||
QItemSelectionModel::SelectionFlag m_ctrlDragSelectionFlag;
|
QItemSelectionModel::SelectionFlag m_ctrlDragSelectionFlag;
|
||||||
QPoint m_lastDragPosition;
|
QPoint m_lastDragPosition;
|
||||||
|
int m_spacing = 5;
|
||||||
|
|
||||||
|
private: /* methods */
|
||||||
QPair<int, int> categoryInternalPosition(const QModelIndex &index) const;
|
QPair<int, int> categoryInternalPosition(const QModelIndex &index) const;
|
||||||
int categoryInternalRowTop(const QModelIndex &index) const;
|
int categoryInternalRowTop(const QModelIndex &index) const;
|
||||||
int itemHeightForCategoryRow(const Group *category, const int internalRow) const;
|
int itemHeightForCategoryRow(const Group *category, const int internalRow) const;
|
||||||
|
Loading…
Reference in New Issue
Block a user