From: Peter Penz Date: Sat, 4 Feb 2012 21:14:53 +0000 (+0100) Subject: Icons view: Layout optimizations X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/commitdiff_plain/72af3125a824722d9875d202dd156cd3f7d8fc46 Icons view: Layout optimizations - Assure that landscape-previews use the whole available width of the icon-area instead of only using the square width. This waste of space occured if the text-width was larger than the icon-width. - Only use one margin instead of two between the icons and the text to improve the visual appearance (thanks to Martin Zilz for the hint) BUG: 293268 FIXED-IN: 4.8.1 CCMAIL: martin@kreativkonzentrat.de --- diff --git a/src/kitemviews/kfileitemlistview.cpp b/src/kitemviews/kfileitemlistview.cpp index 4762e8089..650ed454f 100644 --- a/src/kitemviews/kfileitemlistview.cpp +++ b/src/kitemviews/kfileitemlistview.cpp @@ -152,7 +152,7 @@ QSizeF KFileItemListView::itemSizeHint(int index) const const qreal height = textLinesCount * option.fontMetrics.height() + option.iconSize + - option.margin * 4; + option.margin * 3; return QSizeF(itemSize().width(), height); } @@ -347,8 +347,7 @@ void KFileItemListView::onModelChanged(KItemModelBase* current, KItemModelBase* delete m_modelRolesUpdater; m_modelRolesUpdater = new KFileItemModelRolesUpdater(static_cast(current), this); - const int size = styleOption().iconSize; - m_modelRolesUpdater->setIconSize(QSize(size, size)); + m_modelRolesUpdater->setIconSize(availableIconSize()); applyRolesToModel(); } @@ -462,8 +461,7 @@ void KFileItemListView::updateVisibleIndexRange() // of the icon-size before unpausing m_modelRolesUpdater. This prevents // an unnecessary expensive recreation of all previews afterwards. m_updateIconSizeTimer->stop(); - const KItemListStyleOption& option = styleOption(); - m_modelRolesUpdater->setIconSize(QSize(option.iconSize, option.iconSize)); + m_modelRolesUpdater->setIconSize(availableIconSize()); } m_modelRolesUpdater->setPaused(isTransactionActive()); @@ -485,8 +483,7 @@ void KFileItemListView::updateIconSize() return; } - const KItemListStyleOption& option = styleOption(); - m_modelRolesUpdater->setIconSize(QSize(option.iconSize, option.iconSize)); + m_modelRolesUpdater->setIconSize(availableIconSize()); if (m_updateVisibleIndexRangeTimer->isActive()) { // If the visibility-index-range update is pending do an immediate update @@ -595,4 +592,16 @@ void KFileItemListView::applyRolesToModel() m_modelRolesUpdater->setRoles(roles); } +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; + return QSize(maxIconWidth, iconSize); + } + + return QSize(iconSize, iconSize); +} + #include "kfileitemlistview.moc" diff --git a/src/kitemviews/kfileitemlistview.h b/src/kitemviews/kfileitemlistview.h index 203fb78c4..ea8477858 100644 --- a/src/kitemviews/kfileitemlistview.h +++ b/src/kitemviews/kfileitemlistview.h @@ -124,6 +124,13 @@ private: */ void applyRolesToModel(); + /** + * @return Size that is available for the icons. The size might be larger than specified by + * KItemListStyleOption::iconSize: With the IconsLayout also the empty left area left + * and right of an icon will be included. + */ + QSize availableIconSize() const; + private: Layout m_itemLayout; diff --git a/src/kitemviews/kfileitemlistwidget.cpp b/src/kitemviews/kfileitemlistwidget.cpp index d93e434da..7a95846d8 100644 --- a/src/kitemviews/kfileitemlistwidget.cpp +++ b/src/kitemviews/kfileitemlistwidget.cpp @@ -52,7 +52,6 @@ KFileItemListWidget::KFileItemListWidget(QGraphicsItem* parent) : m_pixmapPos(), m_pixmap(), m_scaledPixmapSize(), - m_originalPixmapSize(), m_iconRect(), m_hoverPixmap(), m_textPos(), @@ -448,23 +447,17 @@ void KFileItemListWidget::updatePixmapCache() // Precondition: Requires already updated m_textPos values to calculate // the remaining height when the alignment is vertical. + const QSizeF widgetSize = size(); const bool iconOnTop = (m_layout == IconsLayout); const KItemListStyleOption& option = styleOption(); - const int iconHeight = option.iconSize; + const qreal margin = option.margin; - const QHash values = data(); - const QSizeF widgetSize = size(); + const int maxIconWidth = iconOnTop ? widgetSize.width() - 2 * margin : option.iconSize; + const int maxIconHeight = option.iconSize; - int scaledIconHeight = 0; - if (iconOnTop) { - scaledIconHeight = static_cast(m_textPos[Name].y() - 3 * option.margin); - } else { - const int textRowsCount = (m_layout == CompactLayout) ? visibleRoles().count() : 1; - const qreal requiredTextHeight = textRowsCount * option.fontMetrics.height(); - scaledIconHeight = (requiredTextHeight < iconHeight) ? widgetSize.height() - 2 * option.margin : iconHeight; - } + const QHash values = data(); - bool updatePixmap = (iconHeight != m_pixmap.height()); + bool updatePixmap = (m_pixmap.width() != maxIconWidth || m_pixmap.height() != maxIconHeight); if (!updatePixmap && m_dirtyContent) { updatePixmap = m_dirtyContentRoles.isEmpty() || m_dirtyContentRoles.contains("iconPixmap") @@ -482,34 +475,11 @@ void KFileItemListWidget::updatePixmapCache() // use a generic icon as fallback iconName = QLatin1String("unknown"); } - m_pixmap = pixmapForIcon(iconName, iconHeight); - m_originalPixmapSize = m_pixmap.size(); - } else if (m_pixmap.size() != QSize(iconHeight, iconHeight)) { + m_pixmap = pixmapForIcon(iconName, maxIconHeight); + } else if (m_pixmap.width() != maxIconWidth || m_pixmap.height() != maxIconHeight) { // A custom pixmap has been applied. Assure that the pixmap - // is scaled to the available size. - const bool scale = m_pixmap.width() > iconHeight || m_pixmap.height() > iconHeight || - (m_pixmap.width() < iconHeight && m_pixmap.height() < iconHeight); - if (scale) { - KPixmapModifier::scale(m_pixmap, QSize(iconHeight, iconHeight)); - } - m_originalPixmapSize = m_pixmap.size(); - - // To simplify the handling of scaling the original pixmap - // will be embedded into a square pixmap. - QPixmap squarePixmap(iconHeight, iconHeight); - squarePixmap.fill(Qt::transparent); - - QPainter painter(&squarePixmap); - const int x = (iconHeight - m_pixmap.width()) / 2; // Center horizontally - int y = iconHeight - m_pixmap.height(); // Move to bottom - if (!iconOnTop) { - y /= 2.0; // Center vertically - } - painter.drawPixmap(x, y, m_pixmap); - - m_pixmap = squarePixmap; - } else { - m_originalPixmapSize = m_pixmap.size(); + // is scaled to the maximum available size. + KPixmapModifier::scale(m_pixmap, QSize(maxIconWidth, maxIconHeight)); } const QStringList overlays = values["iconOverlays"].toStringList(); @@ -535,40 +505,42 @@ void KFileItemListWidget::updatePixmapCache() if (m_isHidden) { applyHiddenEffect(m_pixmap); } - - Q_ASSERT(m_pixmap.height() == iconHeight); } + if (!m_overlay.isNull()) { QPainter painter(&m_pixmap); painter.drawPixmap(0, m_pixmap.height() - m_overlay.height(), m_overlay); } - m_scaledPixmapSize = QSize(scaledIconHeight, scaledIconHeight); - + int scaledIconSize = 0; if (iconOnTop) { - m_pixmapPos.setX((widgetSize.width() - m_scaledPixmapSize.width()) / 2); + scaledIconSize = static_cast(m_textPos[Name].y() - 2 * margin); } else { - m_pixmapPos.setX(m_textPos[Name].x() - 2 * option.margin - scaledIconHeight); + const int textRowsCount = (m_layout == CompactLayout) ? visibleRoles().count() : 1; + const qreal requiredTextHeight = textRowsCount * option.fontMetrics.height(); + scaledIconSize = (requiredTextHeight < maxIconHeight) ? + widgetSize.height() - 2 * margin : maxIconHeight; } - m_pixmapPos.setY(option.margin); - // Center the hover rectangle horizontally and align it on bottom - qreal hoverWidth = m_originalPixmapSize.width(); - qreal hoverHeight = m_originalPixmapSize.height(); - if (scaledIconHeight != m_pixmap.height()) { - const qreal scaleFactor = qreal(scaledIconHeight) / qreal(m_pixmap.height()); - hoverWidth *= scaleFactor; - hoverHeight *= scaleFactor; - } - const qreal hoverX = m_pixmapPos.x() + (m_scaledPixmapSize.width() - hoverWidth) / 2.0; - qreal hoverY = m_scaledPixmapSize.height() - hoverHeight; - if (!iconOnTop) { - hoverY /= 2.0; + const int maxScaledIconWidth = iconOnTop ? widgetSize.width() - 2 * margin : scaledIconSize; + const int maxScaledIconHeight = scaledIconSize; + + m_scaledPixmapSize = m_pixmap.size(); + m_scaledPixmapSize.scale(maxScaledIconWidth, maxScaledIconHeight, Qt::KeepAspectRatio); + + 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()); + } else { + // Center horizontally and vertically within the icon-area + m_pixmapPos.setX(m_textPos[Name].x() - 2 * margin + - (scaledIconSize + m_scaledPixmapSize.width()) / 2); + m_pixmapPos.setY(margin + + (scaledIconSize - m_scaledPixmapSize.height()) / 2); } - hoverY += m_pixmapPos.y(); - m_iconRect = QRectF(hoverX, hoverY, hoverWidth, hoverHeight); - const qreal margin = option.margin; + m_iconRect = QRectF(m_pixmapPos, QSizeF(m_scaledPixmapSize)); m_iconRect.adjust(-margin, -margin, margin, margin); // Prepare the pixmap that is used when the item gets hovered @@ -633,7 +605,8 @@ void KFileItemListWidget::updateIconsLayoutTextCache() const QHash values = data(); const KItemListStyleOption& option = styleOption(); - const qreal maxWidth = size().width() - 2 * option.margin; + const qreal margin = option.margin; + const qreal maxWidth = size().width() - 2 * margin; const qreal widgetHeight = size().height(); const qreal fontHeight = option.fontMetrics.height(); @@ -662,8 +635,8 @@ void KFileItemListWidget::updateIconsLayoutTextCache() textLinesCount += additionalRolesCount; m_text[Name].setTextWidth(maxWidth); - m_textPos[Name] = QPointF(option.margin, widgetHeight - textLinesCount * fontHeight - option.margin); - m_textRect = QRectF(option.margin + (maxWidth - requiredWidthForName) / 2, + m_textPos[Name] = QPointF(margin, widgetHeight - textLinesCount * fontHeight - margin); + m_textRect = QRectF(margin + (maxWidth - requiredWidthForName) / 2, m_textPos[Name].y(), requiredWidthForName, textLinesCountForName * fontHeight); @@ -693,23 +666,22 @@ void KFileItemListWidget::updateIconsLayoutTextCache() // 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 - option.margin); + const QString elidedText = option.fontMetrics.elidedText(text, Qt::ElideRight, maxWidth - margin); m_text[textId].setText(elidedText); } } layout.endLayout(); - m_textPos[textId] = QPointF(option.margin, y); + m_textPos[textId] = QPointF(margin, y); m_text[textId].setTextWidth(maxWidth); - const QRectF textRect(option.margin + (maxWidth - requiredWidth) / 2, y, requiredWidth, fontHeight); + const QRectF textRect(margin + (maxWidth - requiredWidth) / 2, y, requiredWidth, fontHeight); m_textRect |= textRect; y += fontHeight; } // Add a margin to the text rectangle - const qreal margin = option.margin; m_textRect.adjust(-margin, -margin, margin, margin); } @@ -851,7 +823,7 @@ void KFileItemListWidget::drawPixmap(QPainter* painter, const QPixmap& pixmap) #ifdef KFILEITEMLISTWIDGET_DEBUG painter->setPen(Qt::blue); - painter->drawRect(QRectF(m_pixmapPos, QSizeF(scaledPixmap.size()))); + painter->drawRect(QRectF(m_pixmapPos, QSizeF(m_scaledPixmapSize))); #endif } else { painter->drawPixmap(m_pixmapPos, pixmap); diff --git a/src/kitemviews/kfileitemlistwidget.h b/src/kitemviews/kfileitemlistwidget.h index 91f00fe73..4a44a8468 100644 --- a/src/kitemviews/kfileitemlistwidget.h +++ b/src/kitemviews/kfileitemlistwidget.h @@ -139,7 +139,6 @@ private: QPixmap m_pixmap; QSize m_scaledPixmapSize; - QSize m_originalPixmapSize; // Size of pixmap before it gets converted to a square pixmap QRectF m_iconRect; // Cache for KItemListWidget::iconRect() QPixmap m_hoverPixmap; // Cache for modified m_pixmap when hovering the item diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp index 67ba01a2f..c671a2e6e 100644 --- a/src/kitemviews/kitemlistview.cpp +++ b/src/kitemviews/kitemlistview.cpp @@ -1847,16 +1847,20 @@ 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 oldColumnCount = m_layouter->size().width() / itemWidth; const int newColumnCount = newGridSize.width() / newItemSize.width(); - return oldColumnCount != newColumnCount; + if (m_model->count() > newColumnCount) { + const int oldColumnCount = m_layouter->size().width() / itemWidth; + return oldColumnCount != newColumnCount; + } } } else { const qreal itemHeight = m_layouter->itemSize().height(); if (itemHeight > 0) { - const int oldRowCount = m_layouter->size().height() / itemHeight; const int newRowCount = newGridSize.height() / newItemSize.height(); - return oldRowCount != newRowCount; + if (m_model->count() > newRowCount) { + const int oldRowCount = m_layouter->size().height() / itemHeight; + return oldRowCount != newRowCount; + } } } diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp index 8e6c728f7..67df036c8 100644 --- a/src/kitemviews/kitemlistwidget.cpp +++ b/src/kitemviews/kitemlistwidget.cpp @@ -432,7 +432,6 @@ void KItemListWidget::clearHoverCache() void KItemListWidget::drawItemStyleOption(QPainter* painter, QWidget* widget, QStyle::State styleState) { - const QRect iconBounds = iconRect().toRect(); const QRect textBounds = textRect().toRect(); QStyleOptionViewItemV4 viewItemOption; @@ -440,17 +439,8 @@ void KItemListWidget::drawItemStyleOption(QPainter* painter, QWidget* widget, QS viewItemOption.state = styleState; viewItemOption.viewItemPosition = QStyleOptionViewItemV4::OnlyOne; viewItemOption.showDecorationSelected = true; - - if (iconBounds.bottom() > textBounds.top()) { - viewItemOption.rect = iconBounds | textBounds; - widget->style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &viewItemOption, painter, widget); - } else { - viewItemOption.rect = iconBounds; - widget->style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &viewItemOption, painter, widget); - - viewItemOption.rect = textBounds.adjusted(1, 1, -1, -1); - widget->style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &viewItemOption, painter, widget); - } + viewItemOption.rect = textBounds; + widget->style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &viewItemOption, painter, widget); } #include "kitemlistwidget.moc" diff --git a/src/views/dolphinitemlistcontainer.cpp b/src/views/dolphinitemlistcontainer.cpp index c687ede4d..4f7a0e06b 100644 --- a/src/views/dolphinitemlistcontainer.cpp +++ b/src/views/dolphinitemlistcontainer.cpp @@ -218,7 +218,7 @@ void DolphinItemListContainer::updateGridSize() if (itemWidth < iconSize + innerMargin * 2) { itemWidth = iconSize + innerMargin * 2; } - itemHeight = innerMargin * 2 + iconSize + styleOption.fontMetrics.height(); + itemHeight = innerMargin * 3 + iconSize + styleOption.fontMetrics.height(); break; } case KFileItemListView::CompactLayout: {