]> cloud.milkyroute.net Git - dolphin.git/commitdiff
Improve drawing of list-header
authorPeter Penz <peter.penz19@gmail.com>
Wed, 21 Sep 2011 21:40:51 +0000 (23:40 +0200)
committerPeter Penz <peter.penz19@gmail.com>
Wed, 21 Sep 2011 21:42:28 +0000 (23:42 +0200)
src/kitemviews/kitemlistheader.cpp
src/kitemviews/kitemlistheader_p.h

index e5cb43a57c5054ac602f437c8eb6881af73e2675..ab66b5374285c20f91d8e2fab3fa31290cabb486 100644 (file)
 #include "kitemmodelbase.h"
 
 #include <QFontMetricsF>
+#include <QGraphicsSceneHoverEvent>
 #include <QPainter>
 #include <QStyleOptionHeader>
 
+#include <KDebug>
+
 KItemListHeader::KItemListHeader(QGraphicsWidget* parent) :
     QGraphicsWidget(parent),
     m_model(0),
     m_visibleRoles(),
-    m_visibleRolesWidths()
+    m_visibleRolesWidths(),
+    m_hoveredRoleIndex(-1),
+    m_pressedRoleIndex(-1),
+    m_resizePressedRole(false)
 {
-    QStyleOptionHeader opt;
-    const QSize headerSize = style()->sizeFromContents(QStyle::CT_HeaderSection, &opt, QSize());
+    setAcceptHoverEvents(true);
+
+    QStyleOptionHeader option;
+    const QSize headerSize = style()->sizeFromContents(QStyle::CT_HeaderSection, &option, QSize());
     resize(0, headerSize.height());
 }
 
@@ -95,34 +103,78 @@ void KItemListHeader::paint(QPainter* painter, const QStyleOptionGraphicsItem* o
     Q_UNUSED(option);
     Q_UNUSED(widget);
 
-    // Draw background
-    QStyleOption opt;
-    opt.init(widget);
-    opt.rect = rect().toRect();
-    opt.state |= QStyle::State_Horizontal;
-    style()->drawControl(QStyle::CE_HeaderEmptyArea, &opt, painter);
-
     if (!m_model) {
         return;
     }
 
     // Draw roles
-    // TODO: This is a rough draft only
-    QFontMetricsF fontMetrics(font());
-    QTextOption textOption(Qt::AlignLeft | Qt::AlignVCenter);
-
     painter->setFont(font());
     painter->setPen(palette().text().color());
 
-    const qreal margin = style()->pixelMetric(QStyle::PM_HeaderMargin);
-    qreal x = margin;
+    qreal x = 0;
+    int orderIndex = 0;
     foreach (const QByteArray& role, m_visibleRoles) {
-        const QString roleDescription = m_model->roleDescription(role);
-        const qreal textWidth = fontMetrics.width(roleDescription);
-        QRectF rect(x, 0, textWidth, size().height());
-        painter->drawText(rect, roleDescription, textOption);
+        const qreal roleWidth = m_visibleRolesWidths.value(role);
+        const QRectF rect(x, 0, roleWidth, size().height());
+        paintRole(painter, role, rect, orderIndex);
+        x += roleWidth;
+        ++orderIndex;
+    }
+
+    // Draw background without roles
+    QStyleOption opt;
+    opt.init(widget);
+    opt.rect = QRect(x, 0, size().width() - x, size().height());
+    opt.state |= QStyle::State_Horizontal;
+    style()->drawControl(QStyle::CE_HeaderEmptyArea, &opt, painter);
+}
+
+void KItemListHeader::mousePressEvent(QGraphicsSceneMouseEvent* event)
+{
+    event->accept();
+    updatePressedRoleIndex(event->pos());
+}
+
+void KItemListHeader::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
+{
+    QGraphicsWidget::mouseReleaseEvent(event);
+    if (m_pressedRoleIndex != -1) {
+        m_pressedRoleIndex = -1;
+        update();
+    }
+}
+
+void KItemListHeader::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
+{
+    QGraphicsWidget::mouseMoveEvent(event);
+    updatePressedRoleIndex(event->pos());
+}
+
+void KItemListHeader::hoverEnterEvent(QGraphicsSceneHoverEvent* event)
+{
+    QGraphicsWidget::hoverEnterEvent(event);
+    updateHoveredRoleIndex(event->pos());
+}
+
+void KItemListHeader::hoverLeaveEvent(QGraphicsSceneHoverEvent* event)
+{
+    QGraphicsWidget::hoverLeaveEvent(event);
+    if (m_hoveredRoleIndex != -1) {
+        m_hoveredRoleIndex = -1;
+        update();
+    }
+}
+
+void KItemListHeader::hoverMoveEvent(QGraphicsSceneHoverEvent* event)
+{
+    QGraphicsWidget::hoverMoveEvent(event);
 
-        x += m_visibleRolesWidths.value(role) + margin;
+    const QPointF& pos = event->pos();
+    updateHoveredRoleIndex(pos);
+    if (m_hoveredRoleIndex >= 0 && isAboveRoleGrip(pos, m_hoveredRoleIndex)) {
+        setCursor(Qt::SplitHCursor);
+    } else {
+        unsetCursor();
     }
 }
 
