Loads of fixes

This commit is contained in:
Jan Dalheimer 2013-12-30 18:46:12 +01:00
parent 4662fbd298
commit 1e1b2342f4
3 changed files with 77 additions and 48 deletions

View File

@ -79,7 +79,6 @@ int CategorizedView::Category::contentHeight() const
{ {
return 0; return 0;
} }
const int rows = qMax(1, qCeil((qreal)view->numItemsForCategory(this) / (qreal)view->itemsPerRow()));
QMap<int, int> rowToHeightMapping; QMap<int, int> rowToHeightMapping;
foreach (const QModelIndex &index, view->itemsForCategory(this)) foreach (const QModelIndex &index, view->itemsForCategory(this))
{ {
@ -90,20 +89,23 @@ int CategorizedView::Category::contentHeight() const
} }
} }
int result = 0; int result = 0;
for (int i = 0; i < rows; ++i) if (!rowToHeightMapping.isEmpty())
{ {
Q_ASSERT(rowToHeightMapping.contains(i)); for (int i = 0; i < numRows(); ++i)
result += rowToHeightMapping[i]; {
Q_ASSERT(rowToHeightMapping.contains(i));
result += rowToHeightMapping[i];
}
} }
return result; return result;
} }
QSize CategorizedView::Category::categoryTotalSize() const int CategorizedView::Category::numRows() const
{ {
return QSize(view->contentWidth(), contentHeight()); return qMax(1, qCeil((qreal)view->numItemsForCategory(this) / (qreal)view->itemsPerRow()));
} }
CategorizedView::CategorizedView(QWidget *parent) CategorizedView::CategorizedView(QWidget *parent)
: QListView(parent), m_leftMargin(5), m_rightMargin(5), m_categoryMargin(5)//, m_updatesDisabled(false), m_categoryEditor(0), m_editedCategory(0) : QListView(parent), m_leftMargin(5), m_rightMargin(5), m_bottomMargin(5), m_categoryMargin(5)//, m_updatesDisabled(false), m_categoryEditor(0), m_editedCategory(0)
{ {
setViewMode(IconMode); setViewMode(IconMode);
setMovement(Snap); setMovement(Snap);
@ -168,10 +170,7 @@ void CategorizedView::updateGeometries()
{ {
QListView::updateGeometries(); QListView::updateGeometries();
m_cachedItemWidth = -1; invalidateCaches();
m_cachedCategoryToIndexMapping.clear();
m_cachedVisualRects.clear();
m_cachedItemSizes.clear();
QMap<QString, Category *> cats; QMap<QString, Category *> cats;
@ -213,6 +212,7 @@ void CategorizedView::updateGeometries()
} }
// remove the last margin (we don't want it) // remove the last margin (we don't want it)
totalHeight -= m_categoryMargin; totalHeight -= m_categoryMargin;
totalHeight += m_bottomMargin;
verticalScrollBar()->setRange(0, totalHeight- height()); verticalScrollBar()->setRange(0, totalHeight- height());
} }
@ -265,7 +265,7 @@ int CategorizedView::numItemsForCategory(const CategorizedView::Category *catego
} }
QList<QModelIndex> CategorizedView::itemsForCategory(const CategorizedView::Category *category) const QList<QModelIndex> CategorizedView::itemsForCategory(const CategorizedView::Category *category) const
{ {
if (!m_cachedCategoryToIndexMapping.contains(category)) if (!m_cachedCategoryToIndexMapping.contains(category) || true)
{ {
QList<QModelIndex> *indices = new QList<QModelIndex>(); QList<QModelIndex> *indices = new QList<QModelIndex>();
for (int i = 0; i < model()->rowCount(); ++i) for (int i = 0; i < model()->rowCount(); ++i)
@ -393,26 +393,30 @@ QPair<int, int> CategorizedView::categoryInternalPosition(const QModelIndex &ind
} }
return qMakePair(x, y); return qMakePair(x, y);
} }
int CategorizedView::itemHeightForCategoryRow(const CategorizedView::Category *category, const int internalRow) const
{
foreach (const QModelIndex &i, itemsForCategory(category))
{
QPair<int, int> pos = categoryInternalPosition(i);
if (pos.second == internalRow)
{
return itemSize(i).height();
}
}
return -1;
}
void CategorizedView::mousePressEvent(QMouseEvent *event) void CategorizedView::mousePressEvent(QMouseEvent *event)
{ {
//endCategoryEditor(); //endCategoryEditor();
QPoint pos = event->pos(); QPoint pos = event->pos() + offset();
QPersistentModelIndex index = indexAt(pos); QPersistentModelIndex index = indexAt(pos);
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 command = selectionCommand(index, event);
QPoint offset = QPoint(horizontalOffset(), verticalOffset()); m_pressedPosition = pos;
if (!(command & QItemSelectionModel::Current))
{
m_pressedPosition = pos + offset;
}
else if (!indexAt(m_pressedPosition - offset).isValid())
{
m_pressedPosition = visualRect(currentIndex()).center() + offset;
}
m_pressedCategory = categoryAt(m_pressedPosition); m_pressedCategory = categoryAt(m_pressedPosition);
if (m_pressedCategory) if (m_pressedCategory)
@ -430,7 +434,7 @@ void CategorizedView::mousePressEvent(QMouseEvent *event)
setAutoScroll(false); setAutoScroll(false);
selectionModel()->setCurrentIndex(index, QItemSelectionModel::NoUpdate); selectionModel()->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
setAutoScroll(autoScroll); setAutoScroll(autoScroll);
QRect rect(m_pressedPosition - offset, pos); QRect rect(m_pressedPosition, pos);
if (command.testFlag(QItemSelectionModel::Toggle)) if (command.testFlag(QItemSelectionModel::Toggle))
{ {
command &= ~QItemSelectionModel::Toggle; command &= ~QItemSelectionModel::Toggle;
@ -459,7 +463,7 @@ void CategorizedView::mouseMoveEvent(QMouseEvent *event)
if (state() == DraggingState) if (state() == DraggingState)
{ {
topLeft = m_pressedPosition - QPoint(horizontalOffset(), verticalOffset()); topLeft = m_pressedPosition - offset();
if ((topLeft - event->pos()).manhattanLength() > QApplication::startDragDistance()) if ((topLeft - event->pos()).manhattanLength() > QApplication::startDragDistance())
{ {
m_pressedIndex = QModelIndex(); m_pressedIndex = QModelIndex();
@ -474,7 +478,7 @@ void CategorizedView::mouseMoveEvent(QMouseEvent *event)
if (selectionMode() != SingleSelection) if (selectionMode() != SingleSelection)
{ {
topLeft = m_pressedPosition - QPoint(horizontalOffset(), verticalOffset()); topLeft = m_pressedPosition - offset();
} }
else else
{ {
@ -515,7 +519,7 @@ void CategorizedView::mouseMoveEvent(QMouseEvent *event)
} }
void CategorizedView::mouseReleaseEvent(QMouseEvent *event) void CategorizedView::mouseReleaseEvent(QMouseEvent *event)
{ {
QPoint pos = event->pos(); QPoint pos = event->pos() - offset();
QPersistentModelIndex index = indexAt(pos); QPersistentModelIndex index = indexAt(pos);
bool click = (index == m_pressedIndex && index.isValid()) || (m_pressedCategory && m_pressedCategory == categoryAt(pos)); bool click = (index == m_pressedIndex && index.isValid()) || (m_pressedCategory && m_pressedCategory == categoryAt(pos));
@ -582,8 +586,10 @@ void CategorizedView::mouseDoubleClickEvent(QMouseEvent *event)
void CategorizedView::paintEvent(QPaintEvent *event) void CategorizedView::paintEvent(QPaintEvent *event)
{ {
QPainter painter(this->viewport()); QPainter painter(this->viewport());
QPoint offset(horizontalOffset(), verticalOffset()); painter.translate(-offset());
painter.translate(-offset);
// FIXME we shouldn't need to do this
invalidateCaches();
int y = 0; int y = 0;
for (int i = 0; i < m_categories.size(); ++i) for (int i = 0; i < m_categories.size(); ++i)
@ -665,7 +671,7 @@ void CategorizedView::dragEnterEvent(QDragEnterEvent *event)
{ {
return; return;
} }
m_lastDragPosition = event->pos(); m_lastDragPosition = event->pos() + offset();
viewport()->update(); viewport()->update();
event->accept(); event->accept();
} }
@ -675,7 +681,7 @@ void CategorizedView::dragMoveEvent(QDragMoveEvent *event)
{ {
return; return;
} }
m_lastDragPosition = event->pos(); m_lastDragPosition = event->pos() + offset();
viewport()->update(); viewport()->update();
event->accept(); event->accept();
} }
@ -696,7 +702,7 @@ void CategorizedView::dropEvent(QDropEvent *event)
return; return;
} }
QPair<Category *, int> dropPos = rowDropPos(event->pos()); QPair<Category *, int> dropPos = rowDropPos(event->pos() + offset());
const Category *category = dropPos.first; const Category *category = dropPos.first;
const int row = dropPos.second; const int row = dropPos.second;
@ -729,7 +735,8 @@ void CategorizedView::startDrag(Qt::DropActions supportedActions)
} }
QRect rect; QRect rect;
QPixmap pixmap = renderToPixmap(indexes, &rect); QPixmap pixmap = renderToPixmap(indexes, &rect);
rect.adjust(horizontalOffset(), verticalOffset(), 0, 0); rect.translate(offset());
//rect.adjust(horizontalOffset(), verticalOffset(), 0, 0);
QDrag *drag = new QDrag(this); QDrag *drag = new QDrag(this);
drag->setPixmap(pixmap); drag->setPixmap(pixmap);
drag->setMimeData(data); drag->setMimeData(data);
@ -935,15 +942,22 @@ QPair<CategorizedView::Category *, int> CategorizedView::rowDropPos(const QPoint
int internalColumn = -1; int internalColumn = -1;
{ {
const int itemWidth = this->itemWidth(); const int itemWidth = this->itemWidth();
for (int i = 0, c = 0; if (pos.x() >= (itemWidth * itemsPerRow()))
i < contentWidth();
i += itemWidth, ++c)
{ {
if (pos.x() > (i - itemWidth / 2) && internalColumn = itemsPerRow();
pos.x() < (i + itemWidth / 2)) }
else
{
for (int i = 0, c = 0;
i < contentWidth();
i += itemWidth + spacing(), ++c)
{ {
internalColumn = c; if (pos.x() > (i - itemWidth / 2) &&
break; pos.x() <= (i + itemWidth / 2))
{
internalColumn = c;
break;
}
} }
} }
if (internalColumn == -1) if (internalColumn == -1)
@ -956,13 +970,10 @@ QPair<CategorizedView::Category *, int> CategorizedView::rowDropPos(const QPoint
int internalRow = -1; int internalRow = -1;
{ {
// FIXME rework the drag and drop code // FIXME rework the drag and drop code
const int itemHeight = 0; //itemSize().height();
const int top = categoryTop(category); const int top = categoryTop(category);
for (int i = top + category->headerHeight(), r = 0; for (int r = 0, h = top; r < category->numRows(); h += itemHeightForCategoryRow(category, r), ++r)
i < top + category->totalHeight();
i += itemHeight, ++r)
{ {
if (pos.y() > i && pos.y() < (i + itemHeight)) if (pos.y() > h && pos.y() < (h + itemHeightForCategoryRow(category, r)))
{ {
internalRow = r; internalRow = r;
break; break;
@ -984,11 +995,23 @@ QPair<CategorizedView::Category *, int> CategorizedView::rowDropPos(const QPoint
int categoryRow = internalRow * itemsPerRow() + internalColumn; int categoryRow = internalRow * itemsPerRow() + internalColumn;
// this is used if we're past the last item // this is used if we're past the last item
int numItemsInLastRow = indices.size() % itemsPerRow(); if (categoryRow >= indices.size())
if (internalColumn >= numItemsInLastRow)
{ {
return qMakePair(category, indices.last().row() + 1); return qMakePair(category, indices.last().row() + 1);
} }
return qMakePair(category, indices.at(categoryRow).row()); return qMakePair(category, indices.at(categoryRow).row());
} }
void CategorizedView::invalidateCaches()
{
m_cachedItemWidth = -1;
m_cachedCategoryToIndexMapping.clear();
m_cachedVisualRects.clear();
m_cachedItemSizes.clear();
}
QPoint CategorizedView::offset() const
{
return QPoint(horizontalOffset(), verticalOffset());
}

View File

@ -59,7 +59,7 @@ private:
int totalHeight() const; int totalHeight() const;
int headerHeight() const; int headerHeight() const;
int contentHeight() const; int contentHeight() const;
QSize categoryTotalSize() const; int numRows() const;
}; };
friend struct Category; friend struct Category;
@ -69,6 +69,7 @@ private:
int m_leftMargin; int m_leftMargin;
int m_rightMargin; int m_rightMargin;
int m_bottomMargin;
int m_categoryMargin; int m_categoryMargin;
int m_itemSpacing; int m_itemSpacing;
@ -112,6 +113,7 @@ private:
QPoint m_lastDragPosition; QPoint m_lastDragPosition;
QPair<int, int> categoryInternalPosition(const QModelIndex &index) const; QPair<int, int> categoryInternalPosition(const QModelIndex &index) const;
int itemHeightForCategoryRow(const Category *category, const int internalRow) const;
QPixmap renderToPixmap(const QModelIndexList &indices, QRect *r) const; QPixmap renderToPixmap(const QModelIndexList &indices, QRect *r) const;
QList<QPair<QRect, QModelIndex> > draggablePaintPairs(const QModelIndexList &indices, QRect *r) const; QList<QPair<QRect, QModelIndex> > draggablePaintPairs(const QModelIndexList &indices, QRect *r) const;
@ -119,6 +121,10 @@ private:
bool isDragEventAccepted(QDropEvent *event); bool isDragEventAccepted(QDropEvent *event);
QPair<Category *, int> rowDropPos(const QPoint &pos); QPair<Category *, int> rowDropPos(const QPoint &pos);
void invalidateCaches();
QPoint offset() const;
}; };
#endif // WIDGET_H #endif // WIDGET_H

View File

@ -64,7 +64,7 @@ int main(int argc, char *argv[])
model.setItem(8, createItem(Qt::darkGreen, "Dark Green", "")); model.setItem(8, createItem(Qt::darkGreen, "Dark Green", ""));
model.setItem(9, createItem(Qt::green, "Green", "")); model.setItem(9, createItem(Qt::green, "Green", ""));
for (int i = 0; i < 21; ++i) for (int i = 0; i < 20; ++i)
{ {
model.setItem(i + 10, createItem(i+1, "Items 1-20")); model.setItem(i + 10, createItem(i+1, "Items 1-20"));
} }