X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/188d1a9c7d11db2a98f5110fce6ff03afffcb2db..c8d8556950005dfd96ebdb41d2f43ad90356367c:/src/kitemviews/kitemlistwidget.cpp diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp index 86febed97..61e06078b 100644 --- a/src/kitemviews/kitemlistwidget.cpp +++ b/src/kitemviews/kitemlistwidget.cpp @@ -22,14 +22,15 @@ #include "kitemlistwidget.h" +#include "kitemlistselectiontoggle_p.h" #include "kitemlistview.h" #include "kitemmodelbase.h" #include +#include #include #include -#include #include KItemListWidget::KItemListWidget(QGraphicsItem* parent) : @@ -38,29 +39,35 @@ KItemListWidget::KItemListWidget(QGraphicsItem* parent) : m_selected(false), m_current(false), m_hovered(false), + m_alternatingBackgroundColors(false), + m_enabledSelectionToggle(false), m_data(), m_visibleRoles(), m_visibleRolesSizes(), m_styleOption(), m_hoverOpacity(0), m_hoverCache(0), - m_hoverAnimation(0) + m_hoverAnimation(0), + m_selectionToggle(0) { } KItemListWidget::~KItemListWidget() { - clearCache(); + clearHoverCache(); } void KItemListWidget::setIndex(int index) { if (m_index != index) { + delete m_selectionToggle; + m_selectionToggle = 0; + if (m_hoverAnimation) { m_hoverAnimation->stop(); m_hoverOpacity = 0; } - clearCache(); + clearHoverCache(); m_index = index; } @@ -74,7 +81,7 @@ int KItemListWidget::index() const void KItemListWidget::setData(const QHash& data, const QSet& roles) { - clearCache(); + clearHoverCache(); if (roles.isEmpty()) { m_data = data; dataChanged(m_data); @@ -97,58 +104,72 @@ void KItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsItem* o painter->setRenderHint(QPainter::Antialiasing); - const QRect iconBounds = iconBoundingRect().toRect(); - if (m_selected) { - QStyleOptionViewItemV4 viewItemOption; - viewItemOption.initFrom(widget); - viewItemOption.rect = iconBounds; - viewItemOption.state = QStyle::State_Enabled | QStyle::State_Selected | QStyle::State_Item; - viewItemOption.viewItemPosition = QStyleOptionViewItemV4::OnlyOne; - widget->style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &viewItemOption, painter, widget); - - drawTextBackground(painter); + if (m_alternatingBackgroundColors && (m_index & 0x1)) { + const QColor backgroundColor = m_styleOption.palette.color(QPalette::AlternateBase); + const QRectF backgroundRect(0, 0, size().width(), size().height()); + painter->fillRect(backgroundRect, backgroundColor); } - if (isCurrent()) { - drawFocusIndicator(painter); + if (m_selected) { + const QStyle::State activeState(isActiveWindow() ? QStyle::State_Active : 0); + drawItemStyleOption(painter, widget, activeState | + QStyle::State_Enabled | + QStyle::State_Selected | + QStyle::State_Item); } - if (m_hoverOpacity <= 0.0) { - return; - } + if (isCurrent()) { + QStyleOptionFocusRect focusRectOption; + focusRectOption.initFrom(widget); + + const QRect iconBounds = iconRect().toRect(); + const QRect textBounds = textRect().toRect(); + if (iconBounds.bottom() > textBounds.top()) { + focusRectOption.rect = textBounds; + } else { + // See KItemListWidget::drawItemStyleOption(): The selection rectangle + // gets decreased. + focusRectOption.rect = textBounds.adjusted(1, 1, -1, -1); + } - if (!m_hoverCache) { - // Initialize the m_hoverCache pixmap to improve the drawing performance - // when fading the hover background - m_hoverCache = new QPixmap(iconBounds.size()); - m_hoverCache->fill(Qt::transparent); + focusRectOption.state = QStyle::State_Enabled | QStyle::State_Item; + if (m_selected) { + focusRectOption.state |= QStyle::State_Selected; + } - QPainter pixmapPainter(m_hoverCache); + style()->drawPrimitive(QStyle::PE_FrameFocusRect, &focusRectOption, painter, widget); + } - QStyleOptionViewItemV4 viewItemOption; - viewItemOption.initFrom(widget); - viewItemOption.rect = QRect(0, 0, iconBounds.width(), iconBounds.height()); - viewItemOption.state = QStyle::State_Enabled | QStyle::State_MouseOver | QStyle::State_Item; - viewItemOption.viewItemPosition = QStyleOptionViewItemV4::OnlyOne; + if (m_hoverOpacity > 0.0) { + if (!m_hoverCache) { + // Initialize the m_hoverCache pixmap to improve the drawing performance + // when fading the hover background + m_hoverCache = new QPixmap(size().toSize()); + m_hoverCache->fill(Qt::transparent); + + QPainter pixmapPainter(m_hoverCache); + const QStyle::State activeState(isActiveWindow() ? QStyle::State_Active : 0); + drawItemStyleOption(&pixmapPainter, widget, activeState | + QStyle::State_Enabled | + QStyle::State_MouseOver | + QStyle::State_Item); + } - widget->style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &viewItemOption, &pixmapPainter, widget); + const qreal opacity = painter->opacity(); + painter->setOpacity(m_hoverOpacity * opacity); + painter->drawPixmap(0, 0, *m_hoverCache); + painter->setOpacity(opacity); } - - const qreal opacity = painter->opacity(); - painter->setOpacity(m_hoverOpacity * opacity); - painter->drawPixmap(iconBounds.topLeft(), *m_hoverCache); - drawTextBackground(painter); - painter->setOpacity(opacity); } -void KItemListWidget::setVisibleRoles(const QHash& roles) +void KItemListWidget::setVisibleRoles(const QList& roles) { - const QHash previousRoles = m_visibleRoles; + const QList previousRoles = m_visibleRoles; m_visibleRoles = roles; visibleRolesChanged(roles, previousRoles); } -QHash KItemListWidget::visibleRoles() const +QList KItemListWidget::visibleRoles() const { return m_visibleRoles; } @@ -168,7 +189,7 @@ QHash KItemListWidget::visibleRolesSizes() const void KItemListWidget::setStyleOption(const KItemListStyleOption& option) { const KItemListStyleOption previous = m_styleOption; - clearCache(); + clearHoverCache(); m_styleOption = option; styleOptionChanged(option, previous); @@ -183,6 +204,10 @@ void KItemListWidget::setSelected(bool selected) { if (m_selected != selected) { m_selected = selected; + if (m_selectionToggle) { + m_selectionToggle->setChecked(selected); + } + selectedChanged(selected); update(); } @@ -197,6 +222,7 @@ void KItemListWidget::setCurrent(bool current) { if (m_current != current) { m_current = current; + currentChanged(current); update(); } @@ -218,12 +244,19 @@ void KItemListWidget::setHovered(bool hovered) if (!m_hoverAnimation) { m_hoverAnimation = new QPropertyAnimation(this, "hoverOpacity", this); m_hoverAnimation->setDuration(200); + connect(m_hoverAnimation, SIGNAL(finished()), this, SLOT(slotHoverAnimationFinished())); } m_hoverAnimation->stop(); if (hovered) { + const qreal startValue = qMax(hoverOpacity(), qreal(0.1)); + m_hoverAnimation->setStartValue(startValue); m_hoverAnimation->setEndValue(1.0); + if (m_enabledSelectionToggle && !(QApplication::mouseButtons() & Qt::LeftButton)) { + initializeSelectionToggle(); + } } else { + m_hoverAnimation->setStartValue(hoverOpacity()); m_hoverAnimation->setEndValue(0.0); } @@ -239,14 +272,41 @@ bool KItemListWidget::isHovered() const return m_hovered; } +void KItemListWidget::setAlternatingBackgroundColors(bool enable) +{ + if (m_alternatingBackgroundColors != enable) { + m_alternatingBackgroundColors = enable; + alternatingBackgroundColorsChanged(enable); + update(); + } +} + +bool KItemListWidget::alternatingBackgroundColors() const +{ + return m_alternatingBackgroundColors; +} + +void KItemListWidget::setEnabledSelectionToggle(bool enable) +{ + if (m_enabledSelectionToggle != enable) { + m_enabledSelectionToggle = enable; + update(); + } +} + +bool KItemListWidget::enabledSelectionToggle() const +{ + return m_enabledSelectionToggle; +} + bool KItemListWidget::contains(const QPointF& point) const { if (!QGraphicsWidget::contains(point)) { return false; } - return iconBoundingRect().contains(point) || - textBoundingRect().contains(point) || + return iconRect().contains(point) || + textRect().contains(point) || expansionToggleRect().contains(point) || selectionToggleRect().contains(point); } @@ -269,8 +329,8 @@ void KItemListWidget::dataChanged(const QHash& current, update(); } -void KItemListWidget::visibleRolesChanged(const QHash& current, - const QHash& previous) +void KItemListWidget::visibleRolesChanged(const QList& current, + const QList& previous) { Q_UNUSED(current); Q_UNUSED(previous); @@ -308,10 +368,15 @@ void KItemListWidget::hoveredChanged(bool hovered) Q_UNUSED(hovered); } +void KItemListWidget::alternatingBackgroundColorsChanged(bool enabled) +{ + Q_UNUSED(enabled); +} + void KItemListWidget::resizeEvent(QGraphicsSceneResizeEvent* event) { QGraphicsWidget::resizeEvent(event); - clearCache(); + clearHoverCache(); } qreal KItemListWidget::hoverOpacity() const @@ -319,56 +384,71 @@ qreal KItemListWidget::hoverOpacity() const return m_hoverOpacity; } -void KItemListWidget::setHoverOpacity(qreal opacity) +void KItemListWidget::slotHoverAnimationFinished() { - m_hoverOpacity = opacity; - update(); + if (!m_hovered) { + delete m_selectionToggle; + m_selectionToggle = 0; + } } -void KItemListWidget::clearCache() +void KItemListWidget::initializeSelectionToggle() { - delete m_hoverCache; - m_hoverCache = 0; + Q_ASSERT(m_enabledSelectionToggle); + + if (!m_selectionToggle) { + m_selectionToggle = new KItemListSelectionToggle(this); + } + + const QRectF toggleRect = selectionToggleRect(); + m_selectionToggle->setPos(toggleRect.topLeft()); + m_selectionToggle->resize(toggleRect.size()); + + m_selectionToggle->setChecked(isSelected()); } -void KItemListWidget::drawFocusIndicator(QPainter* painter) +void KItemListWidget::setHoverOpacity(qreal opacity) { - // Ideally style()->drawPrimitive(QStyle::PE_FrameFocusRect...) - // should be used, but Oxygen only draws indicators within classes - // derived from QAbstractItemView or Q3ListView. As a workaround - // the indicator is drawn manually. Code copied from oxygenstyle.cpp - // Copyright ( C ) 2009-2010 Hugo Pereira Da Costa - // TODO: Clarify with Oxygen maintainers how to proceed with this. + m_hoverOpacity = opacity; + if (m_selectionToggle) { + m_selectionToggle->setOpacity(opacity); + } - const KItemListStyleOption& option = styleOption(); - const QPalette palette = option.palette; - const QRect rect = textBoundingRect().toRect().adjusted(0, 0, 0, -1); + if (m_hoverOpacity <= 0.0) { + delete m_hoverCache; + m_hoverCache = 0; + } - QLinearGradient gradient(rect.bottomLeft(), rect.bottomRight()); - gradient.setColorAt(0.0, Qt::transparent); - gradient.setColorAt(1.0, Qt::transparent); - gradient.setColorAt(0.2, palette.color(QPalette::Text)); - gradient.setColorAt(0.8, palette.color(QPalette::Text)); + update(); +} - painter->setRenderHint(QPainter::Antialiasing, false); - painter->setPen(QPen(gradient, 1)); - painter->drawLine(rect.bottomLeft(), rect.bottomRight()); - painter->setRenderHint(QPainter::Antialiasing, true); +void KItemListWidget::clearHoverCache() +{ + delete m_hoverCache; + m_hoverCache = 0; } -void KItemListWidget::drawTextBackground(QPainter* painter) +void KItemListWidget::drawItemStyleOption(QPainter* painter, QWidget* widget, QStyle::State styleState) { - const qreal opacity = painter->opacity(); + const QRect iconBounds = iconRect().toRect(); + const QRect textBounds = textRect().toRect(); + + QStyleOptionViewItemV4 viewItemOption; + viewItemOption.initFrom(widget); + viewItemOption.state = styleState; + viewItemOption.viewItemPosition = QStyleOptionViewItemV4::OnlyOne; + viewItemOption.showDecorationSelected = true; - QRectF textBounds = textBoundingRect(); - const qreal marginDiff = m_styleOption.margin / 2; - textBounds.adjust(marginDiff, marginDiff, -marginDiff, -marginDiff); - painter->setOpacity(opacity * 0.1); - painter->setPen(Qt::NoPen); - painter->setBrush(m_styleOption.palette.text()); - painter->drawRoundedRect(textBounds, 4, 4); + 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); - painter->setOpacity(opacity); + viewItemOption.rect = textBounds.adjusted(1, 1, -1, -1); + widget->style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &viewItemOption, painter, widget); + } } #include "kitemlistwidget.moc"