┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Penz <[email protected]>2012-02-06 23:26:20 +0100
committerPeter Penz <[email protected]>2012-02-06 23:31:49 +0100
commit5369ee6819a26d9d3f106521c525c03f81a943ce (patch)
treeb6a31372f7fa6cd58aac1c7faeca6d5d96d50e32
parent7af39fb960352e0504153c627db0615d80758ebe (diff)
Group header improvements
- Use a simpler background and colors as suggested by Martin Zilz. This is just an early draft, I need to post some comparison screenshots to Martin for review. - Fixes of some layout issues that have been revealed because of adjusting the group header heights. - More clever animation/no-animation detection when doing listview-property changes in parallel.
-rw-r--r--src/kitemviews/kfileitemlistgroupheader.cpp8
-rw-r--r--src/kitemviews/kitemlistgroupheader.cpp109
-rw-r--r--src/kitemviews/kitemlistgroupheader.h19
-rw-r--r--src/kitemviews/kitemlistview.cpp74
-rw-r--r--src/kitemviews/kitemlistview.h19
-rw-r--r--src/kitemviews/kitemlistviewlayouter.cpp2
-rw-r--r--src/views/dolphinitemlistcontainer.cpp2
7 files changed, 114 insertions, 119 deletions
diff --git a/src/kitemviews/kfileitemlistgroupheader.cpp b/src/kitemviews/kfileitemlistgroupheader.cpp
index 06d410f28..237a974c2 100644
--- a/src/kitemviews/kfileitemlistgroupheader.cpp
+++ b/src/kitemviews/kfileitemlistgroupheader.cpp
@@ -41,10 +41,9 @@ void KFileItemListGroupHeader::paint(QPainter* painter, const QStyleOptionGraphi
{
KItemListGroupHeader::paint(painter, option, widget);
- painter->setPen(styleOption().palette.text().color());
+ painter->setPen(roleColor());
painter->setFont(m_font);
- const int margin = styleOption().margin;
- painter->drawStaticText(margin * 2, margin, m_text);
+ painter->drawStaticText(roleBounds().topLeft(), m_text);
}
void KFileItemListGroupHeader::dataChanged(const QVariant& current, const QVariant& previous)
@@ -63,8 +62,7 @@ void KFileItemListGroupHeader::resizeEvent(QGraphicsSceneResizeEvent* event)
void KFileItemListGroupHeader::updateText()
{
const qreal width = size().width() - 4 * styleOption().margin;
- m_font = font();
- m_font.setBold(true);
+ m_font = font(); // TODO: Most probably the font size will be slightly shrinked in future
QFontMetricsF fontMetrics(m_font);
const QString text = fontMetrics.elidedText(data().toString(), Qt::ElideRight, width);
diff --git a/src/kitemviews/kitemlistgroupheader.cpp b/src/kitemviews/kitemlistgroupheader.cpp
index a63ad8d09..8eff39901 100644
--- a/src/kitemviews/kitemlistgroupheader.cpp
+++ b/src/kitemviews/kitemlistgroupheader.cpp
@@ -36,15 +36,13 @@ KItemListGroupHeader::KItemListGroupHeader(QGraphicsWidget* parent) :
m_data(),
m_styleOption(),
m_scrollOrientation(Qt::Vertical),
- m_leftBorderCache(0),
- m_rightBorderCache(0),
- m_outlineColor()
+ m_roleColor(),
+ m_roleBounds()
{
}
KItemListGroupHeader::~KItemListGroupHeader()
{
- deleteCache();
}
void KItemListGroupHeader::setRole(const QByteArray& role)
@@ -97,8 +95,6 @@ void KItemListGroupHeader::setScrollOrientation(Qt::Orientation orientation)
m_scrollOrientation = orientation;
if (orientation == Qt::Vertical) {
m_dirtyCache = true;
- } else {
- deleteCache();
}
scrollOrientationChanged(orientation, previous);
}
@@ -114,24 +110,25 @@ void KItemListGroupHeader::paint(QPainter* painter, const QStyleOptionGraphicsIt
Q_UNUSED(option);
Q_UNUSED(widget);
- if (m_scrollOrientation == Qt::Horizontal) {
- Q_ASSERT(!m_leftBorderCache);
- Q_ASSERT(!m_rightBorderCache);
- return;
- }
-
if (m_dirtyCache) {
updateCache();
}
- const int leftBorderX = m_leftBorderCache->width() + 1;
- const int rightBorderX = size().width() - m_rightBorderCache->width() - 2;
+ if (m_scrollOrientation != Qt::Horizontal) {
+ painter->setPen(m_roleColor);
+ const qreal y = m_roleBounds.y() - m_styleOption.margin;
+ painter->drawLine(0, y, size().width() - 1, y);
+ }
+}
- painter->setPen(m_outlineColor);
- painter->drawLine(leftBorderX, 1, rightBorderX, 1);
+QRectF KItemListGroupHeader::roleBounds() const
+{
+ return m_roleBounds;
+}
- painter->drawPixmap(1, 1, *m_leftBorderCache);
- painter->drawPixmap(rightBorderX, 1, *m_rightBorderCache);
+QColor KItemListGroupHeader::roleColor() const
+{
+ return m_roleColor;
}
void KItemListGroupHeader::roleChanged(const QByteArray& current, const QByteArray& previous)
@@ -170,82 +167,26 @@ void KItemListGroupHeader::updateCache()
{
Q_ASSERT(m_dirtyCache);
- deleteCache();
-
- const int length = qMax(int(size().height() - 1), 1);
- m_leftBorderCache = new QPixmap(length, length);
- m_leftBorderCache->fill(Qt::transparent);
-
- m_rightBorderCache = new QPixmap(length, length);
- m_rightBorderCache->fill(Qt::transparent);
-
// Calculate the outline color. No alphablending is used for
// performance reasons.
const QColor c1 = m_styleOption.palette.text().color();
const QColor c2 = m_styleOption.palette.background().color();
const int p1 = 35;
const int p2 = 100 - p1;
- m_outlineColor = QColor((c1.red() * p1 + c2.red() * p2) / 100,
- (c1.green() * p1 + c2.green() * p2) / 100,
- (c1.blue() * p1 + c2.blue() * p2) / 100);
-
- // The drawing code is based on the code of DolphinCategoryDrawer from Dolphin 1.7
- // Copyright (C) 2007 Rafael Fernández López <[email protected]>
- {
- // Cache the left border as pixmap
- QPainter painter(m_leftBorderCache);
- painter.setPen(m_outlineColor);
+ m_roleColor = QColor((c1.red() * p1 + c2.red() * p2) / 100,
+ (c1.green() * p1 + c2.green() * p2) / 100,
+ (c1.blue() * p1 + c2.blue() * p2) / 100);
- // 1. Draw top horizontal line
- painter.drawLine(3, 0, length, 0);
+ const int margin = m_styleOption.margin;
+ const QFontMetrics fontMetrics(m_styleOption.font);
+ const qreal roleHeight = fontMetrics.height();
- // 2. Draw vertical line with gradient
- const QPoint start(0, 3);
- QLinearGradient gradient(start, QPoint(0, length));
- gradient.setColorAt(0, m_outlineColor);
- gradient.setColorAt(1, Qt::transparent);
- painter.fillRect(QRect(start, QSize(1, length - start.y())), gradient);
-
- // 3. Draw arc
- painter.setRenderHint(QPainter::Antialiasing);
- QRectF arc(QPointF(0, 0), QSizeF(4, 4));
- arc.translate(0.5, 0.5);
- painter.drawArc(arc, 1440, 1440);
- }
-
- {
- // Cache the right border as pixmap
- QPainter painter(m_rightBorderCache);
- painter.setPen(m_outlineColor);
-
- // 1. Draw top horizontal line
- painter.drawLine(0, 0, length - 3, 0);
-
- // 2. Draw vertical line with gradient
- const int right = length - 1;
- const QPoint start(right, 3);
- QLinearGradient gradient(start, QPoint(right, length));
- gradient.setColorAt(0, m_outlineColor);
- gradient.setColorAt(1, Qt::transparent);
- painter.fillRect(QRect(start, QSize(1, length - start.y())), gradient);
-
- // 3. Draw arc
- painter.setRenderHint(QPainter::Antialiasing);
- QRectF arc(QPointF(length - 5, 0), QSizeF(4, 4));
- arc.translate(0.5, 0.5);
- painter.drawArc(arc, 0, 1440);
- }
+ m_roleBounds = QRectF(margin,
+ size().height() - roleHeight - margin,
+ size().width() - 2 * margin,
+ roleHeight);
m_dirtyCache = false;
}
-void KItemListGroupHeader::deleteCache()
-{
- delete m_leftBorderCache;
- m_leftBorderCache = 0;
-
- delete m_rightBorderCache;
- m_rightBorderCache = 0;
-}
-
#include "kitemlistgroupheader.moc"
diff --git a/src/kitemviews/kitemlistgroupheader.h b/src/kitemviews/kitemlistgroupheader.h
index 8f556afc5..5ddf20896 100644
--- a/src/kitemviews/kitemlistgroupheader.h
+++ b/src/kitemviews/kitemlistgroupheader.h
@@ -30,6 +30,13 @@
class KItemListView;
+/**
+ * @brief Base class for group headers.
+ *
+ * Draws a default header background. Derived classes must reimplement
+ * the method paint() and draw the role within the given roleBounds() with
+ * the color roleColor().
+ */
class LIBDOLPHINPRIVATE_EXPORT KItemListGroupHeader : public QGraphicsWidget
{
Q_OBJECT
@@ -58,6 +65,12 @@ public:
virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0);
protected:
+ /** @return Bounding rectangle where the role should be drawn into. */
+ QRectF roleBounds() const;
+
+ /** @return Primary color that should be used for drawing the role. */
+ QColor roleColor() const;
+
/**
* Is called after the role has been changed and allows the derived class
* to react on this change.
@@ -87,7 +100,6 @@ protected:
private:
void updateCache();
- void deleteCache();
private:
bool m_dirtyCache;
@@ -96,9 +108,8 @@ private:
KItemListStyleOption m_styleOption;
Qt::Orientation m_scrollOrientation;
- QPixmap* m_leftBorderCache;
- QPixmap* m_rightBorderCache;
- QColor m_outlineColor;
+ QColor m_roleColor;
+ QRectF m_roleBounds;
};
#endif
diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp
index 52d857705..a2252b918 100644
--- a/src/kitemviews/kitemlistview.cpp
+++ b/src/kitemviews/kitemlistview.cpp
@@ -55,6 +55,7 @@ KItemListView::KItemListView(QGraphicsWidget* parent) :
m_enabledSelectionToggles(false),
m_grouped(false),
m_activeTransactions(0),
+ m_endTransactionAnimationHint(Animation),
m_itemSize(),
m_controller(0),
m_model(0),
@@ -125,6 +126,8 @@ void KItemListView::setScrollOrientation(Qt::Orientation orientation)
it.next();
it.value()->setScrollOrientation(orientation);
}
+ updateGroupHeaderHeight();
+
}
doLayout(NoAnimation);
@@ -331,14 +334,19 @@ void KItemListView::setStyleOption(const KItemListStyleOption& option)
const KItemListStyleOption previousOption = m_styleOption;
m_styleOption = option;
+ if (m_grouped) {
+ updateGroupHeaderHeight();
+ }
+
QHashIterator<int, KItemListWidget*> it(m_visibleItems);
while (it.hasNext()) {
it.next();
it.value()->setStyleOption(option);
}
- m_sizeHintResolver->clearCache();
+ m_sizeHintResolver->clearCache();
doLayout(Animation);
+
onStyleOptionChanged(option, previousOption);
}
@@ -548,7 +556,8 @@ void KItemListView::endTransaction()
if (m_activeTransactions == 0) {
onTransactionEnd();
- doLayout(NoAnimation);
+ doLayout(m_endTransactionAnimationHint);
+ m_endTransactionAnimationHint = Animation;
}
}
@@ -557,7 +566,6 @@ bool KItemListView::isTransactionActive() const
return m_activeTransactions > 0;
}
-
void KItemListView::setHeaderShown(bool show)
{
@@ -893,7 +901,7 @@ void KItemListView::slotItemsRemoved(const KItemRangeList& itemRanges)
// geometry update if necessary.
const int activeTransactions = m_activeTransactions;
m_activeTransactions = 0;
- doLayout(animateChangedItemCount(count) ? Animation : NoAnimation, index, -count);
+ doLayout(animateChangedItemCount(count) ? Animation : NoAnimation, index, -count);
m_activeTransactions = activeTransactions;
}
}
@@ -978,12 +986,7 @@ void KItemListView::slotGroupedSortingChanged(bool current)
m_layouter->markAsDirty();
if (m_grouped) {
- // Apply the height of the header to the layouter
- const qreal groupHeaderHeight = m_styleOption.fontMetrics.height() +
- m_styleOption.margin * 2;
- m_layouter->setGroupHeaderHeight(groupHeaderHeight);
-
- updateVisibleGroupHeaders();
+ updateGroupHeaderHeight();
} else {
// Clear all visible headers
QMutableHashIterator<KItemListWidget*, KItemListGroupHeader*> it (m_visibleGroups);
@@ -1287,7 +1290,16 @@ void KItemListView::doLayout(LayoutAnimationHint hint, int changedIndex, int cha
m_layoutTimer->stop();
}
- if (!m_model || m_model->count() < 0 || m_activeTransactions > 0) {
+ if (m_activeTransactions > 0) {
+ if (hint == NoAnimation) {
+ // As soon as at least one property change should be done without animation,
+ // the whole transaction will be marked as not animated.
+ m_endTransactionAnimationHint = NoAnimation;
+ }
+ return;
+ }
+
+ if (!m_model || m_model->count() < 0) {
return;
}
@@ -1608,13 +1620,13 @@ void KItemListView::updateGroupHeaderForWidget(KItemListWidget* widget)
return;
}
- KItemListGroupHeader* header = m_visibleGroups.value(widget);
- if (!header) {
- header = m_groupHeaderCreator->create(this);
- header->setParentItem(widget);
- m_visibleGroups.insert(widget, header);
+ KItemListGroupHeader* groupHeader = m_visibleGroups.value(widget);
+ if (!groupHeader) {
+ groupHeader = m_groupHeaderCreator->create(this);
+ groupHeader->setParentItem(widget);
+ m_visibleGroups.insert(widget, groupHeader);
}
- Q_ASSERT(header->parentItem() == widget);
+ Q_ASSERT(groupHeader->parentItem() == widget);
// Determine the shown data for the header by doing a binary
// search in the groups-list
@@ -1630,18 +1642,18 @@ void KItemListView::updateGroupHeaderForWidget(KItemListWidget* widget)
}
} while (groups.at(mid).first != index && min <= max);
- header->setData(groups.at(mid).second);
- header->setRole(model()->sortRole());
- header->setStyleOption(m_styleOption);
- header->setScrollOrientation(scrollOrientation());
+ groupHeader->setData(groups.at(mid).second);
+ groupHeader->setRole(model()->sortRole());
+ groupHeader->setStyleOption(m_styleOption);
+ groupHeader->setScrollOrientation(scrollOrientation());
- header->show();
+ groupHeader->show();
}
void KItemListView::updateGroupHeaderLayout(KItemListWidget* widget)
{
- KItemListGroupHeader* header = m_visibleGroups.value(widget);
- Q_ASSERT(header);
+ KItemListGroupHeader* groupHeader = m_visibleGroups.value(widget);
+ Q_ASSERT(groupHeader);
const int index = widget->index();
const QRectF groupHeaderRect = m_layouter->groupHeaderRect(index);
@@ -1651,8 +1663,8 @@ void KItemListView::updateGroupHeaderLayout(KItemListWidget* widget)
// group header position to the relative position.
const QPointF groupHeaderPos(groupHeaderRect.x() - itemRect.x(),
- groupHeaderRect.height());
- header->setPos(groupHeaderPos);
- header->resize(groupHeaderRect.size());
+ groupHeader->setPos(groupHeaderPos);
+ groupHeader->resize(groupHeaderRect.size());
}
void KItemListView::recycleGroupHeaderForWidget(KItemListWidget* widget)
@@ -1893,6 +1905,16 @@ bool KItemListView::scrollBarRequired(const QSizeF& size) const
: maxOffset > size.width();
}
+void KItemListView::updateGroupHeaderHeight()
+{
+ qreal groupHeaderHeight = m_styleOption.fontMetrics.height();
+ groupHeaderHeight += (scrollOrientation() == Qt::Vertical)
+ ? m_styleOption.margin * 4 : m_styleOption.margin * 2;
+ m_layouter->setGroupHeaderHeight(groupHeaderHeight);
+
+ updateVisibleGroupHeaders();
+}
+
int KItemListView::calculateAutoScrollingIncrement(int pos, int range, int oldInc)
{
int inc = 0;
diff --git a/src/kitemviews/kitemlistview.h b/src/kitemviews/kitemlistview.h
index e675df221..50d8908e5 100644
--- a/src/kitemviews/kitemlistview.h
+++ b/src/kitemviews/kitemlistview.h
@@ -202,8 +202,20 @@ public:
*/
void scrollToItem(int index);
+ /**
+ * If several properties of KItemListView are changed synchronously, it is
+ * recommended to encapsulate the calls between beginTransaction() and endTransaction().
+ * This prevents unnecessary and expensive layout-calculations.
+ */
void beginTransaction();
+
+ /**
+ * Counterpart to beginTransaction(). The layout changes will only be animated if
+ * all property changes between beginTransaction() and endTransaction() support
+ * animations.
+ */
void endTransaction();
+
bool isTransactionActive() const;
/**
@@ -469,6 +481,12 @@ private:
bool scrollBarRequired(const QSizeF& size) const;
/**
+ * Applies the height of the group header to the layouter. The height
+ * depends on the used scroll orientation.
+ */
+ void updateGroupHeaderHeight();
+
+ /**
* Helper function for triggerAutoScrolling().
* @param pos Logical position of the mouse relative to the range.
* @param range Range of the visible area.
@@ -484,6 +502,7 @@ private:
bool m_enabledSelectionToggles;
bool m_grouped;
int m_activeTransactions; // Counter for beginTransaction()/endTransaction()
+ LayoutAnimationHint m_endTransactionAnimationHint;
QSizeF m_itemSize;
KItemListController* m_controller;
diff --git a/src/kitemviews/kitemlistviewlayouter.cpp b/src/kitemviews/kitemlistviewlayouter.cpp
index 60822adc7..4e7a91087 100644
--- a/src/kitemviews/kitemlistviewlayouter.cpp
+++ b/src/kitemviews/kitemlistviewlayouter.cpp
@@ -221,6 +221,8 @@ QRectF KItemListViewLayouter::itemRect(int index) const
QRectF KItemListViewLayouter::groupHeaderRect(int index) const
{
+ const_cast<KItemListViewLayouter*>(this)->doLayout();
+
const QRectF firstItemRect = itemRect(index);
QPointF pos = firstItemRect.topLeft();
if (pos.isNull()) {
diff --git a/src/views/dolphinitemlistcontainer.cpp b/src/views/dolphinitemlistcontainer.cpp
index 4f7a0e06b..65f69d963 100644
--- a/src/views/dolphinitemlistcontainer.cpp
+++ b/src/views/dolphinitemlistcontainer.cpp
@@ -242,8 +242,10 @@ void DolphinItemListContainer::updateGridSize()
// Apply the calculated values
styleOption.margin = innerMargin;
styleOption.iconSize = iconSize;
+ m_fileItemListView->beginTransaction();
m_fileItemListView->setStyleOption(styleOption);
m_fileItemListView->setItemSize(QSizeF(itemWidth, itemHeight));
+ m_fileItemListView->endTransaction();
}
void DolphinItemListContainer::updateFont()