@@ -138,4 +190,97 @@ void KItemListHeader::slotSortOrderChanged(Qt::SortOrder current, Qt::SortOrder
     Q_UNUSED(previous);
 }
 
+void KItemListHeader::paintRole(QPainter* painter,
+                                const QByteArray& role,
+                                const QRectF& rect,
+                                int orderIndex)
+{
+    // The following code is based on the code from QHeaderView::paintSection().
+    // Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+    QStyleOptionHeader option;
+    option.section = orderIndex;
+    option.state = QStyle::State_None | QStyle::State_Raised;
+    if (isEnabled()) {
+        option.state |= QStyle::State_Enabled;
+    }
+    if (window() && window()->isActiveWindow()) {
+        option.state |= QStyle::State_Active;
+    }
+    if (m_hoveredRoleIndex == orderIndex) {
+        option.state |= QStyle::State_MouseOver;
+    }
+    if (m_pressedRoleIndex == orderIndex) {
+        option.state |= QStyle::State_Sunken;
+    }
+    /*if (m_model->sortRole() == role) {
+        option.sortIndicator = (m_model->sortOrder() == Qt::AscendingOrder) ?
+                                QStyleOptionHeader::SortDown : QStyleOptionHeader::SortUp;
+    }*/
+    option.rect = rect.toRect();
+
+    if (m_visibleRoles.count() == 1) {
+        option.position = QStyleOptionHeader::OnlyOneSection;
+    } else if (orderIndex == 0) {
+        option.position = QStyleOptionHeader::Beginning;
+    } else if (orderIndex == m_visibleRoles.count() - 1) {
+        option.position = QStyleOptionHeader::End;
+    } else {
+        option.position = QStyleOptionHeader::Middle;
+    }
+
+    option.selectedPosition = QStyleOptionHeader::NotAdjacent;
+
+    const QString text = m_model->roleDescription(role);
+    const int grip = style()->pixelMetric(QStyle::PM_HeaderGripMargin);
+    option.text = option.fontMetrics.elidedText(text, Qt::ElideRight, option.rect.width() - grip);
+
+    style()->drawControl(QStyle::CE_Header, &option, painter);
+}
+
+void KItemListHeader::updatePressedRoleIndex(const QPointF& pos)
+{
+    const int pressedIndex = roleIndexAt(pos);
+    if (m_pressedRoleIndex != pressedIndex) {
+        m_pressedRoleIndex = pressedIndex;
+        update();
+    }
+}
+
+void KItemListHeader::updateHoveredRoleIndex(const QPointF& pos)
+{
+    const int hoverIndex = roleIndexAt(pos);
+    if (m_hoveredRoleIndex != hoverIndex) {
+        m_hoveredRoleIndex = hoverIndex;
+        update();
+    }
+}
+
+int KItemListHeader::roleIndexAt(const QPointF& pos) const
+{
+    int index = -1;
+
+    qreal x = 0;
+    foreach (const QByteArray& role, m_visibleRoles) {
+        ++index;
+        x += m_visibleRolesWidths.value(role);
+        if (pos.x() <= x) {
+            break;
+        }
+    }
+
+    return index;
+}
+
+bool KItemListHeader::isAboveRoleGrip(const QPointF& pos, int roleIndex) const
+{
+    qreal x = 0;
+    for (int i = 0; i <= roleIndex; ++i) {
+        const QByteArray role = m_visibleRoles.at(i);
+        x += m_visibleRolesWidths.value(role);
+    }
+
+    const int grip = style()->pixelMetric(QStyle::PM_HeaderGripMargin);
+    return pos.x() >= (x - grip) && pos.x() <= x;
+}
+
 #include "kitemlistheader_p.moc"
index e75bd7b148f067792a81b2d133924d3d070e3777..7219722a78449dd39c8f0d8d156e6f5abaf47069 100644 (file)
@@ -49,14 +49,34 @@ public:
 
     virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0);
 
+protected:
+    virtual void mousePressEvent(QGraphicsSceneMouseEvent* event);
+    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent* event);
+    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent* event);
+    virtual void hoverEnterEvent(QGraphicsSceneHoverEvent* event);
+    virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent* event);
+    virtual void hoverMoveEvent(QGraphicsSceneHoverEvent* event);
+
 private slots:
     void slotSortRoleChanged(const QByteArray& current, const QByteArray& previous);
     void slotSortOrderChanged(Qt::SortOrder current, Qt::SortOrder previous);
 
+private:
+    void paintRole(QPainter* painter, const QByteArray& role, const QRectF& rect, int orderIndex);
+
+    void updatePressedRoleIndex(const QPointF& pos);
+    void updateHoveredRoleIndex(const QPointF& pos);
+    int roleIndexAt(const QPointF& pos) const;
+    bool isAboveRoleGrip(const QPointF& pos, int roleIndex) const;
+
 private:
     KItemModelBase* m_model;
     QList<QByteArray> m_visibleRoles;
     QHash<QByteArray, qreal> m_visibleRolesWidths;
+
+    int m_hoveredRoleIndex;
+    int m_pressedRoleIndex;
+    bool m_resizePressedRole;
 };
 
 #endif