From 1e1b2342f48a3dd1eff90229ac4005fb0d45d2ba Mon Sep 17 00:00:00 2001 From: Jan Dalheimer Date: Mon, 30 Dec 2013 18:46:12 +0100 Subject: [PATCH] Loads of fixes --- CategorizedView.cpp | 115 ++++++++++++++++++++++++++------------------ CategorizedView.h | 8 ++- main.cpp | 2 +- 3 files changed, 77 insertions(+), 48 deletions(-) diff --git a/CategorizedView.cpp b/CategorizedView.cpp index bdb0b222..f660e8f3 100644 --- a/CategorizedView.cpp +++ b/CategorizedView.cpp @@ -79,7 +79,6 @@ int CategorizedView::Category::contentHeight() const { return 0; } - const int rows = qMax(1, qCeil((qreal)view->numItemsForCategory(this) / (qreal)view->itemsPerRow())); QMap rowToHeightMapping; foreach (const QModelIndex &index, view->itemsForCategory(this)) { @@ -90,20 +89,23 @@ int CategorizedView::Category::contentHeight() const } } int result = 0; - for (int i = 0; i < rows; ++i) + if (!rowToHeightMapping.isEmpty()) { - Q_ASSERT(rowToHeightMapping.contains(i)); - result += rowToHeightMapping[i]; + for (int i = 0; i < numRows(); ++i) + { + Q_ASSERT(rowToHeightMapping.contains(i)); + result += rowToHeightMapping[i]; + } } 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) - : 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); setMovement(Snap); @@ -168,10 +170,7 @@ void CategorizedView::updateGeometries() { QListView::updateGeometries(); - m_cachedItemWidth = -1; - m_cachedCategoryToIndexMapping.clear(); - m_cachedVisualRects.clear(); - m_cachedItemSizes.clear(); + invalidateCaches(); QMap cats; @@ -213,6 +212,7 @@ void CategorizedView::updateGeometries() } // remove the last margin (we don't want it) totalHeight -= m_categoryMargin; + totalHeight += m_bottomMargin; verticalScrollBar()->setRange(0, totalHeight- height()); } @@ -265,7 +265,7 @@ int CategorizedView::numItemsForCategory(const CategorizedView::Category *catego } QList CategorizedView::itemsForCategory(const CategorizedView::Category *category) const { - if (!m_cachedCategoryToIndexMapping.contains(category)) + if (!m_cachedCategoryToIndexMapping.contains(category) || true) { QList *indices = new QList(); for (int i = 0; i < model()->rowCount(); ++i) @@ -393,26 +393,30 @@ QPair CategorizedView::categoryInternalPosition(const QModelIndex &ind } return qMakePair(x, y); } +int CategorizedView::itemHeightForCategoryRow(const CategorizedView::Category *category, const int internalRow) const +{ + foreach (const QModelIndex &i, itemsForCategory(category)) + { + QPair pos = categoryInternalPosition(i); + if (pos.second == internalRow) + { + return itemSize(i).height(); + } + } + return -1; +} void CategorizedView::mousePressEvent(QMouseEvent *event) { //endCategoryEditor(); - QPoint pos = event->pos(); + QPoint pos = event->pos() + offset(); QPersistentModelIndex index = indexAt(pos); m_pressedIndex = index; m_pressedAlreadySelected = selectionModel()->isSelected(m_pressedIndex); QItemSelectionModel::SelectionFlags command = selectionCommand(index, event); - QPoint offset = QPoint(horizontalOffset(), verticalOffset()); - if (!(command & QItemSelectionModel::Current)) - { - m_pressedPosition = pos + offset; - } - else if (!indexAt(m_pressedPosition - offset).isValid()) - { - m_pressedPosition = visualRect(currentIndex()).center() + offset; - } + m_pressedPosition = pos; m_pressedCategory = categoryAt(m_pressedPosition); if (m_pressedCategory) @@ -430,7 +434,7 @@ void CategorizedView::mousePressEvent(QMouseEvent *event) setAutoScroll(false); selectionModel()->setCurrentIndex(index, QItemSelectionModel::NoUpdate); setAutoScroll(autoScroll); - QRect rect(m_pressedPosition - offset, pos); + QRect rect(m_pressedPosition, pos); if (command.testFlag(QItemSelectionModel::Toggle)) { command &= ~QItemSelectionModel::Toggle; @@ -459,7 +463,7 @@ void CategorizedView::mouseMoveEvent(QMouseEvent *event) if (state() == DraggingState) { - topLeft = m_pressedPosition - QPoint(horizontalOffset(), verticalOffset()); + topLeft = m_pressedPosition - offset(); if ((topLeft - event->pos()).manhattanLength() > QApplication::startDragDistance()) { m_pressedIndex = QModelIndex(); @@ -474,7 +478,7 @@ void CategorizedView::mouseMoveEvent(QMouseEvent *event) if (selectionMode() != SingleSelection) { - topLeft = m_pressedPosition - QPoint(horizontalOffset(), verticalOffset()); + topLeft = m_pressedPosition - offset(); } else { @@ -515,7 +519,7 @@ void CategorizedView::mouseMoveEvent(QMouseEvent *event) } void CategorizedView::mouseReleaseEvent(QMouseEvent *event) { - QPoint pos = event->pos(); + QPoint pos = event->pos() - offset(); QPersistentModelIndex index = indexAt(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) { 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; for (int i = 0; i < m_categories.size(); ++i) @@ -665,7 +671,7 @@ void CategorizedView::dragEnterEvent(QDragEnterEvent *event) { return; } - m_lastDragPosition = event->pos(); + m_lastDragPosition = event->pos() + offset(); viewport()->update(); event->accept(); } @@ -675,7 +681,7 @@ void CategorizedView::dragMoveEvent(QDragMoveEvent *event) { return; } - m_lastDragPosition = event->pos(); + m_lastDragPosition = event->pos() + offset(); viewport()->update(); event->accept(); } @@ -696,7 +702,7 @@ void CategorizedView::dropEvent(QDropEvent *event) return; } - QPair dropPos = rowDropPos(event->pos()); + QPair dropPos = rowDropPos(event->pos() + offset()); const Category *category = dropPos.first; const int row = dropPos.second; @@ -729,7 +735,8 @@ void CategorizedView::startDrag(Qt::DropActions supportedActions) } QRect 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); drag->setPixmap(pixmap); drag->setMimeData(data); @@ -935,15 +942,22 @@ QPair CategorizedView::rowDropPos(const QPoint int internalColumn = -1; { const int itemWidth = this->itemWidth(); - for (int i = 0, c = 0; - i < contentWidth(); - i += itemWidth, ++c) + if (pos.x() >= (itemWidth * itemsPerRow())) { - if (pos.x() > (i - itemWidth / 2) && - pos.x() < (i + itemWidth / 2)) + internalColumn = itemsPerRow(); + } + else + { + for (int i = 0, c = 0; + i < contentWidth(); + i += itemWidth + spacing(), ++c) { - internalColumn = c; - break; + if (pos.x() > (i - itemWidth / 2) && + pos.x() <= (i + itemWidth / 2)) + { + internalColumn = c; + break; + } } } if (internalColumn == -1) @@ -956,13 +970,10 @@ QPair CategorizedView::rowDropPos(const QPoint int internalRow = -1; { // FIXME rework the drag and drop code - const int itemHeight = 0; //itemSize().height(); const int top = categoryTop(category); - for (int i = top + category->headerHeight(), r = 0; - i < top + category->totalHeight(); - i += itemHeight, ++r) + for (int r = 0, h = top; r < category->numRows(); h += itemHeightForCategoryRow(category, r), ++r) { - if (pos.y() > i && pos.y() < (i + itemHeight)) + if (pos.y() > h && pos.y() < (h + itemHeightForCategoryRow(category, r))) { internalRow = r; break; @@ -984,11 +995,23 @@ QPair CategorizedView::rowDropPos(const QPoint int categoryRow = internalRow * itemsPerRow() + internalColumn; // this is used if we're past the last item - int numItemsInLastRow = indices.size() % itemsPerRow(); - if (internalColumn >= numItemsInLastRow) + if (categoryRow >= indices.size()) { return qMakePair(category, indices.last().row() + 1); } 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()); +} diff --git a/CategorizedView.h b/CategorizedView.h index e98e7c5e..8ab9ce87 100644 --- a/CategorizedView.h +++ b/CategorizedView.h @@ -59,7 +59,7 @@ private: int totalHeight() const; int headerHeight() const; int contentHeight() const; - QSize categoryTotalSize() const; + int numRows() const; }; friend struct Category; @@ -69,6 +69,7 @@ private: int m_leftMargin; int m_rightMargin; + int m_bottomMargin; int m_categoryMargin; int m_itemSpacing; @@ -112,6 +113,7 @@ private: QPoint m_lastDragPosition; QPair categoryInternalPosition(const QModelIndex &index) const; + int itemHeightForCategoryRow(const Category *category, const int internalRow) const; QPixmap renderToPixmap(const QModelIndexList &indices, QRect *r) const; QList > draggablePaintPairs(const QModelIndexList &indices, QRect *r) const; @@ -119,6 +121,10 @@ private: bool isDragEventAccepted(QDropEvent *event); QPair rowDropPos(const QPoint &pos); + + void invalidateCaches(); + + QPoint offset() const; }; #endif // WIDGET_H diff --git a/main.cpp b/main.cpp index b164b85d..58d1c9ba 100644 --- a/main.cpp +++ b/main.cpp @@ -64,7 +64,7 @@ int main(int argc, char *argv[]) model.setItem(8, createItem(Qt::darkGreen, "Dark 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")); }