From: Peter Penz Date: Fri, 23 Sep 2011 17:09:01 +0000 (+0200) Subject: Allow resizing of columns by the user X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/commitdiff_plain/56852cff392f33ee731129fd9a755544d817e590?ds=inline Allow resizing of columns by the user Still open: - Column content is not clipped correctly - First column is not automatically increased to the available width like in Dolphin 1.7 --- diff --git a/src/kitemviews/kfileitemlistview.cpp b/src/kitemviews/kfileitemlistview.cpp index c1d98c810..6ff83b793 100644 --- a/src/kitemviews/kfileitemlistview.cpp +++ b/src/kitemviews/kfileitemlistview.cpp @@ -396,7 +396,20 @@ QSizeF KFileItemListView::visibleRoleSizeHint(int index, const QByteArray& role) const QVariant value = model()->data(index).value(role); const QString text = value.toString(); if (!text.isEmpty()) { - width = qMax(width, qreal(option.margin * 2 + option.fontMetrics.width(text))); + const qreal columnMargin = option.margin * 3; + width = qMax(width, qreal(2 * columnMargin + option.fontMetrics.width(text))); + } + + if (role == "name") { + const QHash values = model()->data(index); + Q_ASSERT(values.contains("expansionLevel")); + + // Increase the width by the expansion-toggle and the current expansion level + const int expansionLevel = values.value("expansionLevel", 0).toInt(); + width += option.margin + expansionLevel * itemSize().height() + KIconLoader::SizeSmall; + + // Increase the width by the required space for the icon + width += option.margin * 2 + option.iconSize; } return QSizeF(width, height); diff --git a/src/kitemviews/kfileitemlistwidget.cpp b/src/kitemviews/kfileitemlistwidget.cpp index a9193fbc7..49c5db5fd 100644 --- a/src/kitemviews/kfileitemlistwidget.cpp +++ b/src/kitemviews/kfileitemlistwidget.cpp @@ -578,7 +578,9 @@ void KFileItemListWidget::updateDetailsLayoutTextCache() const int scaledIconSize = widgetHeight - 2 * option.margin; const int fontHeight = option.fontMetrics.height(); - qreal x = m_expansionArea.right() + option.margin * 3 + scaledIconSize; + const qreal columnMargin = option.margin * 3; + const qreal firstColumnInc = m_expansionArea.right() + option.margin * 2 + scaledIconSize; + qreal x = firstColumnInc; const qreal y = qMax(qreal(option.margin), (widgetHeight - fontHeight) / 2); foreach (const QByteArray& role, m_sortedVisibleRoles) { @@ -588,7 +590,7 @@ void KFileItemListWidget::updateDetailsLayoutTextCache() m_text[textId].setText(text); const qreal requiredWidth = option.fontMetrics.width(text); - m_textPos[textId] = QPointF(x, y); + m_textPos[textId] = QPointF(x + columnMargin, y); const qreal columnWidth = visibleRolesSizes().value(role, QSizeF(0, 0)).width(); x += columnWidth; @@ -596,16 +598,16 @@ void KFileItemListWidget::updateDetailsLayoutTextCache() switch (textId) { case Name: { m_textBoundingRect = QRectF(m_textPos[textId].x() - option.margin, 0, - requiredWidth + 2 * option.margin, size().height()); + requiredWidth + 2 * option.margin, size().height()); // The column after the name should always be aligned on the same x-position independent // from the expansion-level shown in the name column - x -= m_expansionArea.right(); + x -= firstColumnInc; break; } case Size: // The values for the size should be right aligned - m_textPos[textId].rx() += columnWidth - requiredWidth - 2 * option.margin; + m_textPos[textId].rx() += columnWidth - requiredWidth - 2 * columnMargin; break; default: diff --git a/src/kitemviews/kitemlistheader.cpp b/src/kitemviews/kitemlistheader.cpp index c0b48c1a0..09b9bf08f 100644 --- a/src/kitemviews/kitemlistheader.cpp +++ b/src/kitemviews/kitemlistheader.cpp @@ -186,12 +186,15 @@ void KItemListHeader::mouseMoveEvent(QGraphicsSceneMouseEvent* event) if (m_roleOperation == ResizeRoleOperation) { const QByteArray pressedRole = m_visibleRoles.at(m_pressedRoleIndex); - qreal roleWidth = m_visibleRolesWidths.value(pressedRole); - roleWidth += event->pos().x() - event->lastPos().x(); - roleWidth = qMax(minimumRoleWidth(), roleWidth); + qreal previousWidth = m_visibleRolesWidths.value(pressedRole); + qreal currentWidth = previousWidth; + currentWidth += event->pos().x() - event->lastPos().x(); + currentWidth = qMax(minimumRoleWidth(), currentWidth); - m_visibleRolesWidths.insert(pressedRole, roleWidth); + m_visibleRolesWidths.insert(pressedRole, currentWidth); update(); + + emit visibleRoleWidthChanged(pressedRole, currentWidth, previousWidth); } else if ((event->pos() - m_pressedMousePos).manhattanLength() >= QApplication::startDragDistance()) { kDebug() << "Moving of role not supported yet"; m_roleOperation = MoveRoleOperation; diff --git a/src/kitemviews/kitemlistheader_p.h b/src/kitemviews/kitemlistheader_p.h index 79b988464..43b7db59a 100644 --- a/src/kitemviews/kitemlistheader_p.h +++ b/src/kitemviews/kitemlistheader_p.h @@ -49,6 +49,15 @@ public: virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0); +signals: + /** + * Is emitted if the width of a visible role has been adjusted by the user with the mouse + * (no signal is emitted if KItemListHeader::setVisibleRoles() is invoked). + */ + void visibleRoleWidthChanged(const QByteArray& role, + qreal currentWidth, + qreal previousWidth); + protected: virtual void mousePressEvent(QGraphicsSceneMouseEvent* event); virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent* event); diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp index dd2915b8e..ef429e544 100644 --- a/src/kitemviews/kitemlistview.cpp +++ b/src/kitemviews/kitemlistview.cpp @@ -76,7 +76,8 @@ KItemListView::KItemListView(QGraphicsWidget* parent) : m_mousePos(), m_autoScrollIncrement(0), m_autoScrollTimer(0), - m_header(0) + m_header(0), + m_useHeaderWidths(false) { setAcceptHoverEvents(true); @@ -239,11 +240,18 @@ void KItemListView::setHeaderShown(bool show) m_header->setVisibleRoles(m_visibleRoles); m_header->setVisibleRolesWidths(headerRolesWidths()); m_header->setZValue(1); + + m_useHeaderWidths = false; updateHeaderWidth(); + + connect(m_header, SIGNAL(visibleRoleWidthChanged(QByteArray,qreal,qreal)), + this, SLOT(slotVisibleRoleWidthChanged(QByteArray,qreal,qreal))); + m_layouter->setHeaderHeight(m_header->size().height()); } else if (!show && m_header) { delete m_header; m_header = 0; + m_useHeaderWidths = false; m_layouter->setHeaderHeight(0); } } @@ -572,7 +580,9 @@ void KItemListView::resizeEvent(QGraphicsSceneResizeEvent* event) void KItemListView::slotItemsInserted(const KItemRangeList& itemRanges) { - markVisibleRolesSizesAsDirty(); + if (!m_useHeaderWidths) { + markVisibleRolesSizesAsDirty(); + } const bool hasMultipleRanges = (itemRanges.count() > 1); if (hasMultipleRanges) { @@ -645,7 +655,9 @@ void KItemListView::slotItemsInserted(const KItemRangeList& itemRanges) void KItemListView::slotItemsRemoved(const KItemRangeList& itemRanges) { - markVisibleRolesSizesAsDirty(); + if (!m_useHeaderWidths) { + markVisibleRolesSizesAsDirty(); + } const bool hasMultipleRanges = (itemRanges.count() > 1); if (hasMultipleRanges) { @@ -867,6 +879,25 @@ void KItemListView::slotRubberBandActivationChanged(bool active) update(); } +void KItemListView::slotVisibleRoleWidthChanged(const QByteArray& role, + qreal currentWidth, + qreal previousWidth) +{ + Q_UNUSED(previousWidth); + Q_ASSERT(m_header); + + m_useHeaderWidths = true; + + if (m_visibleRolesSizes.contains(role)) { + QSizeF roleSize = m_visibleRolesSizes.value(role); + roleSize.setWidth(currentWidth); + m_visibleRolesSizes.insert(role, roleSize); + } + + m_layouter->setItemSize(QSizeF()); // Forces an update in applyDynamicItemSize() + updateLayout(); +} + void KItemListView::triggerAutoScrolling() { if (!m_autoScrollTimer) { @@ -1267,6 +1298,7 @@ bool KItemListView::markVisibleRolesSizesAsDirty() if (dirty) { m_visibleRolesSizes.clear(); m_layouter->setItemSize(QSizeF()); + m_useHeaderWidths = false; } return dirty; } @@ -1279,16 +1311,14 @@ void KItemListView::applyDynamicItemSize() if (m_visibleRolesSizes.isEmpty()) { m_visibleRolesSizes = visibleRoleSizes(); - foreach (KItemListWidget* widget, visibleItemListWidgets()) { - widget->setVisibleRolesSizes(m_visibleRolesSizes); - } - if (m_header) { m_header->setVisibleRolesWidths(headerRolesWidths()); } } if (m_layouter->itemSize().isEmpty()) { + // Calculate the maximum size of an item by considering the + // visible role sizes and apply them to the layouter. qreal requiredWidth = 0; qreal requiredHeight = 0; @@ -1309,6 +1339,11 @@ void KItemListView::applyDynamicItemSize() } m_layouter->setItemSize(dynamicItemSize); + + // Update the role sizes for all visible widgets + foreach (KItemListWidget* widget, visibleItemListWidgets()) { + widget->setVisibleRolesSizes(m_visibleRolesSizes); + } } } diff --git a/src/kitemviews/kitemlistview.h b/src/kitemviews/kitemlistview.h index da02e0bc2..b088ea487 100644 --- a/src/kitemviews/kitemlistview.h +++ b/src/kitemviews/kitemlistview.h @@ -147,6 +147,12 @@ public: int lastVisibleIndex() const; virtual QSizeF itemSizeHint(int index) const; + + /** + * @return The size of each visible role in case if KItemListView::itemSize() + * is empty. This allows to have dynamic but equal role sizes between + * all items. Per default an empty hash is returned. + */ virtual QHash visibleRoleSizes() const; /** @@ -228,6 +234,16 @@ private slots: void slotRubberBandPosChanged(); void slotRubberBandActivationChanged(bool active); + /** + * Is invoked if the visible role-width of one role in the header has + * been changed by the user. It is remembered that the user has modified + * the role-width, so that it won't be changed anymore automatically to + * calculate an optimized width. + */ + void slotVisibleRoleWidthChanged(const QByteArray& role, + qreal currentWidth, + qreal previousWidth); + /** * Triggers the autoscrolling if autoScroll() is enabled by checking the * current mouse position. If the mouse position is within the autoscroll @@ -354,6 +370,7 @@ private: QTimer* m_autoScrollTimer; KItemListHeader* m_header; + bool m_useHeaderWidths; friend class KItemListController; };