From: Peter Penz Date: Wed, 8 Feb 2012 16:45:22 +0000 (+0100) Subject: Layout optimizations X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/commitdiff_plain/03415d90783979f8e51880b7950721985fee29bf Layout optimizations - Differ internally between margins and paddings - Add a small padding in the icons-view and the compact-views - Optimize the width of the icons-view if previews are shown --- diff --git a/src/kitemviews/kfileitemlistgroupheader.cpp b/src/kitemviews/kfileitemlistgroupheader.cpp index 237a974c2..dd90a838c 100644 --- a/src/kitemviews/kfileitemlistgroupheader.cpp +++ b/src/kitemviews/kfileitemlistgroupheader.cpp @@ -61,7 +61,7 @@ void KFileItemListGroupHeader::resizeEvent(QGraphicsSceneResizeEvent* event) void KFileItemListGroupHeader::updateText() { - const qreal width = size().width() - 4 * styleOption().margin; + const qreal width = size().width() - 4 * styleOption().padding; m_font = font(); // TODO: Most probably the font size will be slightly shrinked in future QFontMetricsF fontMetrics(m_font); diff --git a/src/kitemviews/kfileitemlistview.cpp b/src/kitemviews/kfileitemlistview.cpp index 650ed454f..f8a58ae51 100644 --- a/src/kitemviews/kfileitemlistview.cpp +++ b/src/kitemviews/kfileitemlistview.cpp @@ -129,7 +129,7 @@ QSizeF KFileItemListView::itemSizeHint(int index) const case IconsLayout: { const QString text = KStringHandler::preProcessWrap(values["name"].toString()); - const qreal maxWidth = itemSize().width() - 2 * option.margin; + const qreal maxWidth = itemSize().width() - 2 * option.padding; int textLinesCount = 0; QTextLine line; @@ -152,7 +152,7 @@ QSizeF KFileItemListView::itemSizeHint(int index) const const qreal height = textLinesCount * option.fontMetrics.height() + option.iconSize + - option.margin * 3; + option.padding * 3; return QSizeF(itemSize().width(), height); } @@ -167,14 +167,14 @@ QSizeF KFileItemListView::itemSizeHint(int index) const maximumRequiredWidth = qMax(maximumRequiredWidth, requiredWidth); } - const qreal width = option.margin * 4 + option.iconSize + maximumRequiredWidth; - const qreal height = option.margin * 2 + qMax(option.iconSize, (1 + additionalRolesCount) * option.fontMetrics.height()); + const qreal width = option.padding * 4 + option.iconSize + maximumRequiredWidth; + const qreal height = option.padding * 2 + qMax(option.iconSize, (1 + additionalRolesCount) * option.fontMetrics.height()); return QSizeF(width, height); } case DetailsLayout: { // The width will be determined dynamically by KFileItemListView::visibleRoleSizes() - const qreal height = option.margin * 2 + qMax(option.iconSize, option.fontMetrics.height()); + const qreal height = option.padding * 2 + qMax(option.iconSize, option.fontMetrics.height()); return QSizeF(-1, height); } @@ -504,22 +504,22 @@ QSizeF KFileItemListView::visibleRoleSizeHint(int index, const QByteArray& role) const KItemListStyleOption& option = styleOption(); qreal width = m_minimumRolesWidths.value(role, 0); - const qreal height = option.margin * 2 + option.fontMetrics.height(); + const qreal height = option.padding * 2 + option.fontMetrics.height(); const QHash values = model()->data(index); const QString text = KFileItemListWidget::roleText(role, values); if (!text.isEmpty()) { - const qreal columnMargin = option.margin * 3; - width = qMax(width, qreal(2 * columnMargin + option.fontMetrics.width(text))); + const qreal columnPadding = option.padding * 3; + width = qMax(width, qreal(2 * columnPadding + option.fontMetrics.width(text))); } if (role == "name") { // 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; + width += option.padding + expansionLevel * itemSize().height() + KIconLoader::SizeSmall; // Increase the width by the required space for the icon - width += option.margin * 2 + option.iconSize; + width += option.padding * 2 + option.iconSize; } return QSizeF(width, height); @@ -597,7 +597,7 @@ QSize KFileItemListView::availableIconSize() const const KItemListStyleOption& option = styleOption(); const int iconSize = option.iconSize; if (m_itemLayout == IconsLayout) { - const int maxIconWidth = itemSize().width() - 2 * option.margin; + const int maxIconWidth = itemSize().width() - 2 * option.padding; return QSize(maxIconWidth, iconSize); } diff --git a/src/kitemviews/kfileitemlistwidget.cpp b/src/kitemviews/kfileitemlistwidget.cpp index 7a95846d8..9fdcbec65 100644 --- a/src/kitemviews/kfileitemlistwidget.cpp +++ b/src/kitemviews/kfileitemlistwidget.cpp @@ -128,7 +128,7 @@ void KFileItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsIte // Prevent a possible overlapping of the additional-information texts // with the icon. This can happen if the user has minimized the width // of the name-column to a very small value. - const qreal minX = m_pixmapPos.x() + m_pixmap.width() + 4 * itemListStyleOption.margin; + const qreal minX = m_pixmapPos.x() + m_pixmap.width() + 4 * itemListStyleOption.padding; if (m_textPos[Name + 1].x() < minX) { clipAdditionalInfoBounds = true; painter->save(); @@ -196,13 +196,13 @@ QRectF KFileItemListWidget::selectionToggleRect() const // when trying to hit the toggle. const int widgetHeight = size().height(); const int widgetWidth = size().width(); - const int minMargin = 2; + const int minPadding = 2; - if (toggleSize + minMargin * 2 >= widgetHeight) { + if (toggleSize + minPadding * 2 >= widgetHeight) { toggleSize = widgetHeight; pos.setY(0); } - if (toggleSize + minMargin * 2 >= widgetWidth) { + if (toggleSize + minPadding * 2 >= widgetWidth) { toggleSize = widgetWidth; pos.setX(0); } @@ -432,7 +432,7 @@ void KFileItemListWidget::updateExpansionArea() if (expansionLevel >= 0) { const qreal widgetHeight = size().height(); const qreal expansionLevelSize = KIconLoader::SizeSmall; - const qreal x = option.margin + expansionLevel * widgetHeight; + const qreal x = option.padding + expansionLevel * widgetHeight; const qreal y = (widgetHeight - expansionLevelSize) / 2; m_expansionArea = QRectF(x, y, expansionLevelSize, expansionLevelSize); return; @@ -450,9 +450,9 @@ void KFileItemListWidget::updatePixmapCache() const QSizeF widgetSize = size(); const bool iconOnTop = (m_layout == IconsLayout); const KItemListStyleOption& option = styleOption(); - const qreal margin = option.margin; + const qreal padding = option.padding; - const int maxIconWidth = iconOnTop ? widgetSize.width() - 2 * margin : option.iconSize; + const int maxIconWidth = iconOnTop ? widgetSize.width() - 2 * padding : option.iconSize; const int maxIconHeight = option.iconSize; const QHash values = data(); @@ -514,15 +514,15 @@ void KFileItemListWidget::updatePixmapCache() int scaledIconSize = 0; if (iconOnTop) { - scaledIconSize = static_cast(m_textPos[Name].y() - 2 * margin); + scaledIconSize = static_cast(m_textPos[Name].y() - 2 * padding); } else { const int textRowsCount = (m_layout == CompactLayout) ? visibleRoles().count() : 1; const qreal requiredTextHeight = textRowsCount * option.fontMetrics.height(); scaledIconSize = (requiredTextHeight < maxIconHeight) ? - widgetSize.height() - 2 * margin : maxIconHeight; + widgetSize.height() - 2 * padding : maxIconHeight; } - const int maxScaledIconWidth = iconOnTop ? widgetSize.width() - 2 * margin : scaledIconSize; + const int maxScaledIconWidth = iconOnTop ? widgetSize.width() - 2 * padding : scaledIconSize; const int maxScaledIconHeight = scaledIconSize; m_scaledPixmapSize = m_pixmap.size(); @@ -531,17 +531,17 @@ void KFileItemListWidget::updatePixmapCache() if (iconOnTop) { // Center horizontally and align on bottom within the icon-area m_pixmapPos.setX((widgetSize.width() - m_scaledPixmapSize.width()) / 2); - m_pixmapPos.setY(margin + scaledIconSize - m_scaledPixmapSize.height()); + m_pixmapPos.setY(padding + scaledIconSize - m_scaledPixmapSize.height()); } else { // Center horizontally and vertically within the icon-area - m_pixmapPos.setX(m_textPos[Name].x() - 2 * margin + m_pixmapPos.setX(m_textPos[Name].x() - 2 * padding - (scaledIconSize + m_scaledPixmapSize.width()) / 2); - m_pixmapPos.setY(margin + m_pixmapPos.setY(padding + (scaledIconSize - m_scaledPixmapSize.height()) / 2); } m_iconRect = QRectF(m_pixmapPos, QSizeF(m_scaledPixmapSize)); - m_iconRect.adjust(-margin, -margin, margin, margin); + m_iconRect.adjust(-padding, -padding, padding, padding); // Prepare the pixmap that is used when the item gets hovered if (isHovered()) { @@ -605,8 +605,8 @@ void KFileItemListWidget::updateIconsLayoutTextCache() const QHash values = data(); const KItemListStyleOption& option = styleOption(); - const qreal margin = option.margin; - const qreal maxWidth = size().width() - 2 * margin; + const qreal padding = option.padding; + const qreal maxWidth = size().width() - 2 * padding; const qreal widgetHeight = size().height(); const qreal fontHeight = option.fontMetrics.height(); @@ -635,8 +635,8 @@ void KFileItemListWidget::updateIconsLayoutTextCache() textLinesCount += additionalRolesCount; m_text[Name].setTextWidth(maxWidth); - m_textPos[Name] = QPointF(margin, widgetHeight - textLinesCount * fontHeight - margin); - m_textRect = QRectF(margin + (maxWidth - requiredWidthForName) / 2, + m_textPos[Name] = QPointF(padding, widgetHeight - textLinesCount * fontHeight - padding); + m_textRect = QRectF(padding + (maxWidth - requiredWidthForName) / 2, m_textPos[Name].y(), requiredWidthForName, textLinesCountForName * fontHeight); @@ -665,24 +665,24 @@ void KFileItemListWidget::updateIconsLayoutTextCache() // TODO: QFontMetrics::elidedText() works different regarding the given width // in comparison to QTextLine::setLineWidth(). It might happen that the text does // not get elided although it does not fit into the given width. As workaround - // the margin is substracted. - const QString elidedText = option.fontMetrics.elidedText(text, Qt::ElideRight, maxWidth - margin); + // the padding is substracted. + const QString elidedText = option.fontMetrics.elidedText(text, Qt::ElideRight, maxWidth - padding); m_text[textId].setText(elidedText); } } layout.endLayout(); - m_textPos[textId] = QPointF(margin, y); + m_textPos[textId] = QPointF(padding, y); m_text[textId].setTextWidth(maxWidth); - const QRectF textRect(margin + (maxWidth - requiredWidth) / 2, y, requiredWidth, fontHeight); + const QRectF textRect(padding + (maxWidth - requiredWidth) / 2, y, requiredWidth, fontHeight); m_textRect |= textRect; y += fontHeight; } - // Add a margin to the text rectangle - m_textRect.adjust(-margin, -margin, margin, margin); + // Add a padding to the text rectangle + m_textRect.adjust(-padding, -padding, padding, padding); } void KFileItemListWidget::updateCompactLayoutTextCache() @@ -697,12 +697,12 @@ void KFileItemListWidget::updateCompactLayoutTextCache() const qreal widgetHeight = size().height(); const qreal fontHeight = option.fontMetrics.height(); const qreal textLinesHeight = qMax(visibleRoles().count(), 1) * fontHeight; - const int scaledIconSize = (textLinesHeight < option.iconSize) ? widgetHeight - 2 * option.margin : option.iconSize; + const int scaledIconSize = (textLinesHeight < option.iconSize) ? widgetHeight - 2 * option.padding : option.iconSize; qreal maximumRequiredTextWidth = 0; - const qreal x = option.margin * 3 + scaledIconSize; + const qreal x = option.padding * 3 + scaledIconSize; qreal y = (widgetHeight - textLinesHeight) / 2; - const qreal maxWidth = size().width() - x - option.margin; + const qreal maxWidth = size().width() - x - option.padding; foreach (const QByteArray& role, m_sortedVisibleRoles) { const TextId textId = roleTextId(role); @@ -724,7 +724,7 @@ void KFileItemListWidget::updateCompactLayoutTextCache() y += fontHeight; } - m_textRect = QRectF(x - option.margin, 0, maximumRequiredTextWidth + 2 * option.margin, widgetHeight); + m_textRect = QRectF(x - option.padding, 0, maximumRequiredTextWidth + 2 * option.padding, widgetHeight); } void KFileItemListWidget::updateDetailsLayoutTextCache() @@ -741,13 +741,13 @@ void KFileItemListWidget::updateDetailsLayoutTextCache() const QHash values = data(); const qreal widgetHeight = size().height(); - const int scaledIconSize = widgetHeight - 2 * option.margin; + const int scaledIconSize = widgetHeight - 2 * option.padding; const int fontHeight = option.fontMetrics.height(); - const qreal columnMargin = option.margin * 3; - const qreal firstColumnInc = m_expansionArea.right() + option.margin * 2 + scaledIconSize; + const qreal columnPadding = option.padding * 3; + const qreal firstColumnInc = m_expansionArea.right() + option.padding * 2 + scaledIconSize; qreal x = firstColumnInc; - const qreal y = qMax(qreal(option.margin), (widgetHeight - fontHeight) / 2); + const qreal y = qMax(qreal(option.padding), (widgetHeight - fontHeight) / 2); foreach (const QByteArray& role, m_sortedVisibleRoles) { const TextId textId = roleTextId(role); @@ -757,7 +757,7 @@ void KFileItemListWidget::updateDetailsLayoutTextCache() // Elide the text in case it does not fit into the available column-width qreal requiredWidth = option.fontMetrics.width(text); const qreal columnWidth = visibleRolesSizes().value(role, QSizeF(0, 0)).width(); - qreal availableTextWidth = columnWidth - 2 * columnMargin; + qreal availableTextWidth = columnWidth - 2 * columnPadding; if (textId == Name) { availableTextWidth -= firstColumnInc; } @@ -768,13 +768,13 @@ void KFileItemListWidget::updateDetailsLayoutTextCache() } m_text[textId].setText(text); - m_textPos[textId] = QPointF(x + columnMargin, y); + m_textPos[textId] = QPointF(x + columnPadding, y); x += columnWidth; switch (textId) { case Name: { - m_textRect = QRectF(m_textPos[textId].x() - option.margin, 0, - requiredWidth + 2 * option.margin, size().height()); + m_textRect = QRectF(m_textPos[textId].x() - option.padding, 0, + requiredWidth + 2 * option.padding, 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 @@ -783,7 +783,7 @@ void KFileItemListWidget::updateDetailsLayoutTextCache() } case Size: // The values for the size should be right aligned - m_textPos[textId].rx() += columnWidth - requiredWidth - 2 * columnMargin; + m_textPos[textId].rx() += columnWidth - requiredWidth - 2 * columnPadding; break; default: diff --git a/src/kitemviews/kitemlistgroupheader.cpp b/src/kitemviews/kitemlistgroupheader.cpp index 8eff39901..03964e2b5 100644 --- a/src/kitemviews/kitemlistgroupheader.cpp +++ b/src/kitemviews/kitemlistgroupheader.cpp @@ -116,7 +116,7 @@ void KItemListGroupHeader::paint(QPainter* painter, const QStyleOptionGraphicsIt if (m_scrollOrientation != Qt::Horizontal) { painter->setPen(m_roleColor); - const qreal y = m_roleBounds.y() - m_styleOption.margin; + const qreal y = m_roleBounds.y() - m_styleOption.padding; painter->drawLine(0, y, size().width() - 1, y); } } @@ -177,13 +177,13 @@ void KItemListGroupHeader::updateCache() (c1.green() * p1 + c2.green() * p2) / 100, (c1.blue() * p1 + c2.blue() * p2) / 100); - const int margin = m_styleOption.margin; + const int padding = m_styleOption.padding; const QFontMetrics fontMetrics(m_styleOption.font); const qreal roleHeight = fontMetrics.height(); - m_roleBounds = QRectF(margin, - size().height() - roleHeight - margin, - size().width() - 2 * margin, + m_roleBounds = QRectF(padding, + size().height() - roleHeight - padding, + size().width() - 2 * padding, roleHeight); m_dirtyCache = false; diff --git a/src/kitemviews/kitemliststyleoption.cpp b/src/kitemviews/kitemliststyleoption.cpp index 83af31202..5266ef6bd 100644 --- a/src/kitemviews/kitemliststyleoption.cpp +++ b/src/kitemviews/kitemliststyleoption.cpp @@ -26,7 +26,9 @@ KItemListStyleOption::KItemListStyleOption() : font(), fontMetrics(QFont()), palette(), - margin(0), + padding(0), + horizontalMargin(0), + verticalMargin(0), iconSize(KIconLoader::SizeMedium) { } @@ -36,7 +38,9 @@ KItemListStyleOption::KItemListStyleOption(const KItemListStyleOption& other) : font(other.font), fontMetrics(other.fontMetrics), palette(other.palette), - margin(other.margin), + padding(other.padding), + horizontalMargin(other.horizontalMargin), + verticalMargin(other.verticalMargin), iconSize(other.iconSize) { } diff --git a/src/kitemviews/kitemliststyleoption.h b/src/kitemviews/kitemliststyleoption.h index bafb81d3a..9284dc61b 100644 --- a/src/kitemviews/kitemliststyleoption.h +++ b/src/kitemviews/kitemliststyleoption.h @@ -38,7 +38,9 @@ public: QFont font; QFontMetrics fontMetrics; QPalette palette; - int margin; + int padding; + int horizontalMargin; + int verticalMargin; int iconSize; }; #endif diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp index a2252b918..451e51833 100644 --- a/src/kitemviews/kitemlistview.cpp +++ b/src/kitemviews/kitemlistview.cpp @@ -151,7 +151,9 @@ void KItemListView::setItemSize(const QSizeF& itemSize) // Skip animations when the number of rows or columns // are changed in the grid layout. Although the animation // engine can handle this usecase, it looks obtrusive. - const bool animate = !changesItemGridLayout(m_layouter->size(), itemSize); + const bool animate = !changesItemGridLayout(m_layouter->size(), + itemSize, + m_layouter->itemMargin()); m_itemSize = itemSize; @@ -334,6 +336,18 @@ void KItemListView::setStyleOption(const KItemListStyleOption& option) const KItemListStyleOption previousOption = m_styleOption; m_styleOption = option; + bool animate = true; + const QSizeF margin(option.horizontalMargin, option.verticalMargin); + if (margin != m_layouter->itemMargin()) { + // Skip animations when the number of rows or columns + // are changed in the grid layout. Although the animation + // engine can handle this usecase, it looks obtrusive. + animate = !changesItemGridLayout(m_layouter->size(), + m_layouter->itemSize(), + margin); + m_layouter->setItemMargin(margin); + } + if (m_grouped) { updateGroupHeaderHeight(); } @@ -345,7 +359,7 @@ void KItemListView::setStyleOption(const KItemListStyleOption& option) } m_sizeHintResolver->clearCache(); - doLayout(Animation); + doLayout(animate ? Animation : NoAnimation); onStyleOptionChanged(option, previousOption); } @@ -399,7 +413,9 @@ void KItemListView::setGeometry(const QRectF& rect) m_layouter->setSize(newSize); doLayout(Animation); } else { - const bool animate = !changesItemGridLayout(newSize, m_layouter->itemSize()); + const bool animate = !changesItemGridLayout(newSize, + m_layouter->itemSize(), + m_layouter->itemMargin()); m_layouter->setSize(newSize); if (animate) { @@ -1494,8 +1510,9 @@ bool KItemListView::moveWidget(KItemListWidget* widget,const QRectF& itemBounds) // one row in the vertical scroll-orientation or one column in the horizontal scroll-orientation. // Otherwise instead of a moving-animation a create-animation on the new position will be used // instead. This is done to prevent overlapping (and confusing) moving-animations. - const qreal xMax = m_itemSize.width(); - const qreal yMax = m_itemSize.height(); + const QSizeF itemMargin = m_layouter->itemMargin(); + const qreal xMax = m_itemSize.width() + itemMargin.width(); + const qreal yMax = m_itemSize.height() + itemMargin.height(); qreal xDiff = qAbs(oldPos.x() - newPos.x()); qreal yDiff = qAbs(oldPos.y() - newPos.y()); if (scrollOrientation() == Qt::Vertical) { @@ -1850,7 +1867,9 @@ QRectF KItemListView::headerBoundaries() const return m_header ? m_header->geometry() : QRectF(); } -bool KItemListView::changesItemGridLayout(const QSizeF& newGridSize, const QSizeF& newItemSize) const +bool KItemListView::changesItemGridLayout(const QSizeF& newGridSize, + const QSizeF& newItemSize, + const QSizeF& newItemMargin) const { if (newItemSize.isEmpty() || newGridSize.isEmpty()) { return false; @@ -1859,18 +1878,26 @@ bool KItemListView::changesItemGridLayout(const QSizeF& newGridSize, const QSize if (m_layouter->scrollOrientation() == Qt::Vertical) { const qreal itemWidth = m_layouter->itemSize().width(); if (itemWidth > 0) { - const int newColumnCount = newGridSize.width() / newItemSize.width(); + const int newColumnCount = itemsPerSize(newGridSize.width(), + newItemSize.width(), + newItemMargin.width()); if (m_model->count() > newColumnCount) { - const int oldColumnCount = m_layouter->size().width() / itemWidth; + const int oldColumnCount = itemsPerSize(m_layouter->size().width(), + itemWidth, + m_layouter->itemMargin().width()); return oldColumnCount != newColumnCount; } } } else { const qreal itemHeight = m_layouter->itemSize().height(); if (itemHeight > 0) { - const int newRowCount = newGridSize.height() / newItemSize.height(); + const int newRowCount = itemsPerSize(newGridSize.height(), + newItemSize.height(), + newItemMargin.height()); if (m_model->count() > newRowCount) { - const int oldRowCount = m_layouter->size().height() / itemHeight; + const int oldRowCount = itemsPerSize(m_layouter->size().height(), + itemHeight, + m_layouter->itemMargin().height()); return oldRowCount != newRowCount; } } @@ -1909,7 +1936,7 @@ void KItemListView::updateGroupHeaderHeight() { qreal groupHeaderHeight = m_styleOption.fontMetrics.height(); groupHeaderHeight += (scrollOrientation() == Qt::Vertical) - ? m_styleOption.margin * 4 : m_styleOption.margin * 2; + ? m_styleOption.padding * 4 : m_styleOption.padding * 2; m_layouter->setGroupHeaderHeight(groupHeaderHeight); updateVisibleGroupHeaders(); @@ -1941,6 +1968,13 @@ int KItemListView::calculateAutoScrollingIncrement(int pos, int range, int oldIn return inc; } +int KItemListView::itemsPerSize(qreal size, qreal itemSize, qreal itemMargin) +{ + const qreal availableSize = size - itemMargin; + const int count = availableSize / (itemSize + itemMargin); + return count; +} + KItemListCreatorBase::~KItemListCreatorBase() diff --git a/src/kitemviews/kitemlistview.h b/src/kitemviews/kitemlistview.h index 50d8908e5..808ff5b3e 100644 --- a/src/kitemviews/kitemlistview.h +++ b/src/kitemviews/kitemlistview.h @@ -463,7 +463,9 @@ private: * the new grid- and item-size. Used to determine whether an animation * should be done when applying the new layout. */ - bool changesItemGridLayout(const QSizeF& newGridSize, const QSizeF& newItemSize) const; + bool changesItemGridLayout(const QSizeF& newGridSize, + const QSizeF& newItemSize, + const QSizeF& newItemMargin) const; /** * @param changedItemCount Number of inserted or removed items. @@ -497,6 +499,13 @@ private: * value != 0 will be returned. */ static int calculateAutoScrollingIncrement(int pos, int range, int oldInc); + + /** + * Helper functions for changesItemCount(). + * @return The number of items that fit into the available size by + * respecting the size of the item and the margin between the items. + */ + static int itemsPerSize(qreal size, qreal itemSize, qreal itemMargin); private: bool m_enabledSelectionToggles; diff --git a/src/kitemviews/kitemlistviewlayouter.cpp b/src/kitemviews/kitemlistviewlayouter.cpp index e30c9aa42..30dd10346 100644 --- a/src/kitemviews/kitemlistviewlayouter.cpp +++ b/src/kitemviews/kitemlistviewlayouter.cpp @@ -33,6 +33,7 @@ KItemListViewLayouter::KItemListViewLayouter(QObject* parent) : m_scrollOrientation(Qt::Vertical), m_size(), m_itemSize(128, 128), + m_itemMargin(), m_headerHeight(0), m_model(0), m_sizeHintResolver(0), @@ -94,6 +95,19 @@ QSizeF KItemListViewLayouter::itemSize() const return m_itemSize; } +void KItemListViewLayouter::setItemMargin(const QSizeF& margin) +{ + if (m_itemMargin != margin) { + m_itemMargin = margin; + m_dirty = true; + } +} + +QSizeF KItemListViewLayouter::itemMargin() const +{ + return m_itemMargin; +} + void KItemListViewLayouter::setHeaderHeight(qreal height) { if (m_headerHeight != height) { @@ -276,6 +290,7 @@ void KItemListViewLayouter::doLayout() m_visibleIndexesDirty = true; QSizeF itemSize = m_itemSize; + QSizeF itemMargin = m_itemMargin; QSizeF size = m_size; const bool grouped = createGroupHeaders(); @@ -286,6 +301,8 @@ void KItemListViewLayouter::doLayout() // a vertical scrolling itemSize.setWidth(m_itemSize.height()); itemSize.setHeight(m_itemSize.width()); + itemMargin.setWidth(m_itemMargin.height()); + itemMargin.setHeight(m_itemMargin.width()); size.setWidth(m_size.height()); size.setHeight(m_size.width()); @@ -297,9 +314,10 @@ void KItemListViewLayouter::doLayout() } } - m_columnWidth = itemSize.width(); - m_columnCount = qMax(1, int(size.width() / m_columnWidth)); - m_xPosInc = 0; + m_columnWidth = itemSize.width() + itemMargin.width(); + const qreal widthForColumns = size.width() - itemMargin.width(); + m_columnCount = qMax(1, int(widthForColumns / m_columnWidth)); + m_xPosInc = itemMargin.width(); const int itemCount = m_model->count(); if (itemCount > m_columnCount) { @@ -319,7 +337,7 @@ void KItemListViewLayouter::doLayout() m_itemRects.reserve(itemCount); - qreal y = m_headerHeight; + qreal y = m_headerHeight + itemMargin.height(); int rowIndex = 0; int index = 0; @@ -393,12 +411,12 @@ void KItemListViewLayouter::doLayout() } } - y += maxItemHeight; + y += maxItemHeight + itemMargin.height(); ++rowIndex; } if (m_itemRects.count() > itemCount) { m_itemRects.erase(m_itemRects.begin() + itemCount, - m_itemRects.end()); + m_itemRects.end()); } if (itemCount > 0) { diff --git a/src/kitemviews/kitemlistviewlayouter_p.h b/src/kitemviews/kitemlistviewlayouter_p.h index 25f8eb6cd..af8a6dacb 100644 --- a/src/kitemviews/kitemlistviewlayouter_p.h +++ b/src/kitemviews/kitemlistviewlayouter_p.h @@ -47,6 +47,12 @@ public: void setItemSize(const QSizeF& size); QSizeF itemSize() const; + /** + * Margin between the rows and columns of items. + */ + void setItemMargin(const QSizeF& margin); + QSizeF itemMargin() const; + /** * Sets the height of the header that is always aligned * at the top. A height of <= 0.0 means that no header is @@ -61,8 +67,7 @@ public: */ void setGroupHeaderHeight(qreal height); qreal groupHeaderHeight() const; - - // TODO: add note that offset can be < 0 or > maximumOffset! + void setScrollOffset(qreal scrollOffset); qreal scrollOffset() const; @@ -138,7 +143,8 @@ private: QSizeF m_size; QSizeF m_itemSize; - qreal m_headerHeight; + QSizeF m_itemMargin; + qreal m_headerHeight; const KItemModelBase* m_model; const KItemListSizeHintResolver* m_sizeHintResolver; diff --git a/src/panels/folders/folderspanel.cpp b/src/panels/folders/folderspanel.cpp index 1a5e9c62d..cc7c75f96 100644 --- a/src/panels/folders/folderspanel.cpp +++ b/src/panels/folders/folderspanel.cpp @@ -144,12 +144,12 @@ void FoldersPanel::showEvent(QShowEvent* event) view->setWidgetCreator(new KItemListWidgetCreator()); KItemListStyleOption styleOption = view->styleOption(); - styleOption.margin = 2; + styleOption.padding = 2; styleOption.iconSize = KIconLoader::SizeSmall; view->setStyleOption(styleOption); const qreal itemHeight = qMax(int(KIconLoader::SizeSmall), styleOption.fontMetrics.height()); - view->setItemSize(QSizeF(-1, itemHeight + 2 * styleOption.margin)); + view->setItemSize(QSizeF(-1, itemHeight + 2 * styleOption.padding)); view->setItemLayout(KFileItemListView::DetailsLayout); // Set the opacity to 0 initially. The opacity will be increased after the loading of the initial tree // has been finished in slotLoadingCompleted(). This prevents an unnecessary animation-mess when diff --git a/src/views/dolphinitemlistcontainer.cpp b/src/views/dolphinitemlistcontainer.cpp index 65f69d963..544892674 100644 --- a/src/views/dolphinitemlistcontainer.cpp +++ b/src/views/dolphinitemlistcontainer.cpp @@ -206,7 +206,9 @@ void DolphinItemListContainer::updateGridSize() m_zoomLevel = ZoomLevelInfo::zoomLevelForIconSize(QSize(iconSize, iconSize)); KItemListStyleOption styleOption = m_fileItemListView->styleOption(); - const int innerMargin = (iconSize >= KIconLoader::SizeSmallMedium) ? 4 : 2; + const int padding = (iconSize >= KIconLoader::SizeSmallMedium) ? 4 : 2; + int horizontalMargin = 0; + int verticalMargin = 0; // Calculate the item-width and item-height int itemWidth; @@ -215,21 +217,35 @@ void DolphinItemListContainer::updateGridSize() case KFileItemListView::IconsLayout: { const int minItemWidth = 64; itemWidth = minItemWidth + IconsModeSettings::textWidthIndex() * 64; - if (itemWidth < iconSize + innerMargin * 2) { - itemWidth = iconSize + innerMargin * 2; + + if (previewsShown()) { + // Optimize the width for previews with a 3:2 aspect ratio instead + // of a 1:1 ratio to avoid wasting too much vertical space when + // photos. + const int minWidth = iconSize * 3 / 2; + itemWidth = qMax(itemWidth, minWidth); } - itemHeight = innerMargin * 3 + iconSize + styleOption.fontMetrics.height(); + + if (itemWidth < iconSize + padding * 2) { + itemWidth = iconSize + padding * 2; + } + itemHeight = padding * 3 + iconSize + styleOption.fontMetrics.height(); + + horizontalMargin = padding * 2; + verticalMargin = horizontalMargin; break; } case KFileItemListView::CompactLayout: { - itemWidth = innerMargin * 4 + iconSize + styleOption.fontMetrics.height() * 5; + itemWidth = padding * 4 + iconSize + styleOption.fontMetrics.height() * 5; const int textLinesCount = m_fileItemListView->visibleRoles().count(); - itemHeight = innerMargin * 2 + qMax(iconSize, textLinesCount * styleOption.fontMetrics.height()); + itemHeight = padding * 2 + qMax(iconSize, textLinesCount * styleOption.fontMetrics.height()); + + horizontalMargin = padding * 2; break; } case KFileItemListView::DetailsLayout: { itemWidth = -1; - itemHeight = innerMargin * 2 + qMax(iconSize, styleOption.fontMetrics.height()); + itemHeight = padding * 2 + qMax(iconSize, styleOption.fontMetrics.height()); break; } default: @@ -240,7 +256,9 @@ void DolphinItemListContainer::updateGridSize() } // Apply the calculated values - styleOption.margin = innerMargin; + styleOption.padding = padding; + styleOption.horizontalMargin = horizontalMargin; + styleOption.verticalMargin = verticalMargin; styleOption.iconSize = iconSize; m_fileItemListView->beginTransaction(); m_fileItemListView->setStyleOption(styleOption);